NumCpp  2.7.0
A Templatized Header Only C++ Implementation of the Python NumPy Library
NdArrayCore.hpp
Go to the documentation of this file.
1 #pragma once
29 
39 #include "NumCpp/Core/Shape.hpp"
40 #include "NumCpp/Core/Slice.hpp"
41 #include "NumCpp/Core/Types.hpp"
43 #include "NumCpp/Utils/num2str.hpp"
44 #include "NumCpp/Utils/power.hpp"
45 #include "NumCpp/Utils/sqr.hpp"
47 
48 #include <array>
49 #include <cmath>
50 #include <deque>
51 #include <forward_list>
52 #include <fstream>
53 #include <initializer_list>
54 #include <iostream>
55 #include <iterator>
56 #include <list>
57 #include <memory>
58 #include <numeric>
59 #include <set>
60 #include <string>
61 #include <type_traits>
62 #include <utility>
63 #include <vector>
64 
65 namespace nc
66 {
67  //================================================================================
68  // Class Description:
70  template<typename dtype, class Allocator = std::allocator<dtype>>
71  class NdArray
72  {
73  private:
74  STATIC_ASSERT_VALID_DTYPE(dtype);
75  static_assert(is_same_v<dtype, typename Allocator::value_type>, "value_type and Allocator::value_type must match");
76 
77  using AllocType = typename std::allocator_traits<Allocator>::template rebind_alloc<dtype>;
78  using AllocTraits = std::allocator_traits<AllocType>;
79 
80  public:
81  using value_type = dtype;
82  using allocator_type = Allocator;
83  using pointer = typename AllocTraits::pointer;
84  using const_pointer = typename AllocTraits::const_pointer;
85  using reference = dtype&;
86  using const_reference = const dtype&;
87  using size_type = uint32;
88  using difference_type = typename AllocTraits::difference_type;
89 
92  using reverse_iterator = std::reverse_iterator<iterator>;
93  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
94 
97  using reverse_column_iterator = std::reverse_iterator<column_iterator>;
98  using const_reverse_column_iterator = std::reverse_iterator<const_column_iterator>;
99 
100  //============================================================================
101  // Method Description:
104  NdArray() = default;
105 
106  //============================================================================
107  // Method Description:
112  explicit NdArray(size_type inSquareSize) :
113  shape_(inSquareSize, inSquareSize),
114  size_(inSquareSize * inSquareSize)
115  {
116  newArray();
117  }
118 
119  //============================================================================
120  // Method Description:
126  NdArray(size_type inNumRows, size_type inNumCols) :
127  shape_(inNumRows, inNumCols),
128  size_(inNumRows * inNumCols)
129  {
130  newArray();
131  }
132 
133  //============================================================================
134  // Method Description:
139  explicit NdArray(const Shape& inShape) :
140  shape_(inShape),
141  size_(shape_.size())
142  {
143  newArray();
144  }
145 
146  //============================================================================
147  // Method Description:
152  NdArray(std::initializer_list<dtype> inList) :
153  shape_(1, static_cast<uint32>(inList.size())),
154  size_(shape_.size())
155  {
156  newArray();
157  if (size_ > 0)
158  {
159  stl_algorithms::copy(inList.begin(), inList.end(), begin());
160  }
161  }
162 
163  //============================================================================
164  // Method Description:
169  NdArray(const std::initializer_list<std::initializer_list<dtype> >& inList) :
170  shape_(static_cast<uint32>(inList.size()), 0)
171  {
172  for (const auto& list : inList)
173  {
174  if (shape_.cols == 0)
175  {
176  shape_.cols = static_cast<uint32>(list.size());
177  }
178  else if (list.size() != shape_.cols)
179  {
180  THROW_INVALID_ARGUMENT_ERROR("All rows of the initializer list needs to have the same number of elements");
181  }
182  }
183 
184  size_ = shape_.size();
185  newArray();
186  uint32 row = 0;
187  for (const auto& list : inList)
188  {
189  const auto ptr = begin() += row * shape_.cols;
190  stl_algorithms::copy(list.begin(), list.end(), ptr);
191  ++row;
192  }
193  }
194 
195  //============================================================================
196  // Method Description:
203  template<size_t ArraySize,
204  std::enable_if_t<is_valid_dtype_v<dtype>, int> = 0>
205  NdArray(std::array<dtype, ArraySize>& inArray, bool copy = true) :
206  shape_(1, static_cast<uint32>(ArraySize)),
207  size_(shape_.size())
208  {
209  if (copy)
210  {
211  newArray();
212  if (size_ > 0)
213  {
214  stl_algorithms::copy(inArray.begin(), inArray.end(), begin());
215  }
216  }
217  else
218  {
219  array_ = inArray.data();
220  ownsPtr_ = false;
221  }
222  }
223 
224  //============================================================================
225  // Method Description:
232  template<size_t Dim0Size, size_t Dim1Size>
233  NdArray(std::array<std::array<dtype, Dim1Size>, Dim0Size>& in2dArray, bool copy = true) :
234  shape_(static_cast<uint32>(Dim0Size), static_cast<uint32>(Dim1Size)),
235  size_(shape_.size())
236  {
237  if (copy)
238  {
239  newArray();
240  if (size_ > 0)
241  {
242  const auto start = in2dArray.front().begin();
243  stl_algorithms::copy(start, start + size_, begin());
244  }
245  }
246  else
247  {
248  array_ = in2dArray.front().data();
249  ownsPtr_ = false;
250  }
251  }
252 
253  //============================================================================
254  // Method Description:
261  template<std::enable_if_t<is_valid_dtype_v<dtype>, int> = 0>
262  NdArray(std::vector<dtype>& inVector, bool copy = true) :
263  shape_(1, static_cast<uint32>(inVector.size())),
264  size_(shape_.size())
265  {
266  if (copy)
267  {
268  newArray();
269  if (size_ > 0)
270  {
271  stl_algorithms::copy(inVector.begin(), inVector.end(), begin());
272  }
273  }
274  else
275  {
276  array_ = inVector.data();
277  ownsPtr_ = false;
278  }
279  }
280 
281  //============================================================================
282  // Method Description:
287  explicit NdArray(const std::vector<std::vector<dtype>>& in2dVector) :
288  shape_(static_cast<uint32>(in2dVector.size()), 0)
289  {
290  for (const auto& row : in2dVector)
291  {
292  if (shape_.cols == 0)
293  {
294  shape_.cols = static_cast<uint32>(row.size());
295  }
296  else if (row.size() != shape_.cols)
297  {
298  THROW_INVALID_ARGUMENT_ERROR("All rows of the 2d vector need to have the same number of elements");
299  }
300  }
301 
302  size_ = shape_.size();
303 
304  newArray();
305  auto currentPosition = begin();
306  for (const auto& row : in2dVector)
307  {
308  stl_algorithms::copy(row.begin(), row.end(), currentPosition);
309  currentPosition += shape_.cols;
310  }
311  }
312 
313  //============================================================================
314  // Method Description:
321  template<size_t Dim1Size>
322  NdArray(std::vector<std::array<dtype, Dim1Size>>& in2dArray, bool copy = true) :
323  shape_(static_cast<uint32>(in2dArray.size()), static_cast<uint32>(Dim1Size)),
324  size_(shape_.size())
325  {
326  if (copy)
327  {
328  newArray();
329  if (size_ > 0)
330  {
331  const auto start = in2dArray.front().begin();
332  stl_algorithms::copy(start, start + size_, begin());
333  }
334  }
335  else
336  {
337  array_ = in2dArray.front().data();
338  ownsPtr_ = false;
339  }
340  }
341 
342  //============================================================================
343  // Method Description:
348  template<std::enable_if_t<is_valid_dtype_v<dtype>, int> = 0>
349  explicit NdArray(const std::deque<dtype>& inDeque) :
350  shape_(1, static_cast<uint32>(inDeque.size())),
351  size_(shape_.size())
352  {
353  newArray();
354  if (size_ > 0)
355  {
356  stl_algorithms::copy(inDeque.begin(), inDeque.end(), begin());
357  }
358  }
359 
360  //============================================================================
361  // Method Description:
366  explicit NdArray(const std::deque<std::deque<dtype>>& in2dDeque) :
367  shape_(static_cast<uint32>(in2dDeque.size()), 0)
368  {
369  for (const auto& row : in2dDeque)
370  {
371  if (shape_.cols == 0)
372  {
373  shape_.cols = static_cast<uint32>(row.size());
374  }
375  else if (row.size() != shape_.cols)
376  {
377  THROW_INVALID_ARGUMENT_ERROR("All rows of the 2d vector need to have the same number of elements");
378  }
379  }
380 
381  size_ = shape_.size();
382 
383  newArray();
384  auto currentPosition = begin();
385  for (const auto& row : in2dDeque)
386  {
387  stl_algorithms::copy(row.begin(), row.end(), currentPosition);
388  currentPosition += shape_.cols;
389  }
390  }
391 
392  //============================================================================
393  // Method Description:
398  explicit NdArray(const std::list<dtype>& inList) :
399  shape_(1, static_cast<uint32>(inList.size())),
400  size_(shape_.size())
401  {
402  newArray();
403  if (size_ > 0)
404  {
405  stl_algorithms::copy(inList.begin(), inList.end(), begin());
406  }
407  }
408 
409  //============================================================================
410  // Method Description:
416  template<typename Iterator,
417  std::enable_if_t<is_same_v<typename std::iterator_traits<Iterator>::value_type, dtype>, int> = 0>
418  NdArray(Iterator inFirst, Iterator inLast) :
419  shape_(1, static_cast<uint32>(std::distance(inFirst, inLast))),
420  size_(shape_.size())
421  {
422  newArray();
423  if (size_ > 0)
424  {
425  stl_algorithms::copy(inFirst, inLast, begin());
426  }
427  }
428 
429  //============================================================================
430  // Method Description:
438  shape_(1, size),
439  size_(size)
440  {
441  newArray();
442  if (inPtr != nullptr && size_ > 0)
443  {
444  stl_algorithms::copy(inPtr, inPtr + size_, begin());
445  }
446  }
447 
448  //============================================================================
449  // Method Description:
457  template<typename UIntType1, typename UIntType2,
458  std::enable_if_t<!is_same_v<UIntType1, bool>, int> = 0,
459  std::enable_if_t<!is_same_v<UIntType2, bool>, int> = 0>
460  NdArray(const_pointer inPtr, UIntType1 numRows, UIntType2 numCols) :
461  shape_(numRows, numCols),
462  size_(shape_.size())
463  {
464  newArray();
465  if (inPtr != nullptr && size_ > 0)
466  {
467  stl_algorithms::copy(inPtr, inPtr + size_, begin());
468  }
469  }
470 
471  //============================================================================
472  // Method Description:
481  template<typename Bool,
482  std::enable_if_t<is_same_v<Bool, bool>, int> = 0>
483  NdArray(pointer inPtr, size_type size, Bool takeOwnership) noexcept :
484  shape_(1, size),
485  size_(size),
486  array_(inPtr),
487  ownsPtr_(takeOwnership)
488  {}
489 
490  //============================================================================
491  // Method Description:
501  template<typename Bool,
502  std::enable_if_t<is_same_v<Bool, bool>, int> = 0>
503  NdArray(pointer inPtr, uint32 numRows, uint32 numCols, Bool takeOwnership) noexcept :
504  shape_(numRows, numCols),
505  size_(numRows * numCols),
506  array_(inPtr),
507  ownsPtr_(takeOwnership)
508  {}
509 
510  //============================================================================
511  // Method Description:
516  NdArray(const NdArray<dtype>& inOtherArray) :
517  shape_(inOtherArray.shape_),
518  size_(inOtherArray.size_),
519  endianess_(inOtherArray.endianess_)
520  {
521  newArray();
522  if (size_ > 0)
523  {
524  stl_algorithms::copy(inOtherArray.cbegin(), inOtherArray.cend(), begin());
525  }
526  }
527 
528  //============================================================================
529  // Method Description:
534  NdArray(NdArray<dtype>&& inOtherArray) noexcept :
535  shape_(inOtherArray.shape_),
536  size_(inOtherArray.size_),
537  endianess_(inOtherArray.endianess_),
538  array_(inOtherArray.array_),
539  ownsPtr_(inOtherArray.ownsPtr_)
540  {
541  inOtherArray.shape_.rows = inOtherArray.shape_.cols = 0;
542  inOtherArray.size_ = 0;
543  inOtherArray.ownsPtr_ = false;
544  inOtherArray.array_ = nullptr;
545  }
546 
547  //============================================================================
548  // Method Description:
551  ~NdArray() noexcept
552  {
553  deleteArray();
554  }
555 
556  //============================================================================
557  // Method Description:
564  {
565  if (&rhs != this)
566  {
567  if (rhs.size_ > 0)
568  {
569  newArray(rhs.shape_);
570  endianess_ = rhs.endianess_;
571 
572  stl_algorithms::copy(rhs.cbegin(), rhs.cend(), begin());
573  }
574  }
575 
576  return *this;
577  }
578 
579  //============================================================================
580  // Method Description:
588  {
589  if (array_ != nullptr)
590  {
591  stl_algorithms::fill(begin(), end(), inValue);
592  }
593 
594  return *this;
595  }
596 
597  //============================================================================
598  // Method Description:
605  {
606  if (&rhs != this)
607  {
608  deleteArray();
609  shape_ = rhs.shape_;
610  size_ = rhs.size_;
611  endianess_ = rhs.endianess_;
612  array_ = rhs.array_;
613  ownsPtr_ = rhs.ownsPtr_;
614 
615  rhs.shape_.rows = rhs.shape_.cols = rhs.size_ = 0;
616  rhs.array_ = nullptr;
617  rhs.ownsPtr_ = false;
618  }
619 
620  return *this;
621  }
622 
623  //============================================================================
624  // Method Description:
630  reference operator[](int32 inIndex) noexcept
631  {
632  if (inIndex < 0)
633  {
634  inIndex += size_;
635  }
636 
637  return array_[inIndex];
638  }
639 
640  //============================================================================
641  // Method Description:
647  const_reference operator[](int32 inIndex) const noexcept
648  {
649  if (inIndex < 0)
650  {
651  inIndex += size_;
652  }
653 
654  return array_[inIndex];
655  }
656 
657  //============================================================================
658  // Method Description:
665  reference operator()(int32 inRowIndex, int32 inColIndex) noexcept
666  {
667  if (inRowIndex < 0)
668  {
669  inRowIndex += shape_.rows;
670  }
671 
672  if (inColIndex < 0)
673  {
674  inColIndex += shape_.cols;
675  }
676 
677  return array_[inRowIndex * shape_.cols + inColIndex];
678  }
679 
680  //============================================================================
681  // Method Description:
688  const_reference operator()(int32 inRowIndex, int32 inColIndex) const noexcept
689  {
690  if (inRowIndex < 0)
691  {
692  inRowIndex += shape_.rows;
693  }
694 
695  if (inColIndex < 0)
696  {
697  inColIndex += shape_.cols;
698  }
699 
700  return array_[inRowIndex * shape_.cols + inColIndex];
701  }
702 
703  //============================================================================
704  // Method Description:
711  NdArray<dtype> operator[](const Slice& inSlice) const
712  {
713  Slice inSliceCopy(inSlice);
714 
715  uint32 counter = 0;
716  NdArray<dtype> returnArray(1, inSliceCopy.numElements(size_));
717  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
718  {
719  returnArray[counter++] = at(i);
720  }
721 
722  return returnArray;
723  }
724 
725  //============================================================================
726  // Method Description:
733  {
734  if (inMask.shape() != shape_)
735  {
736  THROW_INVALID_ARGUMENT_ERROR("input inMask must have the same shape as the NdArray it will be masking.");
737  }
738 
739  auto indices = inMask.flatnonzero();
740  auto outArray = NdArray<dtype>(1, indices.size());
741  for (size_type i = 0; i < indices.size(); ++i)
742  {
743  outArray[i] = operator[](indices[i]);
744  }
745 
746  return outArray;
747  }
748 
749  //============================================================================
750  // Method Description:
757  template<typename Indices,
759  NdArray<dtype> operator[](const Indices& inIndices) const
760  {
761  if (inIndices.max().item() > size_ - 1)
762  {
763  THROW_INVALID_ARGUMENT_ERROR("input indices must be less than the array size.");
764  }
765 
766  auto outArray = NdArray<dtype>(1, static_cast<size_type>(inIndices.size()));
767  size_type i = 0;
768  for (auto& index : inIndices)
769  {
770  outArray[i++] = operator[](index);
771  }
772 
773  return outArray;
774  }
775 
776  //============================================================================
777  // Method Description:
785  NdArray<dtype> operator()(Slice inRowSlice, Slice inColSlice) const
786  {
787  NdArray<dtype> returnArray(inRowSlice.numElements(shape_.rows), inColSlice.numElements(shape_.cols));
788 
789  uint32 rowCounter = 0;
790  uint32 colCounter = 0;
791  for (int32 row = inRowSlice.start; row < inRowSlice.stop; row += inRowSlice.step)
792  {
793  for (int32 col = inColSlice.start; col < inColSlice.stop; col += inColSlice.step)
794  {
795  returnArray(rowCounter, colCounter++) = at(row, col);
796  }
797  colCounter = 0;
798  ++rowCounter;
799  }
800 
801  return returnArray;
802  }
803 
804  //============================================================================
805  // Method Description:
813  NdArray<dtype> operator()(Slice inRowSlice, int32 inColIndex) const
814  {
815  NdArray<dtype> returnArray(inRowSlice.numElements(shape_.rows), 1);
816 
817  uint32 rowCounter = 0;
818  for (int32 row = inRowSlice.start; row < inRowSlice.stop; row += inRowSlice.step)
819  {
820  returnArray(rowCounter++, 0) = at(row, inColIndex);
821  }
822 
823  return returnArray;
824  }
825 
826  //============================================================================
827  // Method Description:
835  NdArray<dtype> operator()(int32 inRowIndex, Slice inColSlice) const
836  {
837  NdArray<dtype> returnArray(1, inColSlice.numElements(shape_.cols));
838 
839  uint32 colCounter = 0;
840  for (int32 col = inColSlice.start; col < inColSlice.stop; col += inColSlice.step)
841  {
842  returnArray(0, colCounter++) = at(inRowIndex, col);
843  }
844 
845  return returnArray;
846  }
847 
848  //============================================================================
849  // Method Description:
857  template<typename Indices,
858  enable_if_t<is_same_v<Indices, NdArray<int32>> || is_same_v<Indices, NdArray<uint32>>, int> = 0>
859  NdArray<dtype> operator()(const Indices& rowIndices, int32 colIndex) const
860  {
861  const NdArray<int32> colIndices = { colIndex };
862  return operator()(rowIndices, colIndices);
863  }
864 
865  //============================================================================
866  // Method Description:
874  template<typename Indices,
875  enable_if_t<is_same_v<Indices, NdArray<int32>> || is_same_v<Indices, NdArray<uint32>>, int> = 0>
876  NdArray<dtype> operator()(const Indices& rowIndices, Slice colSlice) const
877  {
878  return operator()(rowIndices, toIndices(colSlice, Axis::COL));
879  }
880 
881  //============================================================================
882  // Method Description:
890  template<typename Indices,
891  enable_if_t<is_same_v<Indices, NdArray<int32>> || is_same_v<Indices, NdArray<uint32>>, int> = 0>
892  NdArray<dtype> operator()(int32 rowIndex, const Indices& colIndices) const
893  {
894  const NdArray<int32> rowIndices = { rowIndex };
895  return operator()(rowIndices, colIndices);
896  }
897 
898  //============================================================================
899  // Method Description:
907  template<typename Indices,
908  enable_if_t<is_same_v<Indices, NdArray<int32>> || is_same_v<Indices, NdArray<uint32>>, int> = 0>
909  NdArray<dtype> operator()(Slice rowSlice, const Indices& colIndices) const
910  {
911  return operator()(toIndices(rowSlice, Axis::ROW), colIndices);
912  }
913 
914  //============================================================================
915  // Method Description:
923  template<typename RowIndices, typename ColIndices,
924  enable_if_t<is_same_v<RowIndices, NdArray<int32>> || is_same_v<RowIndices, NdArray<uint32>>, int> = 0,
925  enable_if_t<is_same_v<ColIndices, NdArray<int32>> || is_same_v<ColIndices, NdArray<uint32>>, int> = 0>
926  NdArray<dtype> operator()(RowIndices rowIndices, ColIndices colIndices) const
927  {
928  rowIndices.sort();
929  colIndices.sort();
930 
931  std::vector<int32> rowIndicesUnique(rowIndices.size());
932  std::vector<int32> colIndicesUnique(colIndices.size());
933 
934  const auto lastRow = stl_algorithms::unique_copy(rowIndices.begin(), rowIndices.end(), rowIndicesUnique.begin());
935  const auto lastCol = stl_algorithms::unique_copy(colIndices.begin(), colIndices.end(), colIndicesUnique.begin());
936 
937  NdArray<dtype> returnArray(static_cast<uint32>(lastRow - rowIndicesUnique.begin()),
938  static_cast<uint32>(lastCol - colIndicesUnique.begin()));
939 
940  uint32 rowCounter = 0;
941  for (auto rowIter = rowIndicesUnique.begin(); rowIter != lastRow; ++rowIter)
942  {
943  uint32 colCounter = 0;
944  for (auto colIter = colIndicesUnique.begin(); colIter != lastCol; ++colIter)
945  {
946  returnArray(rowCounter, colCounter++) = at(*rowIter, *colIter);
947  }
948 
949  ++rowCounter;
950  }
951 
952  return returnArray;
953  }
954 
955  //============================================================================
956  // Method Description:
964  Slice cSlice(int32 inStartIdx = 0, uint32 inStepSize = 1) const noexcept
965  {
966  return Slice(inStartIdx, shape_.cols, inStepSize);
967  }
968 
969  //============================================================================
970  // Method Description:
978  Slice rSlice(int32 inStartIdx = 0, uint32 inStepSize = 1) const noexcept
979  {
980  return Slice(inStartIdx, shape_.rows, inStepSize);
981  }
982 
983  //============================================================================
984  // Method Description:
990  reference at(int32 inIndex)
991  {
992  // this doesn't allow for calling the first element as -size_...
993  // but why would you really want to do that anyway?
994  if (std::abs(inIndex) > static_cast<int64>(size_ - 1))
995  {
996  std::string errStr = "Input index " + utils::num2str(inIndex);
997  errStr += " is out of bounds for array of size " + utils::num2str(size_) + ".";
999  }
1000 
1001  return operator[](inIndex);
1002  }
1003 
1004  //============================================================================
1005  // Method Description:
1011  const_reference at(int32 inIndex) const
1012  {
1013  // this doesn't allow for calling the first element as -size_...
1014  // but why would you really want to do that anyway?
1015  if (std::abs(inIndex) > static_cast<int64>(size_ - 1))
1016  {
1017  std::string errStr = "Input index " + utils::num2str(inIndex);
1018  errStr += " is out of bounds for array of size " + utils::num2str(size_) + ".";
1020  }
1021 
1022  return operator[](inIndex);
1023  }
1024 
1025  //============================================================================
1026  // Method Description:
1033  reference at(int32 inRowIndex, int32 inColIndex)
1034  {
1035  // this doesn't allow for calling the first element as -size_...
1036  // but why would you really want to do that anyway?
1037  if (std::abs(inRowIndex) > static_cast<int32>(shape_.rows - 1))
1038  {
1039  std::string errStr = "Row index " + utils::num2str(inRowIndex);
1040  errStr += " is out of bounds for array of size " + utils::num2str(shape_.rows) + ".";
1042  }
1043 
1044  // this doesn't allow for calling the first element as -size_...
1045  // but why would you really want to that anyway?
1046  if (std::abs(inColIndex) > static_cast<int32>(shape_.cols - 1))
1047  {
1048  std::string errStr = "Column index " + utils::num2str(inColIndex);
1049  errStr += " is out of bounds for array of size " + utils::num2str(shape_.cols) + ".";
1051  }
1052 
1053  return operator()(inRowIndex, inColIndex);
1054  }
1055 
1056  //============================================================================
1057  // Method Description:
1064  const_reference at(int32 inRowIndex, int32 inColIndex) const
1065  {
1066  // this doesn't allow for calling the first element as -size_...
1067  // but why would you really want to do that anyway?
1068  if (std::abs(inRowIndex) > static_cast<int32>(shape_.rows - 1))
1069  {
1070  std::string errStr = "Row index " + utils::num2str(inRowIndex);
1071  errStr += " is out of bounds for array of size " + utils::num2str(shape_.rows) + ".";
1073  }
1074 
1075  // this doesn't allow for calling the first element as -size_...
1076  // but why would you really want to do that anyway?
1077  if (std::abs(inColIndex) > static_cast<int32>(shape_.cols - 1))
1078  {
1079  std::string errStr = "Column index " + utils::num2str(inColIndex);
1080  errStr += " is out of bounds for array of size " + utils::num2str(shape_.cols) + ".";
1082  }
1083 
1084  return operator()(inRowIndex, inColIndex);
1085  }
1086 
1087  //============================================================================
1088  // Method Description:
1094  NdArray<dtype> at(const Slice& inSlice) const
1095  {
1096  // the slice operator already provides bounds checking. just including
1097  // the at method for completeness
1098  return operator[](inSlice);
1099  }
1100 
1101  //============================================================================
1102  // Method Description:
1109  NdArray<dtype> at(const Slice& inRowSlice, const Slice& inColSlice) const
1110  {
1111  // the slice operator already provides bounds checking. just including
1112  // the at method for completeness
1113  return operator()(inRowSlice, inColSlice);
1114  }
1115 
1116  //============================================================================
1117  // Method Description:
1124  NdArray<dtype> at(const Slice& inRowSlice, int32 inColIndex) const
1125  {
1126  // the slice operator already provides bounds checking. just including
1127  // the at method for completeness
1128  return operator()(inRowSlice, inColIndex);
1129  }
1130 
1131  //============================================================================
1132  // Method Description:
1139  NdArray<dtype> at(int32 inRowIndex, const Slice& inColSlice) const
1140  {
1141  // the slice operator already provides bounds checking. just including
1142  // the at method for completeness
1143  return operator()(inRowIndex, inColSlice);
1144  }
1145 
1146  //============================================================================
1147  // Method Description:
1154  NdArray<dtype> at(const NdArray<int32>& rowIndices, const NdArray<int32>& colIndices) const
1155  {
1156  // the slice operator already provides bounds checking. just including
1157  // the at method for completeness
1158  return operator()(rowIndices, colIndices);
1159  }
1160 
1161  //============================================================================
1162  // Method Description:
1166  iterator begin() noexcept
1167  {
1168  return iterator(array_);
1169  }
1170 
1171  //============================================================================
1172  // Method Description:
1179  {
1180  if (inRow >= shape_.rows)
1181  {
1182  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1183  }
1184 
1185  return begin() += (inRow * shape_.cols);
1186  }
1187 
1188  //============================================================================
1189  // Method Description:
1193  const_iterator begin() const noexcept
1194  {
1195  return cbegin();
1196  }
1197 
1198  //============================================================================
1199  // Method Description:
1206  {
1207  return cbegin(inRow);
1208  }
1209 
1210  //============================================================================
1211  // Method Description:
1216  const_iterator cbegin() const noexcept
1217  {
1218  return const_iterator(array_);
1219  }
1220 
1221  //============================================================================
1222  // Method Description:
1229  {
1230  if (inRow >= shape_.rows)
1231  {
1232  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1233  }
1234 
1235  return cbegin() += (inRow * shape_.cols);
1236  }
1237 
1238  //============================================================================
1239  // Method Description:
1244  {
1245  return column_iterator(array_, shape_.rows, shape_.cols);
1246  }
1247 
1248  //============================================================================
1249  // Method Description:
1256  {
1257  if (inCol >= shape_.cols)
1258  {
1259  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1260  }
1261 
1262  return colbegin() += (inCol * shape_.rows);
1263  }
1264 
1265  //============================================================================
1266  // Method Description:
1271  {
1272  return ccolbegin();
1273  }
1274 
1275  //============================================================================
1276  // Method Description:
1283  {
1284  return ccolbegin(inCol);
1285  }
1286 
1287  //============================================================================
1288  // Method Description:
1294  {
1295  return const_column_iterator(array_, shape_.rows, shape_.cols);
1296  }
1297 
1298  //============================================================================
1299  // Method Description:
1306  {
1307  if (inCol >= shape_.cols)
1308  {
1309  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1310  }
1311 
1312  return ccolbegin() += (inCol * shape_.rows);
1313  }
1314 
1315  //============================================================================
1316  // Method Description:
1321  {
1322  return reverse_iterator(end());
1323  }
1324 
1325  //============================================================================
1326  // Method Description:
1333  {
1334  if (inRow >= shape_.rows)
1335  {
1336  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1337  }
1338 
1339  return rbegin() += (shape_.rows - inRow - 1) * shape_.cols;
1340  }
1341 
1342  //============================================================================
1343  // Method Description:
1348  {
1349  return crbegin();
1350  }
1351 
1352  //============================================================================
1353  // Method Description:
1360  {
1361  return crbegin(inRow);
1362  }
1363 
1364  //============================================================================
1365  // Method Description:
1371  {
1372  return const_reverse_iterator(cend());
1373  }
1374 
1375  //============================================================================
1376  // Method Description:
1383  {
1384  if (inRow >= shape_.rows)
1385  {
1386  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1387  }
1388 
1389  return crbegin() += (shape_.rows - inRow - 1) * shape_.cols;
1390  }
1391 
1392  //============================================================================
1393  // Method Description:
1398  {
1399  return reverse_column_iterator(colend());
1400  }
1401 
1402  //============================================================================
1403  // Method Description:
1410  {
1411  if (inCol >= shape_.cols)
1412  {
1413  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1414  }
1415 
1416  return rcolbegin() += (shape_.cols - inCol - 1) * shape_.rows;
1417  }
1418 
1419  //============================================================================
1420  // Method Description:
1425  {
1426  return crcolbegin();
1427  }
1428 
1429  //============================================================================
1430  // Method Description:
1437  {
1438  return crcolbegin(inCol);
1439  }
1440 
1441  //============================================================================
1442  // Method Description:
1448  {
1450  }
1451 
1452  //============================================================================
1453  // Method Description:
1460  {
1461  if (inCol >= shape_.cols)
1462  {
1463  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1464  }
1465 
1466  return crcolbegin() += (shape_.cols - inCol - 1) * shape_.rows;
1467  }
1468 
1469  //============================================================================
1470  // Method Description:
1474  iterator end() noexcept
1475  {
1476  return begin() += size_;
1477  }
1478 
1479  //============================================================================
1480  // Method Description:
1487  {
1488  if (inRow >= shape_.rows)
1489  {
1490  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1491  }
1492 
1493  return begin(inRow) += shape_.cols;
1494  }
1495 
1496  //============================================================================
1497  // Method Description:
1501  const_iterator end() const noexcept
1502  {
1503  return cend();
1504  }
1505 
1506  //============================================================================
1507  // Method Description:
1514  {
1515  return cend(inRow);
1516  }
1517 
1518  //============================================================================
1519  // Method Description:
1524  const_iterator cend() const noexcept
1525  {
1526  return cbegin() += size_;
1527  }
1528 
1529  //============================================================================
1530  // Method Description:
1537  {
1538  if (inRow >= shape_.rows)
1539  {
1540  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1541  }
1542 
1543  return cbegin(inRow) += shape_.cols;
1544  }
1545 
1546  //============================================================================
1547  // Method Description:
1552  {
1553  return rbegin() += size_;
1554  }
1555 
1556  //============================================================================
1557  // Method Description:
1564  {
1565  if (inRow >= shape_.rows)
1566  {
1567  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1568  }
1569 
1570  return rbegin(inRow) += shape_.cols;
1571  }
1572 
1573  //============================================================================
1574  // Method Description:
1578  const_reverse_iterator rend() const noexcept
1579  {
1580  return crend();
1581  }
1582 
1583  //============================================================================
1584  // Method Description:
1591  {
1592  return crend(inRow);
1593  }
1594 
1595  //============================================================================
1596  // Method Description:
1602  {
1603  return crbegin() += size_;
1604  }
1605 
1606  //============================================================================
1607  // Method Description:
1614  {
1615  if (inRow >= shape_.rows)
1616  {
1617  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1618  }
1619 
1620  return crbegin(inRow) += shape_.cols;
1621  }
1622 
1623  //============================================================================
1624  // Method Description:
1629  {
1630  return colbegin() += size_;
1631  }
1632 
1633  //============================================================================
1634  // Method Description:
1641  {
1642  if (inCol >= shape_.cols)
1643  {
1644  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1645  }
1646 
1647  return colbegin(inCol) += shape_.rows;
1648  }
1649 
1650  //============================================================================
1651  // Method Description:
1655  const_column_iterator colend() const noexcept
1656  {
1657  return ccolend();
1658  }
1659 
1660  //============================================================================
1661  // Method Description:
1668  {
1669  return ccolend(inCol);
1670  }
1671 
1672  //============================================================================
1673  // Method Description:
1678  const_column_iterator ccolend() const noexcept
1679  {
1680  return ccolbegin() += size_;
1681  }
1682 
1683  //============================================================================
1684  // Method Description:
1691  {
1692  if (inCol >= shape_.cols)
1693  {
1694  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1695  }
1696 
1697  return ccolbegin(inCol) += shape_.rows;
1698  }
1699 
1700  //============================================================================
1701  // Method Description:
1706  {
1707  return rcolbegin() += size_;
1708  }
1709 
1710  //============================================================================
1711  // Method Description:
1718  {
1719  if (inCol >= shape_.cols)
1720  {
1721  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1722  }
1723 
1724  return rcolbegin(inCol) += shape_.rows;
1725  }
1726 
1727  //============================================================================
1728  // Method Description:
1733  {
1734  return crcolend();
1735  }
1736 
1737  //============================================================================
1738  // Method Description:
1745  {
1746  return crcolend(inCol);
1747  }
1748 
1749  //============================================================================
1750  // Method Description:
1756  {
1757  return crcolbegin() += size_;
1758  }
1759 
1760  //============================================================================
1761  // Method Description:
1768  {
1769  if (inCol >= shape_.cols)
1770  {
1771  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1772  }
1773 
1774  return crcolbegin(inCol) += shape_.rows;
1775  }
1776 
1777  //============================================================================
1778  // Method Description:
1787  {
1789 
1790  const auto function = [](dtype i) -> bool
1791  {
1792  return i != dtype{ 0 };
1793  };
1794 
1795  switch (inAxis)
1796  {
1797  case Axis::NONE:
1798  {
1799  NdArray<bool> returnArray = { stl_algorithms::all_of(cbegin(), cend(), function) };
1800  return returnArray;
1801  }
1802  case Axis::COL:
1803  {
1804  NdArray<bool> returnArray(1, shape_.rows);
1805  for (uint32 row = 0; row < shape_.rows; ++row)
1806  {
1807  returnArray(0, row) = stl_algorithms::all_of(cbegin(row), cend(row), function);
1808  }
1809 
1810  return returnArray;
1811  }
1812  case Axis::ROW:
1813  {
1814  NdArray<dtype> arrayTransposed = transpose();
1815  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
1816  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1817  {
1818  returnArray(0, row) = stl_algorithms::all_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
1819  }
1820 
1821  return returnArray;
1822  }
1823  default:
1824  {
1825  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1826  return {}; // get rid of compiler warning
1827  }
1828  }
1829  }
1830 
1831  //============================================================================
1832  // Method Description:
1841  {
1843 
1844  const auto function = [](dtype i) -> bool
1845  {
1846  return i != dtype{ 0 };
1847  };
1848 
1849  switch (inAxis)
1850  {
1851  case Axis::NONE:
1852  {
1853  NdArray<bool> returnArray = { stl_algorithms::any_of(cbegin(), cend(), function) };
1854  return returnArray;
1855  }
1856  case Axis::COL:
1857  {
1858  NdArray<bool> returnArray(1, shape_.rows);
1859  for (uint32 row = 0; row < shape_.rows; ++row)
1860  {
1861  returnArray(0, row) = stl_algorithms::any_of(cbegin(row), cend(row), function);
1862  }
1863 
1864  return returnArray;
1865  }
1866  case Axis::ROW:
1867  {
1868  NdArray<dtype> arrayTransposed = transpose();
1869  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
1870  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1871  {
1872  returnArray(0, row) = stl_algorithms::any_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
1873  }
1874 
1875  return returnArray;
1876  }
1877  default:
1878  {
1879  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1880  return {}; // get rid of compiler warning
1881  }
1882  }
1883  }
1884 
1885  //============================================================================
1886  // Method Description:
1896  {
1898 
1899  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
1900  {
1901  return lhs < rhs;
1902  };
1903 
1904  switch (inAxis)
1905  {
1906  case Axis::NONE:
1907  {
1908  NdArray<uint32> returnArray = { static_cast<uint32>(stl_algorithms::max_element(cbegin(),
1909  cend(), comparitor) - cbegin()) };
1910  return returnArray;
1911  }
1912  case Axis::COL:
1913  {
1914  NdArray<uint32> returnArray(1, shape_.rows);
1915  for (uint32 row = 0; row < shape_.rows; ++row)
1916  {
1917  returnArray(0, row) = static_cast<uint32>(stl_algorithms::max_element(cbegin(row),
1918  cend(row), comparitor) - cbegin(row));
1919  }
1920 
1921  return returnArray;
1922  }
1923  case Axis::ROW:
1924  {
1925  NdArray<dtype> arrayTransposed = transpose();
1926  NdArray<uint32> returnArray(1, arrayTransposed.shape_.rows);
1927  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1928  {
1929  returnArray(0, row) = static_cast<uint32>(stl_algorithms::max_element(arrayTransposed.cbegin(row),
1930  arrayTransposed.cend(row), comparitor) - arrayTransposed.cbegin(row));
1931  }
1932 
1933  return returnArray;
1934  }
1935  default:
1936  {
1937  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1938  return {}; // get rid of compiler warning
1939  }
1940  }
1941  }
1942 
1943  //============================================================================
1944  // Method Description:
1954  {
1956 
1957  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
1958  {
1959  return lhs < rhs;
1960  };
1961 
1962  switch (inAxis)
1963  {
1964  case Axis::NONE:
1965  {
1966  NdArray<uint32> returnArray = { static_cast<uint32>(stl_algorithms::min_element(cbegin(),
1967  cend(), comparitor) - cbegin()) };
1968  return returnArray;
1969  }
1970  case Axis::COL:
1971  {
1972  NdArray<uint32> returnArray(1, shape_.rows);
1973  for (uint32 row = 0; row < shape_.rows; ++row)
1974  {
1975  returnArray(0, row) = static_cast<uint32>(stl_algorithms::min_element(cbegin(row),
1976  cend(row), comparitor) - cbegin(row));
1977  }
1978 
1979  return returnArray;
1980  }
1981  case Axis::ROW:
1982  {
1983  NdArray<dtype> arrayTransposed = transpose();
1984  NdArray<uint32> returnArray(1, arrayTransposed.shape_.rows);
1985  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1986  {
1987  returnArray(0, row) = static_cast<uint32>(stl_algorithms::min_element(arrayTransposed.cbegin(row),
1988  arrayTransposed.cend(row), comparitor) - arrayTransposed.cbegin(row));
1989  }
1990 
1991  return returnArray;
1992  }
1993  default:
1994  {
1995  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1996  return {}; // get rid of compiler warning
1997  }
1998  }
1999  }
2000 
2001  //============================================================================
2002  // Method Description:
2011  {
2013 
2014  switch (inAxis)
2015  {
2016  case Axis::NONE:
2017  {
2018  std::vector<uint32> idx(size_);
2019  std::iota(idx.begin(), idx.end(), 0);
2020 
2021  const auto function = [this](uint32 i1, uint32 i2) noexcept -> bool
2022  {
2023  return (*this)[i1] < (*this)[i2];
2024  };
2025 
2026  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2027  return NdArray<uint32>(idx);
2028  }
2029  case Axis::COL:
2030  {
2031  NdArray<uint32> returnArray(shape_);
2032  std::vector<uint32> idx(shape_.cols);
2033 
2034  for (uint32 row = 0; row < shape_.rows; ++row)
2035  {
2036  std::iota(idx.begin(), idx.end(), 0);
2037 
2038  const auto function = [this, row](uint32 i1, uint32 i2) noexcept -> bool
2039  {
2040  return operator()(row, i1) < operator()(row, i2);
2041  };
2042 
2043  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2044 
2045  for (uint32 col = 0; col < shape_.cols; ++col)
2046  {
2047  returnArray(row, col) = idx[col];
2048  }
2049  }
2050  return returnArray;
2051  }
2052  case Axis::ROW:
2053  {
2054  NdArray<dtype> arrayTransposed = transpose();
2055  NdArray<uint32> returnArray(shape_.cols, shape_.rows);
2056  std::vector<uint32> idx(arrayTransposed.shape_.cols);
2057 
2058  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
2059  {
2060  std::iota(idx.begin(), idx.end(), 0);
2061 
2062  const auto function = [&arrayTransposed, row](uint32 i1, uint32 i2) noexcept -> bool
2063  {
2064  return arrayTransposed(row, i1) < arrayTransposed(row, i2);
2065  };
2066 
2067  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2068 
2069  for (uint32 col = 0; col < arrayTransposed.shape_.cols; ++col)
2070  {
2071  returnArray(row, col) = idx[col];
2072  }
2073  }
2074  return returnArray.transpose();
2075  }
2076  default:
2077  {
2078  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2079  return {}; // get rid of compiler warning
2080  }
2081  }
2082  }
2083 
2084  //============================================================================
2085  // Method Description:
2093  template<typename dtypeOut, typename dtype_ = dtype,
2098  {
2099  NdArray<dtypeOut> outArray(shape_);
2100  stl_algorithms::transform(cbegin(), cend(), outArray.begin(),
2101  [](dtype value) -> dtypeOut
2102  {
2103  return static_cast<dtypeOut>(value);
2104  }
2105  );
2106 
2107  return outArray;
2108  }
2109 
2110  //============================================================================
2111  // Method Description:
2119  template<typename dtypeOut, typename dtype_ = dtype,
2124  {
2125  NdArray<dtypeOut> outArray(shape_);
2126 
2127  const auto function = [](const_reference value) -> dtypeOut
2128  {
2129  return std::complex<typename dtypeOut::value_type>(value);
2130  };
2131 
2132  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2133 
2134  return outArray;
2135  }
2136 
2137  //============================================================================
2138  // Method Description:
2146  template<typename dtypeOut, typename dtype_ = dtype,
2151  {
2152  NdArray<dtypeOut> outArray(shape_);
2153 
2154  if (is_same_v<dtypeOut, dtype>)
2155  {
2156  std::copy(cbegin(), cend(), outArray.begin());
2157  }
2158  else
2159  {
2160  const auto function = [](const_reference value) noexcept -> dtypeOut
2161  {
2162  return complex_cast<typename dtypeOut::value_type>(value);
2163  };
2164 
2165  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2166  }
2167 
2168  return outArray;
2169  }
2170 
2171  //============================================================================
2172  // Method Description:
2180  template<typename dtypeOut, typename dtype_ = dtype,
2185  {
2186  NdArray<dtypeOut> outArray(shape_);
2187 
2188  const auto function = [](const_reference value) -> dtypeOut
2189  {
2190  return static_cast<dtypeOut>(value.real());
2191  };
2192 
2193  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2194 
2195  return outArray;
2196  }
2197 
2198  //============================================================================
2199  // Method Description:
2204  const_reference back() const noexcept
2205  {
2206  return *(cend() - 1);
2207  }
2208 
2209  //============================================================================
2210  // Method Description:
2215  reference back() noexcept
2216  {
2217  return *(end() - 1);
2218  }
2219 
2220  //============================================================================
2221  // Method Description:
2227  {
2228  return *(cend(row) - 1);
2229  }
2230 
2231  //============================================================================
2232  // Method Description:
2238  {
2239  return *(end(row) - 1);
2240  }
2241 
2242  //============================================================================
2243  // Method Description:
2251  {
2252  STATIC_ASSERT_INTEGER(dtype);
2253 
2255  [](dtype& value) noexcept -> void
2256  {
2257  value = endian::byteSwap(value);
2258  }
2259  );
2260 
2261  switch (endianess_)
2262  {
2263  case Endian::NATIVE:
2264  {
2266  break;
2267  }
2268  case Endian::LITTLE:
2269  {
2270  endianess_ = Endian::BIG;
2271  break;
2272  }
2273  case Endian::BIG:
2274  {
2275  endianess_ = Endian::LITTLE;
2276  break;
2277  }
2278  }
2279 
2280  return *this;
2281  }
2282 
2283  //============================================================================
2284  // Method Description:
2294  {
2296 
2297  NdArray<dtype> outArray(shape_);
2298  stl_algorithms::transform(cbegin(), cend(), outArray.begin(),
2299  [inMin, inMax](dtype value) noexcept -> dtype
2300  {
2301 #ifdef __cpp_lib_clamp
2302  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
2303  {
2304  return lhs < rhs;
2305  };
2306 
2307  return std::clamp(value, inMin, inMax, comparitor);
2308 #else
2309  if (value < inMin)
2310  {
2311  return inMin;
2312  }
2313  else if (value > inMax)
2314  {
2315  return inMax;
2316  }
2317 
2318  return value;
2319 #endif
2320  });
2321 
2322  return outArray;
2323  }
2324 
2325  //============================================================================
2326  // Method Description:
2333  {
2334  return operator()(rSlice(), inColumn);
2335  }
2336 
2337  //============================================================================
2338  // Method Description:
2346  {
2348 
2349  switch (inAxis)
2350  {
2351  case Axis::NONE:
2352  {
2353  NdArray<bool> returnArray = { stl_algorithms::find(cbegin(), cend(), inValue) != cend() };
2354  return returnArray;
2355  }
2356  case Axis::COL:
2357  {
2358  NdArray<bool> returnArray(1, shape_.rows);
2359  for (uint32 row = 0; row < shape_.rows; ++row)
2360  {
2361  returnArray(0, row) = stl_algorithms::find(cbegin(row), cend(row), inValue) != cend(row);
2362  }
2363 
2364  return returnArray;
2365  }
2366  case Axis::ROW:
2367  {
2368  NdArray<dtype> transArray = transpose();
2369  NdArray<bool> returnArray(1, transArray.shape_.rows);
2370  for (uint32 row = 0; row < transArray.shape_.rows; ++row)
2371  {
2372  returnArray(0, row) = stl_algorithms::find(transArray.cbegin(row), transArray.cend(row), inValue) != transArray.cend(row);
2373  }
2374 
2375  return returnArray;
2376  }
2377  default:
2378  {
2379  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2380  return {}; // get rid of compiler warning
2381  }
2382  }
2383  }
2384 
2385  //============================================================================
2386  // Method Description:
2394  {
2395  return NdArray<dtype>(*this);
2396  }
2397 
2398  //============================================================================
2399  // Method Description:
2408  {
2410 
2411  switch (inAxis)
2412  {
2413  case Axis::NONE:
2414  {
2415  NdArray<dtype> returnArray(1, size_);
2416  returnArray[0] = front();
2417  for (uint32 i = 1; i < size_; ++i)
2418  {
2419  returnArray[i] = returnArray[i - 1] * array_[i];
2420  }
2421 
2422  return returnArray;
2423  }
2424  case Axis::COL:
2425  {
2426  NdArray<dtype> returnArray(shape_);
2427  for (uint32 row = 0; row < shape_.rows; ++row)
2428  {
2429  returnArray(row, 0) = operator()(row, 0);
2430  for (uint32 col = 1; col < shape_.cols; ++col)
2431  {
2432  returnArray(row, col) = returnArray(row, col - 1) * operator()(row, col);
2433  }
2434  }
2435 
2436  return returnArray;
2437  }
2438  case Axis::ROW:
2439  {
2440  NdArray<dtype> returnArray(shape_);
2441  for (uint32 col = 0; col < shape_.cols; ++col)
2442  {
2443  returnArray(0, col) = operator()(0, col);
2444  for (uint32 row = 1; row < shape_.rows; ++row)
2445  {
2446  returnArray(row, col) = returnArray(row - 1, col) * operator()(row, col);
2447  }
2448  }
2449 
2450  return returnArray;
2451  }
2452  default:
2453  {
2454  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2455  return {}; // get rid of compiler warning
2456  }
2457  }
2458  }
2459 
2460  //============================================================================
2461  // Method Description:
2470  {
2472 
2473  switch (inAxis)
2474  {
2475  case Axis::NONE:
2476  {
2477  NdArray<dtype> returnArray(1, size_);
2478  returnArray[0] = front();
2479  for (uint32 i = 1; i < size_; ++i)
2480  {
2481  returnArray[i] = returnArray[i - 1] + array_[i];
2482  }
2483 
2484  return returnArray;
2485  }
2486  case Axis::COL:
2487  {
2488  NdArray<dtype> returnArray(shape_);
2489  for (uint32 row = 0; row < shape_.rows; ++row)
2490  {
2491  returnArray(row, 0) = operator()(row, 0);
2492  for (uint32 col = 1; col < shape_.cols; ++col)
2493  {
2494  returnArray(row, col) = returnArray(row, col - 1) + operator()(row, col);
2495  }
2496  }
2497 
2498  return returnArray;
2499  }
2500  case Axis::ROW:
2501  {
2502  NdArray<dtype> returnArray(shape_);
2503  for (uint32 col = 0; col < shape_.cols; ++col)
2504  {
2505  returnArray(0, col) = operator()(0, col);
2506  for (uint32 row = 1; row < shape_.rows; ++row)
2507  {
2508  returnArray(row, col) = returnArray(row - 1, col) + operator()(row, col);
2509  }
2510  }
2511 
2512  return returnArray;
2513  }
2514  default:
2515  {
2516  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2517  return {}; // get rid of compiler warning
2518  }
2519  }
2520  }
2521 
2522  //============================================================================
2523  // Method Description:
2527  pointer data() noexcept
2528  {
2529  return array_;
2530  }
2531 
2532  //============================================================================
2533  // Method Description:
2537  const_pointer data() const noexcept
2538  {
2539  return array_;
2540  }
2541 
2542  //============================================================================
2543  // Method Description:
2550  {
2551  ownsPtr_ = false;
2552  return data();
2553  }
2554 
2555  //============================================================================
2556  // Method Description:
2565  NdArray<dtype> diagonal(int32 inOffset = 0, Axis inAxis = Axis::ROW) const
2566  {
2567  switch (inAxis)
2568  {
2569  case Axis::ROW:
2570  {
2571  std::vector<dtype> diagnolValues;
2572  int32 col = inOffset;
2573  for (uint32 row = 0; row < shape_.rows; ++row)
2574  {
2575  if (col < 0)
2576  {
2577  ++col;
2578  continue;
2579  }
2580  if (col >= static_cast<int32>(shape_.cols))
2581  {
2582  break;
2583  }
2584 
2585  diagnolValues.push_back(operator()(row, static_cast<uint32>(col)));
2586  ++col;
2587  }
2588 
2589  return NdArray<dtype>(diagnolValues);
2590  }
2591  case Axis::COL:
2592  {
2593  std::vector<dtype> diagnolValues;
2594  uint32 col = 0;
2595  for (int32 row = inOffset; row < static_cast<int32>(shape_.rows); ++row)
2596  {
2597  if (row < 0)
2598  {
2599  ++col;
2600  continue;
2601  }
2602  if (col >= shape_.cols)
2603  {
2604  break;
2605  }
2606 
2607  diagnolValues.push_back(operator()(static_cast<uint32>(row), col));
2608  ++col;
2609  }
2610 
2611  return NdArray<dtype>(diagnolValues);
2612  }
2613  default:
2614  {
2615  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2616  return {}; // get rid of compiler warning
2617  }
2618  }
2619  }
2620 
2621  //============================================================================
2622  // Method Description:
2633  NdArray<dtype> dot(const NdArray<dtype>& inOtherArray) const
2634  {
2636 
2637  if (shape_ == inOtherArray.shape_ && (shape_.rows == 1 || shape_.cols == 1))
2638  {
2639  dtype dotProduct = std::inner_product(cbegin(), cend(), inOtherArray.cbegin(), dtype{ 0 });
2640  NdArray<dtype> returnArray = { dotProduct };
2641  return returnArray;
2642  }
2643  if (shape_.cols == inOtherArray.shape_.rows)
2644  {
2645  // 2D array, use matrix multiplication
2646  NdArray<dtype> returnArray(shape_.rows, inOtherArray.shape_.cols);
2647  auto otherArrayT = inOtherArray.transpose();
2648 
2649  for (uint32 i = 0; i < shape_.rows; ++i)
2650  {
2651  for (uint32 j = 0; j < otherArrayT.shape_.rows; ++j)
2652  {
2653  returnArray(i, j) = std::inner_product(otherArrayT.cbegin(j), otherArrayT.cend(j), cbegin(i), dtype{ 0 });
2654  }
2655  }
2656 
2657  return returnArray;
2658  }
2659 
2660  std::string errStr = "shapes of [" + utils::num2str(shape_.rows) + ", " + utils::num2str(shape_.cols) + "]";
2661  errStr += " and [" + utils::num2str(inOtherArray.shape_.rows) + ", " + utils::num2str(inOtherArray.shape_.cols) + "]";
2662  errStr += " are not consistent.";
2664 
2665  return NdArray<dtype>(); // get rid of compiler warning
2666  }
2667 
2668  //============================================================================
2669  // Method Description:
2677  void dump(const std::string& inFilename) const
2678  {
2679  filesystem::File f(inFilename);
2680  if (!f.hasExt())
2681  {
2682  f.withExt(".bin");
2683  }
2684 
2685  std::ofstream ofile(f.fullName().c_str(), std::ios::binary);
2686  if (!ofile.good())
2687  {
2688  THROW_RUNTIME_ERROR("Unable to open the input file:\n\t" + inFilename);
2689  }
2690 
2691  if (array_ != nullptr)
2692  {
2693  ofile.write(reinterpret_cast<const char*>(array_), size_ * sizeof(dtype));
2694  }
2695  ofile.close();
2696  }
2697 
2698  //============================================================================
2699  // Method Description:
2704  Endian endianess() const noexcept
2705  {
2706  STATIC_ASSERT_ARITHMETIC(dtype);
2707 
2708  return endianess_;
2709  }
2710 
2711  //============================================================================
2712  // Method Description:
2720  NdArray<dtype>& fill(value_type inFillValue) noexcept
2721  {
2722  stl_algorithms::fill(begin(), end(), inFillValue);
2723  return *this;
2724  }
2725 
2726  //============================================================================
2727  // Method Description:
2734  {
2736 
2737  std::vector<uint32> indices;
2738  uint32 idx = 0;
2739  for (auto value : *this)
2740  {
2741  if (value != dtype{ 0 })
2742  {
2743  indices.push_back(idx);
2744  }
2745  ++idx;
2746  }
2747 
2748  return NdArray<uint32>(indices);
2749  }
2750 
2751  //============================================================================
2752  // Method Description:
2760  {
2761  NdArray<dtype> outArray(1, size_);
2762  stl_algorithms::copy(cbegin(), cend(), outArray.begin());
2763  return outArray;
2764  }
2765 
2766  //============================================================================
2767  // Method Description:
2772  const_reference front() const noexcept
2773  {
2774  return *cbegin();
2775  }
2776 
2777  //============================================================================
2778  // Method Description:
2783  reference front() noexcept
2784  {
2785  return *begin();
2786  }
2787 
2788  //============================================================================
2789  // Method Description:
2795  {
2796  return *cbegin(row);
2797  }
2798 
2799  //============================================================================
2800  // Method Description:
2806  {
2807  return *begin(row);
2808  }
2809 
2810  //============================================================================
2811  // Method Description:
2818  {
2819  return operator[](inIndices);
2820  }
2821 
2822  //============================================================================
2823  // Method Description:
2832  {
2833  return operator[](inMask);
2834  }
2835 
2836  //============================================================================
2837  // Method Description:
2843  bool isempty() const noexcept
2844  {
2845  return size_ == 0;
2846  }
2847 
2848  //============================================================================
2849  // Method Description:
2855  bool isflat() const noexcept
2856  {
2857  return shape_.rows == 1 || shape_.cols == 1;
2858  }
2859 
2860  //============================================================================
2861  // Method Description:
2868  {
2870 
2871  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
2872  {
2873  return lhs < rhs;
2874  };
2875 
2876  switch (inAxis)
2877  {
2878  case Axis::NONE:
2879  {
2880  return { stl_algorithms::is_sorted(cbegin(), cend(), comparitor) };
2881  }
2882  case Axis::ROW:
2883  {
2884  NdArray<bool> returnArray(shape_.cols, 1);
2885  auto transposedArray = transpose();
2886  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
2887  {
2888  returnArray(0, row) = stl_algorithms::is_sorted(transposedArray.cbegin(row),
2889  transposedArray.cend(row), comparitor);
2890  }
2891 
2892  return returnArray;
2893  }
2894  case Axis::COL:
2895  {
2896  NdArray<bool> returnArray(1, shape_.rows);
2897  for (uint32 row = 0; row < shape_.rows; ++row)
2898  {
2899  returnArray(0, row) = stl_algorithms::is_sorted(cbegin(row), cend(row), comparitor);
2900  }
2901 
2902  return returnArray;
2903  }
2904  default:
2905  {
2906  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2907  return {}; // get rid of compiler warning
2908  }
2909  }
2910  }
2911 
2912  //============================================================================
2913  // Method Description:
2918  bool issquare() const noexcept
2919  {
2920  return shape_.issquare();
2921  }
2922 
2923  //============================================================================
2924  // Method Description:
2932  {
2933  if (size_ != 1)
2934  {
2935  THROW_INVALID_ARGUMENT_ERROR("Can only convert an array of size 1 to a C++ scaler");
2936  }
2937 
2938  return front();
2939  }
2940 
2941  //============================================================================
2942  // Method Description:
2951  {
2953 
2954  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
2955  {
2956  return lhs < rhs;
2957  };
2958 
2959  switch (inAxis)
2960  {
2961  case Axis::NONE:
2962  {
2963  NdArray<dtype> returnArray = { *stl_algorithms::max_element(cbegin(), cend(), comparitor) };
2964  return returnArray;
2965  }
2966  case Axis::COL:
2967  {
2968  NdArray<dtype> returnArray(1, shape_.rows);
2969  for (uint32 row = 0; row < shape_.rows; ++row)
2970  {
2971  returnArray(0, row) = *stl_algorithms::max_element(cbegin(row), cend(row), comparitor);
2972  }
2973 
2974  return returnArray;
2975  }
2976  case Axis::ROW:
2977  {
2978  NdArray<dtype> transposedArray = transpose();
2979  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
2980  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
2981  {
2982  returnArray(0, row) = *stl_algorithms::max_element(transposedArray.cbegin(row),
2983  transposedArray.cend(row), comparitor);
2984  }
2985 
2986  return returnArray;
2987  }
2988  default:
2989  {
2990  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2991  return {}; // get rid of compiler warning
2992  }
2993  }
2994  }
2995 
2996  //============================================================================
2997  // Method Description:
3006  {
3008 
3009  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3010  {
3011  return lhs < rhs;
3012  };
3013 
3014  switch (inAxis)
3015  {
3016  case Axis::NONE:
3017  {
3018  NdArray<dtype> returnArray = { *stl_algorithms::min_element(cbegin(), cend(), comparitor) };
3019  return returnArray;
3020  }
3021  case Axis::COL:
3022  {
3023  NdArray<dtype> returnArray(1, shape_.rows);
3024  for (uint32 row = 0; row < shape_.rows; ++row)
3025  {
3026  returnArray(0, row) = *stl_algorithms::min_element(cbegin(row), cend(row), comparitor);
3027  }
3028 
3029  return returnArray;
3030  }
3031  case Axis::ROW:
3032  {
3033  NdArray<dtype> transposedArray = transpose();
3034  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3035  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3036  {
3037  returnArray(0, row) = *stl_algorithms::min_element(transposedArray.cbegin(row),
3038  transposedArray.cend(row), comparitor);
3039  }
3040 
3041  return returnArray;
3042  }
3043  default:
3044  {
3045  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3046  return {}; // get rid of compiler warning
3047  }
3048  }
3049  }
3050 
3051  //============================================================================
3052  // Method Description:
3063  {
3065 
3066  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3067  {
3068  return lhs < rhs;
3069  };
3070 
3071  if (size_ == 0)
3072  {
3073  THROW_RUNTIME_ERROR("Median is undefined for an array of size = 0.");
3074  }
3075 
3076  switch (inAxis)
3077  {
3078  case Axis::NONE:
3079  {
3080  NdArray<dtype> copyArray(*this);
3081 
3082  const uint32 middleIdx = size_ / 2; // integer division
3083  stl_algorithms::nth_element(copyArray.begin(), copyArray.begin() + middleIdx, copyArray.end(), comparitor);
3084 
3085  dtype medianValue = copyArray.array_[middleIdx];
3086  if (size_ % 2 == 0)
3087  {
3088  const uint32 lhsIndex = middleIdx - 1;
3089  stl_algorithms::nth_element(copyArray.begin(), copyArray.begin() + lhsIndex, copyArray.end(), comparitor);
3090  medianValue = (medianValue + copyArray.array_[lhsIndex]) / dtype{2}; // potentially integer division, ok
3091  }
3092 
3093  return { medianValue };
3094  }
3095  case Axis::COL:
3096  {
3097  NdArray<dtype> copyArray(*this);
3098  NdArray<dtype> returnArray(1, shape_.rows);
3099 
3100  const bool isEven = shape_.cols % 2 == 0;
3101  for (uint32 row = 0; row < shape_.rows; ++row)
3102  {
3103  const uint32 middleIdx = shape_.cols / 2; // integer division
3104  stl_algorithms::nth_element(copyArray.begin(row), copyArray.begin(row) + middleIdx,
3105  copyArray.end(row), comparitor);
3106 
3107  dtype medianValue = copyArray(row, middleIdx);
3108  if (isEven)
3109  {
3110  const uint32 lhsIndex = middleIdx - 1;
3111  stl_algorithms::nth_element(copyArray.begin(row), copyArray.begin(row) + lhsIndex,
3112  copyArray.end(row), comparitor);
3113  medianValue = (medianValue + copyArray(row, lhsIndex)) / dtype{2}; // potentially integer division, ok
3114  }
3115 
3116  returnArray(0, row) = medianValue;
3117  }
3118 
3119  return returnArray;
3120  }
3121  case Axis::ROW:
3122  {
3123  NdArray<dtype> transposedArray = transpose();
3124  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3125 
3126  const bool isEven = shape_.rows % 2 == 0;
3127  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3128  {
3129  const uint32 middleIdx = transposedArray.shape_.cols / 2; // integer division
3130  stl_algorithms::nth_element(transposedArray.begin(row), transposedArray.begin(row) + middleIdx,
3131  transposedArray.end(row), comparitor);
3132 
3133  dtype medianValue = transposedArray(row, middleIdx);
3134  if (isEven)
3135  {
3136  const uint32 lhsIndex = middleIdx - 1;
3137  stl_algorithms::nth_element(transposedArray.begin(row), transposedArray.begin(row) + lhsIndex,
3138  transposedArray.end(row), comparitor);
3139  medianValue = (medianValue + transposedArray(row, lhsIndex)) / dtype{2}; // potentially integer division, ok
3140  }
3141 
3142  returnArray(0, row) = medianValue;
3143  }
3144 
3145  return returnArray;
3146  }
3147  default:
3148  {
3149  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3150  return {}; // get rid of compiler warning
3151  }
3152  }
3153  }
3154 
3155  //============================================================================
3156  // Method Description:
3160  NdArray<dtype>& nans() noexcept
3161  {
3162  STATIC_ASSERT_FLOAT(dtype);
3163 
3165  return *this;
3166  }
3167 
3168  //============================================================================
3169  // Method Description:
3176  uint64 nbytes() const noexcept
3177  {
3178  return static_cast<uint64>(sizeof(dtype) * size_);
3179  }
3180 
3181  //============================================================================
3182  // Method Description:
3191  NdArray<dtype> newbyteorder(Endian inEndianess) const
3192  {
3193  STATIC_ASSERT_INTEGER(dtype);
3194 
3195  const bool nativeIsLittle = endian::isLittleEndian();
3196 
3197  switch (endianess_)
3198  {
3199  case Endian::NATIVE:
3200  {
3201  switch (inEndianess)
3202  {
3203  case Endian::NATIVE:
3204  {
3205  return NdArray(*this);
3206  }
3207  case Endian::BIG:
3208  {
3209  if (nativeIsLittle)
3210  {
3211  NdArray<dtype> outArray(shape_);
3212 
3213  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3214 
3215  outArray.endianess_ = Endian::BIG;
3216  return outArray;
3217  }
3218  else
3219  {
3220  auto outArray = NdArray(*this);
3221  outArray.endianess_ = Endian::BIG;
3222  return outArray;
3223  }
3224  }
3225  case Endian::LITTLE:
3226  {
3227  if (nativeIsLittle)
3228  {
3229  auto outArray = NdArray(*this);
3230  outArray.endianess_ = Endian::LITTLE;
3231  return outArray;
3232  }
3233  else
3234  {
3235  NdArray<dtype> outArray(shape_);
3236 
3237  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3238 
3239  outArray.endianess_ = Endian::LITTLE;
3240  return outArray;
3241  }
3242  }
3243  default:
3244  {
3245  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3246  return {}; // get rid of compiler warning
3247  }
3248  }
3249  break;
3250  }
3251  case Endian::BIG:
3252  {
3253  switch (inEndianess)
3254  {
3255  case Endian::NATIVE:
3256  {
3257  if (nativeIsLittle)
3258  {
3259  NdArray<dtype> outArray(shape_);
3260 
3261  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3262 
3263  outArray.endianess_ = Endian::NATIVE;
3264  return outArray;
3265  }
3266  else
3267  {
3268  auto outArray = NdArray(*this);
3269  outArray.endianess_ = Endian::NATIVE;
3270  return outArray;
3271  }
3272  }
3273  case Endian::BIG:
3274  {
3275  return NdArray(*this);
3276  }
3277  case Endian::LITTLE:
3278  {
3279  NdArray<dtype> outArray(shape_);
3280 
3281  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3282 
3283  outArray.endianess_ = Endian::LITTLE;
3284  return outArray;
3285  }
3286  default:
3287  {
3288  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3289  return {}; // get rid of compiler warning
3290  }
3291  }
3292  break;
3293  }
3294  case Endian::LITTLE:
3295  {
3296  switch (inEndianess)
3297  {
3298  case Endian::NATIVE:
3299  {
3300  if (nativeIsLittle)
3301  {
3302  auto outArray = NdArray(*this);
3303  outArray.endianess_ = Endian::NATIVE;
3304  return outArray;
3305  }
3306  else
3307  {
3308  NdArray<dtype> outArray(shape_);
3309 
3310  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3311 
3312  outArray.endianess_ = Endian::NATIVE;
3313  return outArray;
3314  }
3315  }
3316  case Endian::BIG:
3317  {
3318  NdArray<dtype> outArray(shape_);
3319 
3320  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3321 
3322  outArray.endianess_ = Endian::BIG;
3323  return outArray;
3324  }
3325  case Endian::LITTLE:
3326  {
3327  return NdArray(*this);
3328  }
3329  default:
3330  {
3331  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3332  return {}; // get rid of compiler warning
3333  }
3334  }
3335  break;
3336  }
3337  default:
3338  {
3339  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3340  return {}; // get rid of compiler warning
3341  }
3342  }
3343  }
3344 
3345  //============================================================================
3346  // Method Description:
3355  {
3357 
3358  const auto function = [](dtype i) -> bool
3359  {
3360  return i != dtype{ 0 };
3361  };
3362 
3363  switch (inAxis)
3364  {
3365  case Axis::NONE:
3366  {
3367  NdArray<bool> returnArray = { stl_algorithms::none_of(cbegin(), cend(), function) };
3368  return returnArray;
3369  }
3370  case Axis::COL:
3371  {
3372  NdArray<bool> returnArray(1, shape_.rows);
3373  for (uint32 row = 0; row < shape_.rows; ++row)
3374  {
3375  returnArray(0, row) = stl_algorithms::none_of(cbegin(row), cend(row), function);
3376  }
3377 
3378  return returnArray;
3379  }
3380  case Axis::ROW:
3381  {
3382  NdArray<dtype> arrayTransposed = transpose();
3383  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
3384  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
3385  {
3386  returnArray(0, row) = stl_algorithms::none_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
3387  }
3388 
3389  return returnArray;
3390  }
3391  default:
3392  {
3393  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3394  return {}; // get rid of compiler warning
3395  }
3396  }
3397  }
3398 
3399  //============================================================================
3400  // Method Description:
3409  std::pair<NdArray<uint32>, NdArray<uint32>> nonzero() const;
3410 
3411  //============================================================================
3412  // Method Description:
3418  uint32 numCols() const noexcept
3419  {
3420  return shape_.cols;
3421  }
3422 
3423  //============================================================================
3424  // Method Description:
3430  uint32 numRows() const noexcept
3431  {
3432  return shape_.rows;
3433  }
3434 
3435  //============================================================================
3436  // Method Description:
3440  NdArray<dtype>& ones() noexcept
3441  {
3443 
3444  fill(dtype{ 1 });
3445  return *this;
3446  }
3447 
3448  //============================================================================
3449  // Method Description:
3454  bool ownsInternalData() noexcept
3455  {
3456  return ownsPtr_;
3457  }
3458 
3459  //============================================================================
3460  // Method Description:
3475  {
3477 
3478  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3479  {
3480  return lhs < rhs;
3481  };
3482 
3483  switch (inAxis)
3484  {
3485  case Axis::NONE:
3486  {
3487  if (inKth >= size_)
3488  {
3489  std::string errStr = "kth(=" + utils::num2str(inKth);
3490  errStr += ") out of bounds (" + utils::num2str(size_) + ")";
3492  }
3493 
3494  stl_algorithms::nth_element(begin(), begin() + inKth, end(), comparitor);
3495  break;
3496  }
3497  case Axis::COL:
3498  {
3499  if (inKth >= shape_.cols)
3500  {
3501  std::string errStr = "kth(=" + utils::num2str(inKth);
3502  errStr += ") out of bounds (" + utils::num2str(shape_.cols) + ")";
3504  }
3505 
3506  for (uint32 row = 0; row < shape_.rows; ++row)
3507  {
3508  stl_algorithms::nth_element(begin(row), begin(row) + inKth, end(row), comparitor);
3509  }
3510  break;
3511  }
3512  case Axis::ROW:
3513  {
3514  if (inKth >= shape_.rows)
3515  {
3516  std::string errStr = "kth(=" + utils::num2str(inKth);
3517  errStr += ") out of bounds (" + utils::num2str(shape_.rows) + ")";
3519  }
3520 
3521  NdArray<dtype> transposedArray = transpose();
3522  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3523  {
3524  stl_algorithms::nth_element(transposedArray.begin(row), transposedArray.begin(row) + inKth,
3525  transposedArray.end(row), comparitor);
3526  }
3527  *this = transposedArray.transpose();
3528  break;
3529  }
3530  }
3531 
3532  return *this;
3533  }
3534 
3535  //============================================================================
3536  // Method Description:
3540  void print() const
3541  {
3543 
3544  std::cout << *this;
3545  }
3546 
3547  //============================================================================
3548  // Method Description:
3557  {
3559 
3560  switch (inAxis)
3561  {
3562  case Axis::NONE:
3563  {
3564  dtype product = std::accumulate(cbegin(), cend(),
3565  dtype{ 1 }, std::multiplies<dtype>());
3566  NdArray<dtype> returnArray = { product };
3567  return returnArray;
3568  }
3569  case Axis::COL:
3570  {
3571  NdArray<dtype> returnArray(1, shape_.rows);
3572  for (uint32 row = 0; row < shape_.rows; ++row)
3573  {
3574  returnArray(0, row) = std::accumulate(cbegin(row), cend(row),
3575  dtype{ 1 }, std::multiplies<dtype>());
3576  }
3577 
3578  return returnArray;
3579  }
3580  case Axis::ROW:
3581  {
3582  NdArray<dtype> transposedArray = transpose();
3583  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3584  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3585  {
3586  returnArray(0, row) = std::accumulate(transposedArray.cbegin(row), transposedArray.cend(row),
3587  dtype{ 1 }, std::multiplies<dtype>());
3588  }
3589 
3590  return returnArray;
3591  }
3592  default:
3593  {
3594  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3595  return {}; // get rid of compiler warning
3596  }
3597  }
3598  }
3599 
3600  //============================================================================
3601  // Method Description:
3610  {
3612 
3613  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3614  {
3615  return lhs < rhs;
3616  };
3617 
3618  switch (inAxis)
3619  {
3620  case Axis::NONE:
3621  {
3622  const auto result = stl_algorithms::minmax_element(cbegin(), cend(), comparitor);
3623  NdArray<dtype> returnArray = { *result.second - *result.first };
3624  return returnArray;
3625  }
3626  case Axis::COL:
3627  {
3628  NdArray<dtype> returnArray(1, shape_.rows);
3629  for (uint32 row = 0; row < shape_.rows; ++row)
3630  {
3631  const auto result = stl_algorithms::minmax_element(cbegin(row), cend(row), comparitor);
3632  returnArray(0, row) = *result.second - *result.first;
3633  }
3634 
3635  return returnArray;
3636  }
3637  case Axis::ROW:
3638  {
3639  NdArray<dtype> transposedArray = transpose();
3640  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3641  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3642  {
3643  const auto result = stl_algorithms::minmax_element(transposedArray.cbegin(row), transposedArray.cend(row), comparitor);
3644  returnArray(0, row) = *result.second - *result.first;
3645  }
3646 
3647  return returnArray;
3648  }
3649  default:
3650  {
3651  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3652  return {}; // get rid of compiler warning
3653  }
3654  }
3655  }
3656 
3657  //============================================================================
3658  // Method Description:
3666  NdArray<dtype>& put(int32 inIndex, value_type inValue)
3667  {
3668  at(inIndex) = inValue;
3669 
3670  return *this;
3671  }
3672 
3673  //============================================================================
3674  // Method Description:
3683  NdArray<dtype>& put(int32 inRow, int32 inCol, value_type inValue)
3684  {
3685  at(inRow, inCol) = inValue;
3686 
3687  return *this;
3688  }
3689 
3690  //============================================================================
3691  // Method Description:
3699  NdArray<dtype>& put(const NdArray<uint32>& inIndices, value_type inValue)
3700  {
3701  for (auto index : inIndices)
3702  {
3703  put(index, inValue);
3704  }
3705 
3706  return *this;
3707  }
3708 
3709  //============================================================================
3710  // Method Description:
3718  NdArray<dtype>& put(const NdArray<uint32>& inIndices, const NdArray<dtype>& inValues)
3719  {
3720  if (inIndices.size() != inValues.size())
3721  {
3722  THROW_INVALID_ARGUMENT_ERROR("Input indices do not match values dimensions.");
3723  }
3724 
3725  uint32 counter = 0;
3726  for (auto index : inIndices)
3727  {
3728  put(index, inValues[counter++]);
3729  }
3730 
3731  return *this;
3732  }
3733 
3734  //============================================================================
3735  // Method Description:
3743  NdArray<dtype>& put(const Slice& inSlice, value_type inValue)
3744  {
3745  Slice inSliceCopy(inSlice);
3746  inSliceCopy.makePositiveAndValidate(size_);
3747 
3748  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
3749  {
3750  put(i, inValue);
3751  }
3752 
3753  return *this;
3754  }
3755 
3756  //============================================================================
3757  // Method Description:
3765  NdArray<dtype>& put(const Slice& inSlice, const NdArray<dtype>& inValues)
3766  {
3767  Slice inSliceCopy(inSlice);
3768  inSliceCopy.makePositiveAndValidate(size_);
3769 
3770  std::vector<uint32> indices;
3771  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
3772  {
3773  indices.push_back(i);
3774  }
3775 
3776  return put(NdArray<uint32>(indices), inValues);
3777  }
3778 
3779  //============================================================================
3780  // Method Description:
3789  NdArray<dtype>& put(const Slice& inRowSlice, const Slice& inColSlice, value_type inValue)
3790  {
3791  Slice inRowSliceCopy(inRowSlice);
3792  Slice inColSliceCopy(inColSlice);
3793 
3794  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3795  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3796 
3797  std::vector<uint32> indices;
3798  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3799  {
3800  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3801  {
3802  put(row, col, inValue);
3803  }
3804  }
3805 
3806  return *this;
3807  }
3808 
3809  //============================================================================
3810  // Method Description:
3819  NdArray<dtype>& put(const Slice& inRowSlice, int32 inColIndex, value_type inValue)
3820  {
3821  Slice inRowSliceCopy(inRowSlice);
3822  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3823 
3824  std::vector<uint32> indices;
3825  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3826  {
3827  put(row, inColIndex, inValue);
3828  }
3829 
3830  return *this;
3831  }
3832 
3833  //============================================================================
3834  // Method Description:
3843  NdArray<dtype>& put(int32 inRowIndex, const Slice& inColSlice, value_type inValue)
3844  {
3845  Slice inColSliceCopy(inColSlice);
3846  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3847 
3848  std::vector<uint32> indices;
3849  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3850  {
3851  put(inRowIndex, col, inValue);
3852  }
3853 
3854  return *this;
3855  }
3856 
3857  //============================================================================
3858  // Method Description:
3867  NdArray<dtype>& put(const Slice& inRowSlice, const Slice& inColSlice, const NdArray<dtype>& inValues)
3868  {
3869  Slice inRowSliceCopy(inRowSlice);
3870  Slice inColSliceCopy(inColSlice);
3871 
3872  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3873  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3874 
3875  std::vector<uint32> indices;
3876  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3877  {
3878  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3879  {
3880  const uint32 index = row * shape_.cols + col;
3881  indices.push_back(index);
3882  }
3883  }
3884 
3885  return put(NdArray<uint32>(indices), inValues);
3886  }
3887 
3888  //============================================================================
3889  // Method Description:
3898  NdArray<dtype>& put(const Slice& inRowSlice, int32 inColIndex, const NdArray<dtype>& inValues)
3899  {
3900  Slice inRowSliceCopy(inRowSlice);
3901  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3902 
3903  std::vector<uint32> indices;
3904  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3905  {
3906  const uint32 index = row * shape_.cols + inColIndex;
3907  indices.push_back(index);
3908  }
3909 
3910  return put(NdArray<uint32>(indices), inValues);
3911  }
3912 
3913  //============================================================================
3914  // Method Description:
3923  NdArray<dtype>& put(int32 inRowIndex, const Slice& inColSlice, const NdArray<dtype>& inValues)
3924  {
3925  Slice inColSliceCopy(inColSlice);
3926  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3927 
3928  std::vector<uint32> indices;
3929  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3930  {
3931  const uint32 index = inRowIndex * shape_.cols + col;
3932  indices.push_back(index);
3933  }
3934 
3935  return put(NdArray<uint32>(indices), inValues);
3936  }
3937 
3938  //============================================================================
3939  // Method Description:
3946  {
3947  if (inMask.shape() != shape_)
3948  {
3949  THROW_INVALID_ARGUMENT_ERROR("input inMask must be the same shape as the array it is masking.");
3950  }
3951 
3952  return put(inMask.flatnonzero(), inValue);
3953  }
3954 
3955  //============================================================================
3956  // Method Description:
3962  NdArray<dtype>& putMask(const NdArray<bool>& inMask, const NdArray<dtype>& inValues)
3963  {
3964  if (inMask.shape() != shape_)
3965  {
3966  THROW_INVALID_ARGUMENT_ERROR("input inMask must be the same shape as the array it is masking.");
3967  }
3968 
3969  return put(inMask.flatnonzero(), inValues);
3970  }
3971 
3972  //============================================================================
3973  // Method Description:
3980  NdArray<dtype>& ravel() noexcept
3981  {
3982  reshape(size_);
3983  return *this;
3984  }
3985 
3986  //============================================================================
3987  // Method Description:
3996  NdArray<dtype> repeat(uint32 inNumRows, uint32 inNumCols) const
3997  {
3998  NdArray<dtype> returnArray(shape_.rows * inNumRows, shape_.cols * inNumCols);
3999 
4000  for (uint32 row = 0; row < inNumRows; ++row)
4001  {
4002  for (uint32 col = 0; col < inNumCols; ++col)
4003  {
4004  std::vector<uint32> indices(shape_.size());
4005 
4006  const uint32 rowStart = row * shape_.rows;
4007  const uint32 colStart = col * shape_.cols;
4008 
4009  const uint32 rowEnd = (row + 1) * shape_.rows;
4010  const uint32 colEnd = (col + 1) * shape_.cols;
4011 
4012  uint32 counter = 0;
4013  for (uint32 rowIdx = rowStart; rowIdx < rowEnd; ++rowIdx)
4014  {
4015  for (uint32 colIdx = colStart; colIdx < colEnd; ++colIdx)
4016  {
4017  indices[counter++] = rowIdx * returnArray.shape_.cols + colIdx;
4018  }
4019  }
4020 
4021  returnArray.put(NdArray<uint32>(indices), *this);
4022  }
4023  }
4024 
4025  return returnArray;
4026  }
4027 
4028  //============================================================================
4029  // Method Description:
4037  NdArray<dtype> repeat(const Shape& inRepeatShape) const
4038  {
4039  return repeat(inRepeatShape.rows, inRepeatShape.cols);
4040  }
4041 
4042  //============================================================================
4043  // Method Description:
4049  void replace(value_type oldValue, value_type newValue)
4050  {
4052 
4053  stl_algorithms::replace(begin(), end(), oldValue, newValue);
4054  }
4055 
4056  //============================================================================
4057  // Method Description:
4068  {
4069  if (inSize != size_)
4070  {
4071  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into shape ";
4072  errStr += "[" + utils::num2str(1) + ", " + utils::num2str(inSize) + "]";
4073  THROW_RUNTIME_ERROR(errStr);
4074  }
4075 
4076  shape_.rows = 1;
4077  shape_.cols = inSize;
4078 
4079  return *this;
4080  }
4081 
4082  //============================================================================
4083  // Method Description:
4094  NdArray<dtype>& reshape(int32 inNumRows, int32 inNumCols)
4095  {
4096  if (inNumRows < 0)
4097  {
4098  if (size_ % inNumCols == 0)
4099  {
4100  return reshape(size_ / inNumCols, inNumCols);
4101  }
4102 
4103  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into a shape ";
4104  errStr += "with " + utils::num2str(inNumCols) + " columns";
4106 
4107  }
4108 
4109  if (inNumCols < 0)
4110  {
4111  if (size_ % inNumRows == 0)
4112  {
4113  return reshape(inNumRows, size_ / inNumRows);
4114  }
4115 
4116  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into a shape ";
4117  errStr += "with " + utils::num2str(inNumRows) + " rows";
4119 
4120  }
4121 
4122  if (static_cast<uint32>(inNumRows * inNumCols) != size_)
4123  {
4124  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into shape ";
4125  errStr += "[" + utils::num2str(inNumRows) + ", " + utils::num2str(inNumCols) + "]";
4127  }
4128 
4129  shape_.rows = static_cast<uint32>(inNumRows);
4130  shape_.cols = static_cast<uint32>(inNumCols);
4131 
4132  return *this;
4133  }
4134 
4135  //============================================================================
4136  // Method Description:
4146  NdArray<dtype>& reshape(const Shape& inShape)
4147  {
4148  return reshape(inShape.rows, inShape.cols);
4149  }
4150 
4151  //============================================================================
4152  // Method Description:
4161  NdArray<dtype>& resizeFast(uint32 inNumRows, uint32 inNumCols)
4162  {
4163  newArray(Shape(inNumRows, inNumCols));
4164  return *this;
4165  }
4166 
4167  //============================================================================
4168  // Method Description:
4176  NdArray<dtype>& resizeFast(const Shape& inShape)
4177  {
4178  return resizeFast(inShape.rows, inShape.cols);
4179  }
4180 
4181  //============================================================================
4182  // Method Description:
4193  NdArray<dtype>& resizeSlow(uint32 inNumRows, uint32 inNumCols)
4194  {
4195  std::vector<dtype> oldData(size_);
4196  stl_algorithms::copy(begin(), end(), oldData.begin());
4197 
4198  const Shape inShape(inNumRows, inNumCols);
4199  const Shape oldShape = shape_;
4200 
4201  newArray(inShape);
4202 
4203  for (uint32 row = 0; row < inShape.rows; ++row)
4204  {
4205  for (uint32 col = 0; col < inShape.cols; ++col)
4206  {
4207  if (row >= oldShape.rows || col >= oldShape.cols)
4208  {
4209  operator()(row, col) = dtype{ 0 }; // zero fill
4210  }
4211  else
4212  {
4213  operator()(row, col) = oldData[row * oldShape.cols + col];
4214  }
4215  }
4216  }
4217 
4218  return *this;
4219  }
4220 
4221  //============================================================================
4222  // Method Description:
4232  NdArray<dtype>& resizeSlow(const Shape& inShape)
4233  {
4234  return resizeSlow(inShape.rows, inShape.cols);
4235  }
4236 
4237  //============================================================================
4238  // Method Description:
4247  NdArray<dtype> round(uint8 inNumDecimals = 0) const
4248  {
4249  STATIC_ASSERT_FLOAT(dtype);
4250 
4251  NdArray<dtype> returnArray(shape_);
4252  const double multFactor = utils::power(10.0, inNumDecimals);
4253  const auto function = [multFactor](dtype value) noexcept -> dtype
4254  {
4255  return static_cast<dtype>(std::nearbyint(static_cast<double>(value) * multFactor) / multFactor);
4256  };
4257 
4258  stl_algorithms::transform(cbegin(), cend(), returnArray.begin(), function);
4259 
4260  return returnArray;
4261  }
4262 
4263  //============================================================================
4264  // Method Description:
4271  {
4272  return NdArray<dtype>(cbegin(inRow), cend(inRow));
4273  }
4274 
4275  //============================================================================
4276  // Method Description:
4283  Shape shape() const noexcept
4284  {
4285  return shape_;
4286  }
4287 
4288  //============================================================================
4289  // Method Description:
4296  size_type size() const noexcept
4297  {
4298  return size_;
4299  }
4300 
4301  //============================================================================
4302  // Method Description:
4311  {
4313 
4314  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
4315  {
4316  return lhs < rhs;
4317  };
4318 
4319  switch (inAxis)
4320  {
4321  case Axis::NONE:
4322  {
4323  stl_algorithms::sort(begin(), end(), comparitor);
4324  break;
4325  }
4326  case Axis::COL:
4327  {
4328  for (uint32 row = 0; row < shape_.rows; ++row)
4329  {
4330  stl_algorithms::sort(begin(row), end(row), comparitor);
4331  }
4332  break;
4333  }
4334  case Axis::ROW:
4335  {
4336  NdArray<dtype> transposedArray = transpose();
4337  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
4338  {
4339  stl_algorithms::sort(transposedArray.begin(row), transposedArray.end(row), comparitor);
4340  }
4341 
4342  *this = transposedArray.transpose();
4343  break;
4344  }
4345  }
4346 
4347  return *this;
4348  }
4349 
4350  //============================================================================
4351  // Method Description:
4356  std::string str() const
4357  {
4359 
4360  std::string out;
4361  out += "[";
4362  for (uint32 row = 0; row < shape_.rows; ++row)
4363  {
4364  out += "[";
4365  for (uint32 col = 0; col < shape_.cols; ++col)
4366  {
4367  out += utils::value2str(operator()(row, col)) + ", ";
4368  }
4369 
4370  if (row == shape_.rows - 1)
4371  {
4372  out += "]";
4373  }
4374  else
4375  {
4376  out += "]\n";
4377  }
4378  }
4379  out += "]\n";
4380  return out;
4381  }
4382 
4383  //============================================================================
4384  // Method Description:
4393  {
4395 
4396  switch (inAxis)
4397  {
4398  case Axis::NONE:
4399  {
4400  NdArray<dtype> returnArray = { std::accumulate(cbegin(), cend(), dtype{ 0 }) };
4401  return returnArray;
4402  }
4403  case Axis::COL:
4404  {
4405  NdArray<dtype> returnArray(1, shape_.rows);
4406  for (uint32 row = 0; row < shape_.rows; ++row)
4407  {
4408  returnArray(0, row) = std::accumulate(cbegin(row), cend(row), dtype{ 0 });
4409  }
4410 
4411  return returnArray;
4412  }
4413  case Axis::ROW:
4414  {
4415  NdArray<dtype> transposedArray = transpose();
4416  const Shape transShape = transposedArray.shape();
4417  NdArray<dtype> returnArray(1, transShape.rows);
4418  for (uint32 row = 0; row < transShape.rows; ++row)
4419  {
4420  returnArray(0, row) = std::accumulate(transposedArray.cbegin(row), transposedArray.cend(row), dtype{ 0 });
4421  }
4422 
4423  return returnArray;
4424  }
4425  default:
4426  {
4427  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
4428  return {}; // get rid of compiler warning
4429  }
4430  }
4431  }
4432 
4433  //============================================================================
4434  // Method Description:
4442  {
4443  return transpose();
4444  }
4445 
4446  //============================================================================
4447  // Method Description:
4455 
4458  void tofile(const std::string& inFilename) const
4459  {
4460  dump(inFilename);
4461  }
4462 
4463  //============================================================================
4464  // Method Description:
4475  void tofile(const std::string& inFilename, const char inSep) const
4476  {
4478 
4479  filesystem::File f(inFilename);
4480  if (!f.hasExt())
4481  {
4482  f.withExt("txt");
4483  }
4484 
4485  std::ofstream ofile(f.fullName().c_str());
4486  if (!ofile.good())
4487  {
4488  THROW_RUNTIME_ERROR("Input file could not be opened:\n\t" + inFilename);
4489  }
4490 
4491  uint32 counter = 0;
4492  for (auto value : *this)
4493  {
4494  ofile << value;
4495  if (counter++ != size_ - 1)
4496  {
4497  ofile << inSep;
4498  }
4499  }
4500  ofile.close();
4501  }
4502 
4503  //============================================================================
4504  // Method Description:
4512  NdArray<uint32> toIndices(Slice inSlice, Axis inAxis = Axis::ROW) const
4513  {
4514  uint32 numElements = 0;
4515  switch (inAxis)
4516  {
4517  case Axis::NONE:
4518  {
4519  numElements = inSlice.numElements(size_);
4520  break;
4521  }
4522  case Axis::ROW:
4523  {
4524  numElements = inSlice.numElements(shape_.rows);
4525  break;
4526  }
4527  case Axis::COL:
4528  {
4529  numElements = inSlice.numElements(shape_.cols);
4530  break;
4531  }
4532  default:
4533  {
4534  // not actually possible, getting rid of compiler warning
4535  THROW_INVALID_ARGUMENT_ERROR("Invalid 'inAxis' option");
4536  }
4537  }
4538 
4539  if (numElements == 0)
4540  {
4541  return {};
4542  }
4543 
4544  NdArray<uint32> indices(1, numElements);
4545  indices[0] = inSlice.start;
4546  for (uint32 i = 1; i < indices.size(); ++i)
4547  {
4548  indices[i] = static_cast<uint32>(indices[i - 1] + inSlice.step);
4549  }
4550 
4551  return indices;
4552  }
4553 
4554  //============================================================================
4555  // Method Description:
4560  std::vector<dtype> toStlVector() const
4561  {
4562  return std::vector<dtype>(cbegin(), cend());
4563  }
4564 
4565  //============================================================================
4566  // Method Description:
4576  value_type trace(uint32 inOffset = 0, Axis inAxis = Axis::ROW) const noexcept
4577  {
4579 
4580  uint32 rowStart = 0;
4581  uint32 colStart = 0;
4582  switch (inAxis)
4583  {
4584  case Axis::ROW:
4585  {
4586  rowStart += inOffset;
4587  break;
4588  }
4589  case Axis::COL:
4590  {
4591  colStart += inOffset;
4592  break;
4593  }
4594  default:
4595  {
4596  // if the user input NONE, override back to ROW
4597  inAxis = Axis::ROW;
4598  break;
4599  }
4600  }
4601 
4602  if (rowStart >= shape_.rows || colStart >= shape_.cols)
4603  {
4604  return dtype{ 0 };
4605  }
4606 
4607  uint32 col = colStart;
4608  dtype sum = 0;
4609  for (uint32 row = rowStart; row < shape_.rows; ++row)
4610  {
4611  if (col >= shape_.cols)
4612  {
4613  break;
4614  }
4615  sum += operator()(row, col++);
4616  }
4617 
4618  return sum;
4619  }
4620 
4621  //============================================================================
4622  // Method Description:
4630  {
4631  NdArray<dtype> transArray(shape_.cols, shape_.rows);
4632  for (uint32 row = 0; row < shape_.rows; ++row)
4633  {
4634  for (uint32 col = 0; col < shape_.cols; ++col)
4635  {
4636  transArray(col, row) = operator()(row, col);
4637  }
4638  }
4639  return transArray;
4640  }
4641 
4642  //============================================================================
4643  // Method Description:
4647  NdArray<dtype>& zeros() noexcept
4648  {
4650 
4651  fill(dtype{ 0 });
4652  return *this;
4653  }
4654 
4655  private:
4656  //====================================Attributes==============================
4657  allocator_type allocator_{};
4658  Shape shape_{ 0, 0 };
4659  size_type size_{ 0 };
4660  Endian endianess_{ Endian::NATIVE };
4661  pointer array_{ nullptr };
4662  bool ownsPtr_{ false };
4663 
4664  //============================================================================
4665  // Method Description:
4668  void deleteArray() noexcept
4669  {
4670  if (ownsPtr_ && array_ != nullptr)
4671  {
4672  allocator_.deallocate(array_, size_);
4673  }
4674 
4675  array_ = nullptr;
4676  shape_.rows = shape_.cols = 0;
4677  size_ = 0;
4678  ownsPtr_ = false;
4679  endianess_ = Endian::NATIVE;
4680  }
4681 
4682  //============================================================================
4683  // Method Description:
4686  void newArray()
4687  {
4688  if (size_ > 0)
4689  {
4690  array_ = allocator_.allocate(size_);
4691  ownsPtr_ = true;
4692  }
4693  }
4694 
4695  //============================================================================
4696  // Method Description:
4701  void newArray(const Shape& inShape)
4702  {
4703  deleteArray();
4704 
4705  shape_ = inShape;
4706  size_ = inShape.size();
4707  newArray();
4708  }
4709  };
4710 
4711  // NOTE: this needs to be defined outside of the class to get rid of a compiler
4712  // error in Visual Studio
4713  template<typename dtype, class _Alloc>
4714  std::pair<NdArray<uint32>, NdArray<uint32>> NdArray<dtype, _Alloc>::nonzero() const
4715  {
4717 
4718  std::vector<uint32> rowIndices;
4719  std::vector<uint32> colIndices;
4720 
4721  for (uint32 row = 0; row < shape_.rows; ++row)
4722  {
4723  for (uint32 col = 0; col < shape_.cols; ++col)
4724  {
4725  if (operator()(row, col) != dtype{ 0 })
4726  {
4727  rowIndices.push_back(row);
4728  colIndices.push_back(col);
4729  }
4730  }
4731  }
4732 
4733  return std::make_pair(NdArray<uint32>(rowIndices), NdArray<uint32>(colIndices));
4734  }
4735 } // namespace nc
#define THROW_RUNTIME_ERROR(msg)
Definition: Error.hpp:37
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:36
#define STATIC_ASSERT_FLOAT(dtype)
Definition: StaticAsserts.hpp:43
#define STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype)
Definition: StaticAsserts.hpp:50
#define STATIC_ASSERT_INTEGER(dtype)
Definition: StaticAsserts.hpp:40
#define STATIC_ASSERT_ARITHMETIC(dtype)
Definition: StaticAsserts.hpp:37
Custom column iterator for NdArray.
Definition: NdArrayIterators.hpp:834
Custom column const_iterator for NdArray.
Definition: NdArrayIterators.hpp:503
Custom const_iterator for NdArray.
Definition: NdArrayIterators.hpp:44
Holds 1D and 2D arrays, the main work horse of the NumCpp library.
Definition: NdArrayCore.hpp:72
uint32 numCols() const noexcept
Definition: NdArrayCore.hpp:3418
NdArray(std::vector< std::array< dtype, Dim1Size >> &in2dArray, bool copy=true)
Definition: NdArrayCore.hpp:322
const_reverse_column_iterator rcolbegin() const noexcept
Definition: NdArrayCore.hpp:1424
NdArray< dtype > at(const NdArray< int32 > &rowIndices, const NdArray< int32 > &colIndices) const
Definition: NdArrayCore.hpp:1154
NdArray< dtypeOut > astype() const
Definition: NdArrayCore.hpp:2097
NdArray< dtype > & put(int32 inIndex, value_type inValue)
Definition: NdArrayCore.hpp:3666
size_type size() const noexcept
Definition: NdArrayCore.hpp:4296
reverse_iterator rbegin() noexcept
Definition: NdArrayCore.hpp:1320
NdArray< dtype > & resizeSlow(uint32 inNumRows, uint32 inNumCols)
Definition: NdArrayCore.hpp:4193
NdArray< dtype > & put(const Slice &inRowSlice, const Slice &inColSlice, value_type inValue)
Definition: NdArrayCore.hpp:3789
NdArray< bool > issorted(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2867
const_iterator cbegin() const noexcept
Definition: NdArrayCore.hpp:1216
NdArray< dtype > operator[](const Indices &inIndices) const
Definition: NdArrayCore.hpp:759
const_reference at(int32 inIndex) const
Definition: NdArrayCore.hpp:1011
const_column_iterator ccolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1305
NdArrayConstColumnIterator< dtype, size_type, const_pointer, difference_type > const_column_iterator
Definition: NdArrayCore.hpp:96
NdArray< dtype > round(uint8 inNumDecimals=0) const
Definition: NdArrayCore.hpp:4247
NdArray< bool > any(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1840
const_pointer data() const noexcept
Definition: NdArrayCore.hpp:2537
NdArray< uint32 > toIndices(Slice inSlice, Axis inAxis=Axis::ROW) const
Definition: NdArrayCore.hpp:4512
NdArray< dtype > at(const Slice &inRowSlice, int32 inColIndex) const
Definition: NdArrayCore.hpp:1124
iterator end() noexcept
Definition: NdArrayCore.hpp:1474
NdArray< dtype > operator()(Slice inRowSlice, int32 inColIndex) const
Definition: NdArrayCore.hpp:813
NdArray< dtype > & put(const Slice &inRowSlice, const Slice &inColSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3867
NdArray(std::vector< dtype > &inVector, bool copy=true)
Definition: NdArrayCore.hpp:262
NdArray(const std::initializer_list< std::initializer_list< dtype > > &inList)
Definition: NdArrayCore.hpp:169
NdArray< dtype > prod(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3556
NdArray< dtype > copy() const
Definition: NdArrayCore.hpp:2393
NdArray< dtype > & resizeFast(const Shape &inShape)
Definition: NdArrayCore.hpp:4176
std::vector< dtype > toStlVector() const
Definition: NdArrayCore.hpp:4560
reference back(size_type row)
Definition: NdArrayCore.hpp:2237
iterator end(size_type inRow)
Definition: NdArrayCore.hpp:1486
NdArray< dtype > flatten() const
Definition: NdArrayCore.hpp:2759
void tofile(const std::string &inFilename, const char inSep) const
Definition: NdArrayCore.hpp:4475
const_column_iterator ccolbegin() const noexcept
Definition: NdArrayCore.hpp:1293
typename AllocTraits::pointer pointer
Definition: NdArrayCore.hpp:83
Slice cSlice(int32 inStartIdx=0, uint32 inStepSize=1) const noexcept
Definition: NdArrayCore.hpp:964
reverse_iterator rbegin(size_type inRow)
Definition: NdArrayCore.hpp:1332
Shape shape() const noexcept
Definition: NdArrayCore.hpp:4283
NdArray< dtype > & byteswap() noexcept
Definition: NdArrayCore.hpp:2250
const_reverse_column_iterator rcolend() const noexcept
Definition: NdArrayCore.hpp:1732
uint32 numRows() const noexcept
Definition: NdArrayCore.hpp:3430
const dtype & const_reference
Definition: NdArrayCore.hpp:86
NdArray< dtype > & put(const Slice &inRowSlice, int32 inColIndex, value_type inValue)
Definition: NdArrayCore.hpp:3819
NdArray< dtype > & partition(uint32 inKth, Axis inAxis=Axis::NONE)
Definition: NdArrayCore.hpp:3474
bool issquare() const noexcept
Definition: NdArrayCore.hpp:2918
NdArrayIterator< dtype, pointer, difference_type > iterator
Definition: NdArrayCore.hpp:90
bool isflat() const noexcept
Definition: NdArrayCore.hpp:2855
Endian endianess() const noexcept
Definition: NdArrayCore.hpp:2704
void tofile(const std::string &inFilename) const
Definition: NdArrayCore.hpp:4458
const_reverse_column_iterator crcolbegin() const noexcept
Definition: NdArrayCore.hpp:1447
const_reverse_column_iterator crcolend(size_type inCol) const
Definition: NdArrayCore.hpp:1767
column_iterator colbegin(size_type inCol)
Definition: NdArrayCore.hpp:1255
NdArrayColumnIterator< dtype, size_type, pointer, difference_type > column_iterator
Definition: NdArrayCore.hpp:95
NdArray< bool > none(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3354
NdArray< dtype > at(const Slice &inSlice) const
Definition: NdArrayCore.hpp:1094
reference at(int32 inIndex)
Definition: NdArrayCore.hpp:990
NdArray< dtype > & sort(Axis inAxis=Axis::NONE)
Definition: NdArrayCore.hpp:4310
pointer data() noexcept
Definition: NdArrayCore.hpp:2527
bool isempty() const noexcept
Definition: NdArrayCore.hpp:2843
column_iterator colbegin() noexcept
Definition: NdArrayCore.hpp:1243
const_reference front(size_type row) const
Definition: NdArrayCore.hpp:2794
reverse_column_iterator rcolend(size_type inCol)
Definition: NdArrayCore.hpp:1717
NdArray< dtype > sum(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:4392
NdArray(Iterator inFirst, Iterator inLast)
Definition: NdArrayCore.hpp:418
NdArray< dtype > operator[](const Slice &inSlice) const
Definition: NdArrayCore.hpp:711
reverse_column_iterator rcolbegin() noexcept
Definition: NdArrayCore.hpp:1397
NdArrayConstIterator< dtype, const_pointer, difference_type > const_iterator
Definition: NdArrayCore.hpp:91
const_iterator cbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1228
const_column_iterator ccolend(size_type inCol) const
Definition: NdArrayCore.hpp:1690
NdArray< dtype > cumsum(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2469
NdArray< dtype > median(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3062
NdArray< dtype > getByMask(const NdArray< bool > &inMask) const
Definition: NdArrayCore.hpp:2831
const_iterator cend(size_type inRow) const
Definition: NdArrayCore.hpp:1536
NdArray< dtype > column(uint32 inColumn)
Definition: NdArrayCore.hpp:2332
const_reverse_column_iterator rcolend(size_type inCol) const
Definition: NdArrayCore.hpp:1744
NdArray< dtype > & putMask(const NdArray< bool > &inMask, value_type inValue)
Definition: NdArrayCore.hpp:3945
const_iterator end(size_type inRow) const
Definition: NdArrayCore.hpp:1513
reference back() noexcept
Definition: NdArrayCore.hpp:2215
const_reverse_column_iterator crcolend() const noexcept
Definition: NdArrayCore.hpp:1755
const_reference back(size_type row) const
Definition: NdArrayCore.hpp:2226
reverse_column_iterator rcolbegin(size_type inCol)
Definition: NdArrayCore.hpp:1409
NdArray(const std::deque< std::deque< dtype >> &in2dDeque)
Definition: NdArrayCore.hpp:366
NdArray< dtype > & put(int32 inRow, int32 inCol, value_type inValue)
Definition: NdArrayCore.hpp:3683
iterator begin(size_type inRow)
Definition: NdArrayCore.hpp:1178
const_reverse_iterator rend() const noexcept
Definition: NdArrayCore.hpp:1578
NdArray< dtype > clip(value_type inMin, value_type inMax) const
Definition: NdArrayCore.hpp:2293
const_reverse_column_iterator rcolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1436
NdArray< dtype > & operator=(NdArray< dtype > &&rhs) noexcept
Definition: NdArrayCore.hpp:604
typename AllocTraits::difference_type difference_type
Definition: NdArrayCore.hpp:88
NdArray< uint32 > argmin(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1953
const_iterator end() const noexcept
Definition: NdArrayCore.hpp:1501
bool ownsInternalData() noexcept
Definition: NdArrayCore.hpp:3454
NdArray< dtype > & fill(value_type inFillValue) noexcept
Definition: NdArrayCore.hpp:2720
column_iterator colend() noexcept
Definition: NdArrayCore.hpp:1628
NdArray(std::initializer_list< dtype > inList)
Definition: NdArrayCore.hpp:152
NdArray< dtype > operator()(Slice inRowSlice, Slice inColSlice) const
Definition: NdArrayCore.hpp:785
NdArray< dtype > & put(const NdArray< uint32 > &inIndices, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3718
const_reference back() const noexcept
Definition: NdArrayCore.hpp:2204
NdArray< dtype > operator()(int32 inRowIndex, Slice inColSlice) const
Definition: NdArrayCore.hpp:835
std::pair< NdArray< uint32 >, NdArray< uint32 > > nonzero() const
Definition: NdArrayCore.hpp:4714
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: NdArrayCore.hpp:93
NdArray(const_pointer inPtr, UIntType1 numRows, UIntType2 numCols)
Definition: NdArrayCore.hpp:460
NdArray< dtype > cumprod(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2407
uint64 nbytes() const noexcept
Definition: NdArrayCore.hpp:3176
const_reference at(int32 inRowIndex, int32 inColIndex) const
Definition: NdArrayCore.hpp:1064
NdArray< dtype > transpose() const
Definition: NdArrayCore.hpp:4629
NdArray< dtype > swapaxes() const
Definition: NdArrayCore.hpp:4441
NdArray< dtype > & put(int32 inRowIndex, const Slice &inColSlice, value_type inValue)
Definition: NdArrayCore.hpp:3843
NdArray(const std::list< dtype > &inList)
Definition: NdArrayCore.hpp:398
NdArray()=default
NdArray< dtype > at(int32 inRowIndex, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:1139
const_reference front() const noexcept
Definition: NdArrayCore.hpp:2772
NdArray< dtype > repeat(const Shape &inRepeatShape) const
Definition: NdArrayCore.hpp:4037
~NdArray() noexcept
Definition: NdArrayCore.hpp:551
NdArray< dtype > min(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3005
NdArray(pointer inPtr, uint32 numRows, uint32 numCols, Bool takeOwnership) noexcept
Definition: NdArrayCore.hpp:503
NdArray< dtype > & reshape(const Shape &inShape)
Definition: NdArrayCore.hpp:4146
reference front() noexcept
Definition: NdArrayCore.hpp:2783
NdArray(size_type inNumRows, size_type inNumCols)
Definition: NdArrayCore.hpp:126
Allocator allocator_type
Definition: NdArrayCore.hpp:82
void print() const
Definition: NdArrayCore.hpp:3540
const_reverse_column_iterator crcolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1459
reverse_iterator rend(size_type inRow)
Definition: NdArrayCore.hpp:1563
NdArray< uint32 > flatnonzero() const
Definition: NdArrayCore.hpp:2733
NdArray(size_type inSquareSize)
Definition: NdArrayCore.hpp:112
NdArray< dtype > operator()(int32 rowIndex, const Indices &colIndices) const
Definition: NdArrayCore.hpp:892
reverse_iterator rend() noexcept
Definition: NdArrayCore.hpp:1551
const_reverse_iterator rend(size_type inRow) const
Definition: NdArrayCore.hpp:1590
NdArray< dtype > getByIndices(const NdArray< uint32 > &inIndices) const
Definition: NdArrayCore.hpp:2817
typename AllocTraits::const_pointer const_pointer
Definition: NdArrayCore.hpp:84
NdArray< dtype > & resizeSlow(const Shape &inShape)
Definition: NdArrayCore.hpp:4232
const_reverse_iterator crbegin() const noexcept
Definition: NdArrayCore.hpp:1370
const_column_iterator colend(size_type inCol) const
Definition: NdArrayCore.hpp:1667
std::reverse_iterator< iterator > reverse_iterator
Definition: NdArrayCore.hpp:92
NdArray< dtype > operator()(const Indices &rowIndices, Slice colSlice) const
Definition: NdArrayCore.hpp:876
NdArray(const std::vector< std::vector< dtype >> &in2dVector)
Definition: NdArrayCore.hpp:287
const_reverse_iterator rbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1359
const_iterator cend() const noexcept
Definition: NdArrayCore.hpp:1524
std::string str() const
Definition: NdArrayCore.hpp:4356
std::reverse_iterator< const_column_iterator > const_reverse_column_iterator
Definition: NdArrayCore.hpp:98
reference operator[](int32 inIndex) noexcept
Definition: NdArrayCore.hpp:630
NdArray< dtype > & reshape(int32 inNumRows, int32 inNumCols)
Definition: NdArrayCore.hpp:4094
NdArray(NdArray< dtype > &&inOtherArray) noexcept
Definition: NdArrayCore.hpp:534
NdArray< dtype > & nans() noexcept
Definition: NdArrayCore.hpp:3160
NdArray< dtype > & put(const NdArray< uint32 > &inIndices, value_type inValue)
Definition: NdArrayCore.hpp:3699
NdArray< dtype > ptp(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3609
const_reference operator()(int32 inRowIndex, int32 inColIndex) const noexcept
Definition: NdArrayCore.hpp:688
reference front(size_type row)
Definition: NdArrayCore.hpp:2805
NdArray< dtype > diagonal(int32 inOffset=0, Axis inAxis=Axis::ROW) const
Definition: NdArrayCore.hpp:2565
NdArray< dtype > & putMask(const NdArray< bool > &inMask, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3962
NdArray< dtype > operator[](const NdArray< bool > &inMask) const
Definition: NdArrayCore.hpp:732
NdArray< dtype > row(uint32 inRow)
Definition: NdArrayCore.hpp:4270
NdArray< dtype > operator()(const Indices &rowIndices, int32 colIndex) const
Definition: NdArrayCore.hpp:859
const_iterator begin(size_type inRow) const
Definition: NdArrayCore.hpp:1205
iterator begin() noexcept
Definition: NdArrayCore.hpp:1166
NdArray< dtype > & put(const Slice &inSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3765
const_column_iterator colbegin() const noexcept
Definition: NdArrayCore.hpp:1270
NdArray< dtype > max(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2950
std::reverse_iterator< column_iterator > reverse_column_iterator
Definition: NdArrayCore.hpp:97
NdArray< dtype > & operator=(const NdArray< dtype > &rhs)
Definition: NdArrayCore.hpp:563
value_type item() const
Definition: NdArrayCore.hpp:2931
reference operator()(int32 inRowIndex, int32 inColIndex) noexcept
Definition: NdArrayCore.hpp:665
const_column_iterator colend() const noexcept
Definition: NdArrayCore.hpp:1655
NdArray< dtype > & resizeFast(uint32 inNumRows, uint32 inNumCols)
Definition: NdArrayCore.hpp:4161
const_reverse_iterator crend() const noexcept
Definition: NdArrayCore.hpp:1601
NdArray< dtype > & ones() noexcept
Definition: NdArrayCore.hpp:3440
NdArray< dtype > operator()(RowIndices rowIndices, ColIndices colIndices) const
Definition: NdArrayCore.hpp:926
NdArray< dtype > & zeros() noexcept
Definition: NdArrayCore.hpp:4647
const_column_iterator colbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1282
NdArray< dtype > dot(const NdArray< dtype > &inOtherArray) const
Definition: NdArrayCore.hpp:2633
NdArray< dtype > repeat(uint32 inNumRows, uint32 inNumCols) const
Definition: NdArrayCore.hpp:3996
NdArray< dtype > & reshape(size_type inSize)
Definition: NdArrayCore.hpp:4067
NdArray< bool > contains(value_type inValue, Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2345
const_column_iterator ccolend() const noexcept
Definition: NdArrayCore.hpp:1678
NdArray< uint32 > argmax(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1895
value_type trace(uint32 inOffset=0, Axis inAxis=Axis::ROW) const noexcept
Definition: NdArrayCore.hpp:4576
reverse_column_iterator rcolend() noexcept
Definition: NdArrayCore.hpp:1705
NdArray(std::array< dtype, ArraySize > &inArray, bool copy=true)
Definition: NdArrayCore.hpp:205
NdArray< dtype > & put(int32 inRowIndex, const Slice &inColSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3923
const_reverse_iterator rbegin() const noexcept
Definition: NdArrayCore.hpp:1347
NdArray(const_pointer inPtr, size_type size)
Definition: NdArrayCore.hpp:437
NdArray(const std::deque< dtype > &inDeque)
Definition: NdArrayCore.hpp:349
NdArray(std::array< std::array< dtype, Dim1Size >, Dim0Size > &in2dArray, bool copy=true)
Definition: NdArrayCore.hpp:233
void dump(const std::string &inFilename) const
Definition: NdArrayCore.hpp:2677
dtype & reference
Definition: NdArrayCore.hpp:85
pointer dataRelease() noexcept
Definition: NdArrayCore.hpp:2549
reference at(int32 inRowIndex, int32 inColIndex)
Definition: NdArrayCore.hpp:1033
NdArray< dtype > at(const Slice &inRowSlice, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:1109
NdArray< dtype > operator()(Slice rowSlice, const Indices &colIndices) const
Definition: NdArrayCore.hpp:909
NdArray(const NdArray< dtype > &inOtherArray)
Definition: NdArrayCore.hpp:516
NdArray< uint32 > argsort(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2010
uint32 size_type
Definition: NdArrayCore.hpp:87
const_iterator begin() const noexcept
Definition: NdArrayCore.hpp:1193
NdArray< dtype > & operator=(value_type inValue) noexcept
Definition: NdArrayCore.hpp:587
NdArray< dtype > newbyteorder(Endian inEndianess) const
Definition: NdArrayCore.hpp:3191
column_iterator colend(size_type inCol)
Definition: NdArrayCore.hpp:1640
NdArray< dtype > & put(const Slice &inSlice, value_type inValue)
Definition: NdArrayCore.hpp:3743
const_reference operator[](int32 inIndex) const noexcept
Definition: NdArrayCore.hpp:647
NdArray< dtype > & ravel() noexcept
Definition: NdArrayCore.hpp:3980
dtype value_type
Definition: NdArrayCore.hpp:81
NdArray(pointer inPtr, size_type size, Bool takeOwnership) noexcept
Definition: NdArrayCore.hpp:483
void replace(value_type oldValue, value_type newValue)
Definition: NdArrayCore.hpp:4049
NdArray< dtype > & put(const Slice &inRowSlice, int32 inColIndex, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3898
Slice rSlice(int32 inStartIdx=0, uint32 inStepSize=1) const noexcept
Definition: NdArrayCore.hpp:978
const_reverse_iterator crend(size_type inRow) const
Definition: NdArrayCore.hpp:1613
const_reverse_iterator crbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1382
NdArray(const Shape &inShape)
Definition: NdArrayCore.hpp:139
NdArray< bool > all(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1786
Custom iterator for NdArray.
Definition: NdArrayIterators.hpp:324
A Shape Class for NdArrays.
Definition: Core/Shape.hpp:41
uint32 rows
Definition: Core/Shape.hpp:44
uint32 cols
Definition: Core/Shape.hpp:45
uint32 size() const noexcept
Definition: Core/Shape.hpp:102
A Class for slicing into NdArrays.
Definition: Slice.hpp:44
int32 step
Definition: Slice.hpp:49
int32 start
Definition: Slice.hpp:47
void makePositiveAndValidate(uint32 inArraySize)
Definition: Slice.hpp:137
uint32 numElements(uint32 inArraySize)
Definition: Slice.hpp:188
int32 stop
Definition: Slice.hpp:48
Provides simple filesystem functions.
Definition: Filesystem.hpp:40
constexpr auto j
Definition: Constants.hpp:45
const double nan
NaN.
Definition: Constants.hpp:44
bool isLittleEndian() noexcept
Definition: Endian.hpp:44
dtype byteSwap(dtype value) noexcept
Definition: Endian.hpp:63
dtype f(dtype inDofN, dtype inDofD)
Definition: f.hpp:55
bool any_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:76
void sort(RandomIt first, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:629
bool none_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:379
ForwardIt max_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:268
void stable_sort(RandomIt first, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:664
OutputIt transform(InputIt first, InputIt last, OutputIt destination, UnaryOperation unaryFunction)
Definition: StlAlgorithms.hpp:702
bool all_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:57
void for_each(InputIt first, InputIt last, UnaryFunction f)
Definition: StlAlgorithms.hpp:213
InputIt find(InputIt first, InputIt last, const T &value) noexcept
Definition: StlAlgorithms.hpp:195
constexpr OutputIt unique_copy(InputIt first, InputIt last, OutputIt destination) noexcept
Definition: StlAlgorithms.hpp:744
std::pair< ForwardIt, ForwardIt > minmax_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:341
void replace(ForwardIt first, ForwardIt last, const T &oldValue, const T &newValue) noexcept
Definition: StlAlgorithms.hpp:435
bool is_sorted(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:231
OutputIt copy(InputIt first, InputIt last, OutputIt destination) noexcept
Definition: StlAlgorithms.hpp:95
void nth_element(RandomIt first, RandomIt nth, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:397
ForwardIt min_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:304
void fill(ForwardIt first, ForwardIt last, const T &value) noexcept
Definition: StlAlgorithms.hpp:174
std::string num2str(dtype inNumber)
Definition: num2str.hpp:46
dtype power(dtype inValue, uint8 inPower) noexcept
Definition: Utils/power.hpp:48
std::string value2str(dtype inValue)
Definition: value2str.hpp:48
Definition: Coordinate.hpp:45
NdArray< dtype > repeat(const NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition: repeat.hpp:49
std::pair< NdArray< uint32 >, NdArray< uint32 > > nonzero(const NdArray< dtype > &inArray)
Definition: nonzero.hpp:48
NdArray< dtype > & resizeFast(NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition: resizeFast.hpp:50
Axis
Enum To describe an axis.
Definition: Types.hpp:46
NdArray< dtype > & reshape(NdArray< dtype > &inArray, uint32 inSize)
Definition: reshape.hpp:51
std::int64_t int64
Definition: Types.hpp:35
auto abs(dtype inValue) noexcept
Definition: abs.hpp:49
std::uint64_t uint64
Definition: Types.hpp:39
NdArray< dtype > & resizeSlow(NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition: resizeSlow.hpp:52
Endian
Enum for endianess.
Definition: Types.hpp:50
std::int32_t int32
Definition: Types.hpp:36
std::uint8_t uint8
Definition: Types.hpp:42
NdArray< dtype > sum(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition: sum.hpp:46
NdArray< dtype > & put(NdArray< dtype > &inArray, const NdArray< uint32 > &inIndices, dtype inValue)
Definition: put.hpp:48
NdArray< dtype > transpose(const NdArray< dtype > &inArray)
Definition: transpose.hpp:45
typename std::enable_if< B, T >::type enable_if_t
Definition: TypeTraits.hpp:40
std::uint32_t uint32
Definition: Types.hpp:40
void dump(const NdArray< dtype > &inArray, const std::string &inFilename)
Definition: dump.hpp:46