NumCpp  2.8.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 
30 #include <array>
31 #include <cmath>
32 #include <deque>
33 #include <forward_list>
34 #include <fstream>
35 #include <initializer_list>
36 #include <iostream>
37 #include <iterator>
38 #include <list>
39 #include <memory>
40 #include <numeric>
41 #include <set>
42 #include <string>
43 #include <type_traits>
44 #include <utility>
45 #include <vector>
46 
56 #include "NumCpp/Core/Shape.hpp"
57 #include "NumCpp/Core/Slice.hpp"
58 #include "NumCpp/Core/Types.hpp"
60 #include "NumCpp/Utils/num2str.hpp"
61 #include "NumCpp/Utils/power.hpp"
62 #include "NumCpp/Utils/sqr.hpp"
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>,
76  "value_type and Allocator::value_type must match");
77 
78  using AllocType = typename std::allocator_traits<Allocator>::template rebind_alloc<dtype>;
79  using AllocTraits = std::allocator_traits<AllocType>;
80 
81  public:
82  using value_type = dtype;
83  using allocator_type = Allocator;
84  using pointer = typename AllocTraits::pointer;
85  using const_pointer = typename AllocTraits::const_pointer;
86  using reference = dtype&;
87  using const_reference = const dtype&;
88  using size_type = uint32;
89  using difference_type = typename AllocTraits::difference_type;
90 
93  using reverse_iterator = std::reverse_iterator<iterator>;
94  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
95 
98  using reverse_column_iterator = std::reverse_iterator<column_iterator>;
99  using const_reverse_column_iterator = std::reverse_iterator<const_column_iterator>;
100 
101  //============================================================================
102  // Method Description:
105  NdArray() = default;
106 
107  //============================================================================
108  // Method Description:
113  explicit NdArray(size_type inSquareSize) :
114  shape_(inSquareSize, inSquareSize),
115  size_(inSquareSize * inSquareSize)
116  {
117  newArray();
118  }
119 
120  //============================================================================
121  // Method Description:
127  NdArray(size_type inNumRows, size_type inNumCols) :
128  shape_(inNumRows, inNumCols),
129  size_(inNumRows * inNumCols)
130  {
131  newArray();
132  }
133 
134  //============================================================================
135  // Method Description:
140  explicit NdArray(const Shape& inShape) :
141  shape_(inShape),
142  size_(shape_.size())
143  {
144  newArray();
145  }
146 
147  //============================================================================
148  // Method Description:
153  NdArray(std::initializer_list<dtype> inList) :
154  shape_(1, static_cast<uint32>(inList.size())),
155  size_(shape_.size())
156  {
157  newArray();
158  if (size_ > 0)
159  {
160  stl_algorithms::copy(inList.begin(), inList.end(), begin());
161  }
162  }
163 
164  //============================================================================
165  // Method Description:
170  NdArray(const std::initializer_list<std::initializer_list<dtype>>& inList) :
171  shape_(static_cast<uint32>(inList.size()), 0)
172  {
173  for (const auto& list : inList)
174  {
175  if (shape_.cols == 0)
176  {
177  shape_.cols = static_cast<uint32>(list.size());
178  }
179  else if (list.size() != shape_.cols)
180  {
182  "All rows of the initializer list needs to have the same number of elements");
183  }
184  }
185 
186  size_ = shape_.size();
187  newArray();
188  uint32 row = 0;
189  for (const auto& list : inList)
190  {
191  const auto ptr = begin() += row * shape_.cols;
192  stl_algorithms::copy(list.begin(), list.end(), ptr);
193  ++row;
194  }
195  }
196 
197  //============================================================================
198  // Method Description:
205  template<size_t ArraySize, std::enable_if_t<is_valid_dtype_v<dtype>, int> = 0>
206  NdArray(std::array<dtype, ArraySize>& inArray, bool copy = true) :
207  shape_(1, static_cast<uint32>(ArraySize)),
208  size_(shape_.size())
209  {
210  if (copy)
211  {
212  newArray();
213  if (size_ > 0)
214  {
215  stl_algorithms::copy(inArray.begin(), inArray.end(), begin());
216  }
217  }
218  else
219  {
220  array_ = inArray.data();
221  ownsPtr_ = false;
222  }
223  }
224 
225  //============================================================================
226  // Method Description:
233  template<size_t Dim0Size, size_t Dim1Size>
234  NdArray(std::array<std::array<dtype, Dim1Size>, Dim0Size>& in2dArray, bool copy = true) :
235  shape_(static_cast<uint32>(Dim0Size), static_cast<uint32>(Dim1Size)),
236  size_(shape_.size())
237  {
238  if (copy)
239  {
240  newArray();
241  if (size_ > 0)
242  {
243  const auto start = in2dArray.front().begin();
244  stl_algorithms::copy(start, start + size_, begin());
245  }
246  }
247  else
248  {
249  array_ = in2dArray.front().data();
250  ownsPtr_ = false;
251  }
252  }
253 
254  //============================================================================
255  // Method Description:
262  template<std::enable_if_t<is_valid_dtype_v<dtype>, int> = 0>
263  NdArray(std::vector<dtype>& inVector, bool copy = true) :
264  shape_(1, static_cast<uint32>(inVector.size())),
265  size_(shape_.size())
266  {
267  if (copy)
268  {
269  newArray();
270  if (size_ > 0)
271  {
272  stl_algorithms::copy(inVector.begin(), inVector.end(), begin());
273  }
274  }
275  else
276  {
277  array_ = inVector.data();
278  ownsPtr_ = false;
279  }
280  }
281 
282  //============================================================================
283  // Method Description:
288  explicit NdArray(const std::vector<std::vector<dtype>>& in2dVector) :
289  shape_(static_cast<uint32>(in2dVector.size()), 0)
290  {
291  for (const auto& row : in2dVector)
292  {
293  if (shape_.cols == 0)
294  {
295  shape_.cols = static_cast<uint32>(row.size());
296  }
297  else if (row.size() != shape_.cols)
298  {
299  THROW_INVALID_ARGUMENT_ERROR("All rows of the 2d vector need to have the same number of elements");
300  }
301  }
302 
303  size_ = shape_.size();
304 
305  newArray();
306  auto currentPosition = begin();
307  for (const auto& row : in2dVector)
308  {
309  stl_algorithms::copy(row.begin(), row.end(), currentPosition);
310  currentPosition += shape_.cols;
311  }
312  }
313 
314  //============================================================================
315  // Method Description:
322  template<size_t Dim1Size>
323  NdArray(std::vector<std::array<dtype, Dim1Size>>& in2dArray, bool copy = true) :
324  shape_(static_cast<uint32>(in2dArray.size()), static_cast<uint32>(Dim1Size)),
325  size_(shape_.size())
326  {
327  if (copy)
328  {
329  newArray();
330  if (size_ > 0)
331  {
332  const auto start = in2dArray.front().begin();
333  stl_algorithms::copy(start, start + size_, begin());
334  }
335  }
336  else
337  {
338  array_ = in2dArray.front().data();
339  ownsPtr_ = false;
340  }
341  }
342 
343  //============================================================================
344  // Method Description:
349  template<std::enable_if_t<is_valid_dtype_v<dtype>, int> = 0>
350  explicit NdArray(const std::deque<dtype>& inDeque) :
351  shape_(1, static_cast<uint32>(inDeque.size())),
352  size_(shape_.size())
353  {
354  newArray();
355  if (size_ > 0)
356  {
357  stl_algorithms::copy(inDeque.begin(), inDeque.end(), begin());
358  }
359  }
360 
361  //============================================================================
362  // Method Description:
367  explicit NdArray(const std::deque<std::deque<dtype>>& in2dDeque) :
368  shape_(static_cast<uint32>(in2dDeque.size()), 0)
369  {
370  for (const auto& row : in2dDeque)
371  {
372  if (shape_.cols == 0)
373  {
374  shape_.cols = static_cast<uint32>(row.size());
375  }
376  else if (row.size() != shape_.cols)
377  {
378  THROW_INVALID_ARGUMENT_ERROR("All rows of the 2d vector need to have the same number of elements");
379  }
380  }
381 
382  size_ = shape_.size();
383 
384  newArray();
385  auto currentPosition = begin();
386  for (const auto& row : in2dDeque)
387  {
388  stl_algorithms::copy(row.begin(), row.end(), currentPosition);
389  currentPosition += shape_.cols;
390  }
391  }
392 
393  //============================================================================
394  // Method Description:
399  explicit NdArray(const std::list<dtype>& inList) :
400  shape_(1, static_cast<uint32>(inList.size())),
401  size_(shape_.size())
402  {
403  newArray();
404  if (size_ > 0)
405  {
406  stl_algorithms::copy(inList.begin(), inList.end(), begin());
407  }
408  }
409 
410  //============================================================================
411  // Method Description:
417  template<typename Iterator,
418  std::enable_if_t<is_same_v<typename std::iterator_traits<Iterator>::value_type, dtype>, int> = 0>
419  NdArray(Iterator inFirst, Iterator inLast) :
420  shape_(1, static_cast<uint32>(std::distance(inFirst, inLast))),
421  size_(shape_.size())
422  {
423  newArray();
424  if (size_ > 0)
425  {
426  stl_algorithms::copy(inFirst, inLast, begin());
427  }
428  }
429 
430  //============================================================================
431  // Method Description:
439  shape_(1, size),
440  size_(size)
441  {
442  newArray();
443  if (inPtr != nullptr && size_ > 0)
444  {
445  stl_algorithms::copy(inPtr, inPtr + size_, begin());
446  }
447  }
448 
449  //============================================================================
450  // Method Description:
458  template<typename UIntType1,
459  typename UIntType2,
460  std::enable_if_t<!is_same_v<UIntType1, bool>, int> = 0,
461  std::enable_if_t<!is_same_v<UIntType2, bool>, int> = 0>
462  NdArray(const_pointer inPtr, UIntType1 numRows, UIntType2 numCols) :
463  shape_(numRows, numCols),
464  size_(shape_.size())
465  {
466  newArray();
467  if (inPtr != nullptr && size_ > 0)
468  {
469  stl_algorithms::copy(inPtr, inPtr + size_, begin());
470  }
471  }
472 
473  //============================================================================
474  // Method Description:
483  template<typename BoolType, std::enable_if_t<is_same_v<BoolType, bool>, int> = 0>
484  NdArray(pointer inPtr, size_type size, BoolType takeOwnership) noexcept :
485  shape_(1, size),
486  size_(size),
487  array_(inPtr),
488  ownsPtr_(takeOwnership)
489  {
490  }
491 
492  //============================================================================
493  // Method Description:
503  template<typename BoolType, std::enable_if_t<is_same_v<BoolType, bool>, int> = 0>
504  NdArray(pointer inPtr, uint32 numRows, uint32 numCols, BoolType takeOwnership) noexcept :
505  shape_(numRows, numCols),
506  size_(numRows * numCols),
507  array_(inPtr),
508  ownsPtr_(takeOwnership)
509  {
510  }
511 
512  //============================================================================
513  // Method Description:
518  NdArray(const NdArray<dtype>& inOtherArray) :
519  shape_(inOtherArray.shape_),
520  size_(inOtherArray.size_),
521  endianess_(inOtherArray.endianess_)
522  {
523  newArray();
524  if (size_ > 0)
525  {
526  stl_algorithms::copy(inOtherArray.cbegin(), inOtherArray.cend(), begin());
527  }
528  }
529 
530  //============================================================================
531  // Method Description:
536  NdArray(NdArray<dtype>&& inOtherArray) noexcept :
537  shape_(inOtherArray.shape_),
538  size_(inOtherArray.size_),
539  endianess_(inOtherArray.endianess_),
540  array_(inOtherArray.array_),
541  ownsPtr_(inOtherArray.ownsPtr_)
542  {
543  inOtherArray.shape_.rows = inOtherArray.shape_.cols = 0;
544  inOtherArray.size_ = 0;
545  inOtherArray.ownsPtr_ = false;
546  inOtherArray.array_ = nullptr;
547  }
548 
549  //============================================================================
550  // Method Description:
553  ~NdArray() noexcept
554  {
555  deleteArray();
556  }
557 
558  //============================================================================
559  // Method Description:
566  {
567  if (&rhs != this)
568  {
569  if (rhs.size_ > 0)
570  {
571  newArray(rhs.shape_);
572  endianess_ = rhs.endianess_;
573 
574  stl_algorithms::copy(rhs.cbegin(), rhs.cend(), begin());
575  }
576  }
577 
578  return *this;
579  }
580 
581  //============================================================================
582  // Method Description:
590  {
591  if (array_ != nullptr)
592  {
593  stl_algorithms::fill(begin(), end(), inValue);
594  }
595 
596  return *this;
597  }
598 
599  //============================================================================
600  // Method Description:
607  {
608  if (&rhs != this)
609  {
610  deleteArray();
611  shape_ = rhs.shape_;
612  size_ = rhs.size_;
613  endianess_ = rhs.endianess_;
614  array_ = rhs.array_;
615  ownsPtr_ = rhs.ownsPtr_;
616 
617  rhs.shape_.rows = rhs.shape_.cols = rhs.size_ = 0;
618  rhs.array_ = nullptr;
619  rhs.ownsPtr_ = false;
620  }
621 
622  return *this;
623  }
624 
625  //============================================================================
626  // Method Description:
632  reference operator[](int32 inIndex) noexcept
633  {
634  if (inIndex < 0)
635  {
636  inIndex += size_;
637  }
638 
639  return array_[inIndex];
640  }
641 
642  //============================================================================
643  // Method Description:
649  const_reference operator[](int32 inIndex) const noexcept
650  {
651  if (inIndex < 0)
652  {
653  inIndex += size_;
654  }
655 
656  return array_[inIndex];
657  }
658 
659  //============================================================================
660  // Method Description:
667  reference operator()(int32 inRowIndex, int32 inColIndex) noexcept
668  {
669  if (inRowIndex < 0)
670  {
671  inRowIndex += shape_.rows;
672  }
673 
674  if (inColIndex < 0)
675  {
676  inColIndex += shape_.cols;
677  }
678 
679  return array_[inRowIndex * shape_.cols + inColIndex];
680  }
681 
682  //============================================================================
683  // Method Description:
690  const_reference operator()(int32 inRowIndex, int32 inColIndex) const noexcept
691  {
692  if (inRowIndex < 0)
693  {
694  inRowIndex += shape_.rows;
695  }
696 
697  if (inColIndex < 0)
698  {
699  inColIndex += shape_.cols;
700  }
701 
702  return array_[inRowIndex * shape_.cols + inColIndex];
703  }
704 
705  //============================================================================
706  // Method Description:
713  NdArray<dtype> operator[](const Slice& inSlice) const
714  {
715  Slice inSliceCopy(inSlice);
716 
717  uint32 counter = 0;
718  NdArray<dtype> returnArray(1, inSliceCopy.numElements(size_));
719  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
720  {
721  returnArray[counter++] = at(i);
722  }
723 
724  return returnArray;
725  }
726 
727  //============================================================================
728  // Method Description:
735  {
736  if (inMask.shape() != shape_)
737  {
739  "input inMask must have the same shape as the NdArray it will be masking.");
740  }
741 
742  auto indices = inMask.flatnonzero();
743  auto outArray = NdArray<dtype>(1, indices.size());
744  for (size_type i = 0; i < indices.size(); ++i)
745  {
746  outArray[i] = operator[](indices[i]);
747  }
748 
749  return outArray;
750  }
751 
752  //============================================================================
753  // Method Description:
760  template<typename Indices, enable_if_t<is_same_v<Indices, NdArray<size_type>>, int> = 0>
761  NdArray<dtype> operator[](const Indices& inIndices) const
762  {
763  if (inIndices.max().item() > size_ - 1)
764  {
765  THROW_INVALID_ARGUMENT_ERROR("input indices must be less than the array size.");
766  }
767 
768  auto outArray = NdArray<dtype>(1, static_cast<size_type>(inIndices.size()));
769  size_type i = 0;
770  for (auto& index : inIndices)
771  {
772  outArray[i++] = operator[](index);
773  }
774 
775  return outArray;
776  }
777 
778  //============================================================================
779  // Method Description:
787  NdArray<dtype> operator()(Slice inRowSlice, Slice inColSlice) const
788  {
789  NdArray<dtype> returnArray(inRowSlice.numElements(shape_.rows), inColSlice.numElements(shape_.cols));
790 
791  uint32 rowCounter = 0;
792  uint32 colCounter = 0;
793  for (int32 row = inRowSlice.start; row < inRowSlice.stop; row += inRowSlice.step)
794  {
795  for (int32 col = inColSlice.start; col < inColSlice.stop; col += inColSlice.step)
796  {
797  returnArray(rowCounter, colCounter++) = at(row, col);
798  }
799  colCounter = 0;
800  ++rowCounter;
801  }
802 
803  return returnArray;
804  }
805 
806  //============================================================================
807  // Method Description:
815  NdArray<dtype> operator()(Slice inRowSlice, int32 inColIndex) const
816  {
817  NdArray<dtype> returnArray(inRowSlice.numElements(shape_.rows), 1);
818 
819  uint32 rowCounter = 0;
820  for (int32 row = inRowSlice.start; row < inRowSlice.stop; row += inRowSlice.step)
821  {
822  returnArray(rowCounter++, 0) = at(row, inColIndex);
823  }
824 
825  return returnArray;
826  }
827 
828  //============================================================================
829  // Method Description:
837  NdArray<dtype> operator()(int32 inRowIndex, Slice inColSlice) const
838  {
839  NdArray<dtype> returnArray(1, inColSlice.numElements(shape_.cols));
840 
841  uint32 colCounter = 0;
842  for (int32 col = inColSlice.start; col < inColSlice.stop; col += inColSlice.step)
843  {
844  returnArray(0, colCounter++) = at(inRowIndex, col);
845  }
846 
847  return returnArray;
848  }
849 
850  //============================================================================
851  // Method Description:
859  template<typename Indices,
860  enable_if_t<is_same_v<Indices, NdArray<int32>> || is_same_v<Indices, NdArray<uint32>>, int> = 0>
861  NdArray<dtype> operator()(const Indices& rowIndices, int32 colIndex) const
862  {
863  const NdArray<int32> colIndices = { colIndex };
864  return operator()(rowIndices, colIndices);
865  }
866 
867  //============================================================================
868  // Method Description:
876  template<typename Indices,
877  enable_if_t<is_same_v<Indices, NdArray<int32>> || is_same_v<Indices, NdArray<uint32>>, int> = 0>
878  NdArray<dtype> operator()(const Indices& rowIndices, Slice colSlice) const
879  {
880  return operator()(rowIndices, toIndices(colSlice, Axis::COL));
881  }
882 
883  //============================================================================
884  // Method Description:
892  template<typename Indices,
893  enable_if_t<is_same_v<Indices, NdArray<int32>> || is_same_v<Indices, NdArray<uint32>>, int> = 0>
894  NdArray<dtype> operator()(int32 rowIndex, const Indices& colIndices) const
895  {
896  const NdArray<int32> rowIndices = { rowIndex };
897  return operator()(rowIndices, colIndices);
898  }
899 
900  //============================================================================
901  // Method Description:
909  template<typename Indices,
910  enable_if_t<is_same_v<Indices, NdArray<int32>> || is_same_v<Indices, NdArray<uint32>>, int> = 0>
911  NdArray<dtype> operator()(Slice rowSlice, const Indices& colIndices) const
912  {
913  return operator()(toIndices(rowSlice, Axis::ROW), colIndices);
914  }
915 
916  //============================================================================
917  // Method Description:
925  template<typename RowIndices,
926  typename ColIndices,
927  enable_if_t<is_same_v<RowIndices, NdArray<int32>> || is_same_v<RowIndices, NdArray<uint32>>, int> = 0,
928  enable_if_t<is_same_v<ColIndices, NdArray<int32>> || is_same_v<ColIndices, NdArray<uint32>>, int> = 0>
929  NdArray<dtype> operator()(RowIndices rowIndices, ColIndices colIndices) const
930  {
931  rowIndices.sort();
932  colIndices.sort();
933 
934  std::vector<int32> rowIndicesUnique(rowIndices.size());
935  std::vector<int32> colIndicesUnique(colIndices.size());
936 
937  const auto lastRow =
938  stl_algorithms::unique_copy(rowIndices.begin(), rowIndices.end(), rowIndicesUnique.begin());
939  const auto lastCol =
940  stl_algorithms::unique_copy(colIndices.begin(), colIndices.end(), colIndicesUnique.begin());
941 
942  NdArray<dtype> returnArray(static_cast<uint32>(lastRow - rowIndicesUnique.begin()),
943  static_cast<uint32>(lastCol - colIndicesUnique.begin()));
944 
945  uint32 rowCounter = 0;
946  for (auto rowIter = rowIndicesUnique.begin(); rowIter != lastRow; ++rowIter)
947  {
948  uint32 colCounter = 0;
949  for (auto colIter = colIndicesUnique.begin(); colIter != lastCol; ++colIter)
950  {
951  returnArray(rowCounter, colCounter++) = at(*rowIter, *colIter);
952  }
953 
954  ++rowCounter;
955  }
956 
957  return returnArray;
958  }
959 
960  //============================================================================
961  // Method Description:
969  Slice cSlice(int32 inStartIdx = 0, uint32 inStepSize = 1) const noexcept
970  {
971  return Slice(inStartIdx, shape_.cols, inStepSize);
972  }
973 
974  //============================================================================
975  // Method Description:
983  Slice rSlice(int32 inStartIdx = 0, uint32 inStepSize = 1) const noexcept
984  {
985  return Slice(inStartIdx, shape_.rows, inStepSize);
986  }
987 
988  //============================================================================
989  // Method Description:
995  reference at(int32 inIndex)
996  {
997  // this doesn't allow for calling the first element as -size_...
998  // but why would you really want to do that anyway?
999  if (std::abs(inIndex) > static_cast<int64>(size_ - 1))
1000  {
1001  std::string errStr = "Input index " + utils::num2str(inIndex);
1002  errStr += " is out of bounds for array of size " + utils::num2str(size_) + ".";
1004  }
1005 
1006  return operator[](inIndex);
1007  }
1008 
1009  //============================================================================
1010  // Method Description:
1016  const_reference at(int32 inIndex) const
1017  {
1018  // this doesn't allow for calling the first element as -size_...
1019  // but why would you really want to do that anyway?
1020  if (std::abs(inIndex) > static_cast<int64>(size_ - 1))
1021  {
1022  std::string errStr = "Input index " + utils::num2str(inIndex);
1023  errStr += " is out of bounds for array of size " + utils::num2str(size_) + ".";
1025  }
1026 
1027  return operator[](inIndex);
1028  }
1029 
1030  //============================================================================
1031  // Method Description:
1038  reference at(int32 inRowIndex, int32 inColIndex)
1039  {
1040  // this doesn't allow for calling the first element as -size_...
1041  // but why would you really want to do that anyway?
1042  if (std::abs(inRowIndex) > static_cast<int32>(shape_.rows - 1))
1043  {
1044  std::string errStr = "Row index " + utils::num2str(inRowIndex);
1045  errStr += " is out of bounds for array of size " + utils::num2str(shape_.rows) + ".";
1047  }
1048 
1049  // this doesn't allow for calling the first element as -size_...
1050  // but why would you really want to that anyway?
1051  if (std::abs(inColIndex) > static_cast<int32>(shape_.cols - 1))
1052  {
1053  std::string errStr = "Column index " + utils::num2str(inColIndex);
1054  errStr += " is out of bounds for array of size " + utils::num2str(shape_.cols) + ".";
1056  }
1057 
1058  return operator()(inRowIndex, inColIndex);
1059  }
1060 
1061  //============================================================================
1062  // Method Description:
1069  const_reference at(int32 inRowIndex, int32 inColIndex) const
1070  {
1071  // this doesn't allow for calling the first element as -size_...
1072  // but why would you really want to do that anyway?
1073  if (std::abs(inRowIndex) > static_cast<int32>(shape_.rows - 1))
1074  {
1075  std::string errStr = "Row index " + utils::num2str(inRowIndex);
1076  errStr += " is out of bounds for array of size " + utils::num2str(shape_.rows) + ".";
1078  }
1079 
1080  // this doesn't allow for calling the first element as -size_...
1081  // but why would you really want to do that anyway?
1082  if (std::abs(inColIndex) > static_cast<int32>(shape_.cols - 1))
1083  {
1084  std::string errStr = "Column index " + utils::num2str(inColIndex);
1085  errStr += " is out of bounds for array of size " + utils::num2str(shape_.cols) + ".";
1087  }
1088 
1089  return operator()(inRowIndex, inColIndex);
1090  }
1091 
1092  //============================================================================
1093  // Method Description:
1099  NdArray<dtype> at(const Slice& inSlice) const
1100  {
1101  // the slice operator already provides bounds checking. just including
1102  // the at method for completeness
1103  return operator[](inSlice);
1104  }
1105 
1106  //============================================================================
1107  // Method Description:
1114  NdArray<dtype> at(const Slice& inRowSlice, const Slice& inColSlice) const
1115  {
1116  // the slice operator already provides bounds checking. just including
1117  // the at method for completeness
1118  return operator()(inRowSlice, inColSlice);
1119  }
1120 
1121  //============================================================================
1122  // Method Description:
1129  NdArray<dtype> at(const Slice& inRowSlice, int32 inColIndex) const
1130  {
1131  // the slice operator already provides bounds checking. just including
1132  // the at method for completeness
1133  return operator()(inRowSlice, inColIndex);
1134  }
1135 
1136  //============================================================================
1137  // Method Description:
1144  NdArray<dtype> at(int32 inRowIndex, const Slice& inColSlice) const
1145  {
1146  // the slice operator already provides bounds checking. just including
1147  // the at method for completeness
1148  return operator()(inRowIndex, inColSlice);
1149  }
1150 
1151  //============================================================================
1152  // Method Description:
1159  NdArray<dtype> at(const NdArray<int32>& rowIndices, const NdArray<int32>& colIndices) const
1160  {
1161  // the slice operator already provides bounds checking. just including
1162  // the at method for completeness
1163  return operator()(rowIndices, colIndices);
1164  }
1165 
1166  //============================================================================
1167  // Method Description:
1171  iterator begin() noexcept
1172  {
1173  return iterator(array_);
1174  }
1175 
1176  //============================================================================
1177  // Method Description:
1184  {
1185  if (inRow >= shape_.rows)
1186  {
1187  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1188  }
1189 
1190  return begin() += (inRow * shape_.cols);
1191  }
1192 
1193  //============================================================================
1194  // Method Description:
1198  const_iterator begin() const noexcept
1199  {
1200  return cbegin();
1201  }
1202 
1203  //============================================================================
1204  // Method Description:
1211  {
1212  return cbegin(inRow);
1213  }
1214 
1215  //============================================================================
1216  // Method Description:
1221  const_iterator cbegin() const noexcept
1222  {
1223  return const_iterator(array_);
1224  }
1225 
1226  //============================================================================
1227  // Method Description:
1234  {
1235  if (inRow >= shape_.rows)
1236  {
1237  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1238  }
1239 
1240  return cbegin() += (inRow * shape_.cols);
1241  }
1242 
1243  //============================================================================
1244  // Method Description:
1249  {
1250  return column_iterator(array_, shape_.rows, shape_.cols);
1251  }
1252 
1253  //============================================================================
1254  // Method Description:
1261  {
1262  if (inCol >= shape_.cols)
1263  {
1264  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1265  }
1266 
1267  return colbegin() += (inCol * shape_.rows);
1268  }
1269 
1270  //============================================================================
1271  // Method Description:
1276  {
1277  return ccolbegin();
1278  }
1279 
1280  //============================================================================
1281  // Method Description:
1288  {
1289  return ccolbegin(inCol);
1290  }
1291 
1292  //============================================================================
1293  // Method Description:
1299  {
1300  return const_column_iterator(array_, shape_.rows, shape_.cols);
1301  }
1302 
1303  //============================================================================
1304  // Method Description:
1311  {
1312  if (inCol >= shape_.cols)
1313  {
1314  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1315  }
1316 
1317  return ccolbegin() += (inCol * shape_.rows);
1318  }
1319 
1320  //============================================================================
1321  // Method Description:
1326  {
1327  return reverse_iterator(end());
1328  }
1329 
1330  //============================================================================
1331  // Method Description:
1338  {
1339  if (inRow >= shape_.rows)
1340  {
1341  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1342  }
1343 
1344  return rbegin() += (shape_.rows - inRow - 1) * shape_.cols;
1345  }
1346 
1347  //============================================================================
1348  // Method Description:
1353  {
1354  return crbegin();
1355  }
1356 
1357  //============================================================================
1358  // Method Description:
1365  {
1366  return crbegin(inRow);
1367  }
1368 
1369  //============================================================================
1370  // Method Description:
1376  {
1377  return const_reverse_iterator(cend());
1378  }
1379 
1380  //============================================================================
1381  // Method Description:
1388  {
1389  if (inRow >= shape_.rows)
1390  {
1391  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1392  }
1393 
1394  return crbegin() += (shape_.rows - inRow - 1) * shape_.cols;
1395  }
1396 
1397  //============================================================================
1398  // Method Description:
1403  {
1404  return reverse_column_iterator(colend());
1405  }
1406 
1407  //============================================================================
1408  // Method Description:
1415  {
1416  if (inCol >= shape_.cols)
1417  {
1418  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1419  }
1420 
1421  return rcolbegin() += (shape_.cols - inCol - 1) * shape_.rows;
1422  }
1423 
1424  //============================================================================
1425  // Method Description:
1430  {
1431  return crcolbegin();
1432  }
1433 
1434  //============================================================================
1435  // Method Description:
1442  {
1443  return crcolbegin(inCol);
1444  }
1445 
1446  //============================================================================
1447  // Method Description:
1453  {
1455  }
1456 
1457  //============================================================================
1458  // Method Description:
1465  {
1466  if (inCol >= shape_.cols)
1467  {
1468  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1469  }
1470 
1471  return crcolbegin() += (shape_.cols - inCol - 1) * shape_.rows;
1472  }
1473 
1474  //============================================================================
1475  // Method Description:
1479  iterator end() noexcept
1480  {
1481  return begin() += size_;
1482  }
1483 
1484  //============================================================================
1485  // Method Description:
1492  {
1493  if (inRow >= shape_.rows)
1494  {
1495  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1496  }
1497 
1498  return begin(inRow) += shape_.cols;
1499  }
1500 
1501  //============================================================================
1502  // Method Description:
1506  const_iterator end() const noexcept
1507  {
1508  return cend();
1509  }
1510 
1511  //============================================================================
1512  // Method Description:
1519  {
1520  return cend(inRow);
1521  }
1522 
1523  //============================================================================
1524  // Method Description:
1529  const_iterator cend() const noexcept
1530  {
1531  return cbegin() += size_;
1532  }
1533 
1534  //============================================================================
1535  // Method Description:
1542  {
1543  if (inRow >= shape_.rows)
1544  {
1545  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1546  }
1547 
1548  return cbegin(inRow) += shape_.cols;
1549  }
1550 
1551  //============================================================================
1552  // Method Description:
1557  {
1558  return rbegin() += size_;
1559  }
1560 
1561  //============================================================================
1562  // Method Description:
1569  {
1570  if (inRow >= shape_.rows)
1571  {
1572  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1573  }
1574 
1575  return rbegin(inRow) += shape_.cols;
1576  }
1577 
1578  //============================================================================
1579  // Method Description:
1583  const_reverse_iterator rend() const noexcept
1584  {
1585  return crend();
1586  }
1587 
1588  //============================================================================
1589  // Method Description:
1596  {
1597  return crend(inRow);
1598  }
1599 
1600  //============================================================================
1601  // Method Description:
1607  {
1608  return crbegin() += size_;
1609  }
1610 
1611  //============================================================================
1612  // Method Description:
1619  {
1620  if (inRow >= shape_.rows)
1621  {
1622  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1623  }
1624 
1625  return crbegin(inRow) += shape_.cols;
1626  }
1627 
1628  //============================================================================
1629  // Method Description:
1634  {
1635  return colbegin() += size_;
1636  }
1637 
1638  //============================================================================
1639  // Method Description:
1646  {
1647  if (inCol >= shape_.cols)
1648  {
1649  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1650  }
1651 
1652  return colbegin(inCol) += shape_.rows;
1653  }
1654 
1655  //============================================================================
1656  // Method Description:
1661  {
1662  return ccolend();
1663  }
1664 
1665  //============================================================================
1666  // Method Description:
1673  {
1674  return ccolend(inCol);
1675  }
1676 
1677  //============================================================================
1678  // Method Description:
1684  {
1685  return ccolbegin() += size_;
1686  }
1687 
1688  //============================================================================
1689  // Method Description:
1696  {
1697  if (inCol >= shape_.cols)
1698  {
1699  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1700  }
1701 
1702  return ccolbegin(inCol) += shape_.rows;
1703  }
1704 
1705  //============================================================================
1706  // Method Description:
1711  {
1712  return rcolbegin() += size_;
1713  }
1714 
1715  //============================================================================
1716  // Method Description:
1723  {
1724  if (inCol >= shape_.cols)
1725  {
1726  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1727  }
1728 
1729  return rcolbegin(inCol) += shape_.rows;
1730  }
1731 
1732  //============================================================================
1733  // Method Description:
1738  {
1739  return crcolend();
1740  }
1741 
1742  //============================================================================
1743  // Method Description:
1750  {
1751  return crcolend(inCol);
1752  }
1753 
1754  //============================================================================
1755  // Method Description:
1761  {
1762  return crcolbegin() += size_;
1763  }
1764 
1765  //============================================================================
1766  // Method Description:
1773  {
1774  if (inCol >= shape_.cols)
1775  {
1776  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1777  }
1778 
1779  return crcolbegin(inCol) += shape_.rows;
1780  }
1781 
1782  //============================================================================
1783  // Method Description:
1792  {
1794 
1795  const auto function = [](dtype i) -> bool { return i != dtype{ 0 }; };
1796 
1797  switch (inAxis)
1798  {
1799  case Axis::NONE:
1800  {
1801  NdArray<bool> returnArray = { stl_algorithms::all_of(cbegin(), cend(), function) };
1802  return returnArray;
1803  }
1804  case Axis::COL:
1805  {
1806  NdArray<bool> returnArray(1, shape_.rows);
1807  for (uint32 row = 0; row < shape_.rows; ++row)
1808  {
1809  returnArray(0, row) = stl_algorithms::all_of(cbegin(row), cend(row), function);
1810  }
1811 
1812  return returnArray;
1813  }
1814  case Axis::ROW:
1815  {
1816  NdArray<dtype> arrayTransposed = transpose();
1817  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
1818  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1819  {
1820  returnArray(0, row) =
1821  stl_algorithms::all_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
1822  }
1823 
1824  return returnArray;
1825  }
1826  default:
1827  {
1828  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1829  return {}; // get rid of compiler warning
1830  }
1831  }
1832  }
1833 
1834  //============================================================================
1835  // Method Description:
1844  {
1846 
1847  const auto function = [](dtype i) -> bool { return i != dtype{ 0 }; };
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) =
1873  stl_algorithms::any_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
1874  }
1875 
1876  return returnArray;
1877  }
1878  default:
1879  {
1880  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1881  return {}; // get rid of compiler warning
1882  }
1883  }
1884  }
1885 
1886  //============================================================================
1887  // Method Description:
1897  {
1899 
1900  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
1901 
1902  switch (inAxis)
1903  {
1904  case Axis::NONE:
1905  {
1906  NdArray<uint32> returnArray = { static_cast<uint32>(
1907  stl_algorithms::max_element(cbegin(), cend(), comparitor) - cbegin()) };
1908  return returnArray;
1909  }
1910  case Axis::COL:
1911  {
1912  NdArray<uint32> returnArray(1, shape_.rows);
1913  for (uint32 row = 0; row < shape_.rows; ++row)
1914  {
1915  returnArray(0, row) = static_cast<uint32>(
1916  stl_algorithms::max_element(cbegin(row), cend(row), comparitor) - cbegin(row));
1917  }
1918 
1919  return returnArray;
1920  }
1921  case Axis::ROW:
1922  {
1923  NdArray<dtype> arrayTransposed = transpose();
1924  NdArray<uint32> returnArray(1, arrayTransposed.shape_.rows);
1925  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1926  {
1927  returnArray(0, row) =
1928  static_cast<uint32>(stl_algorithms::max_element(arrayTransposed.cbegin(row),
1929  arrayTransposed.cend(row),
1930  comparitor) -
1931  arrayTransposed.cbegin(row));
1932  }
1933 
1934  return returnArray;
1935  }
1936  default:
1937  {
1938  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1939  return {}; // get rid of compiler warning
1940  }
1941  }
1942  }
1943 
1944  //============================================================================
1945  // Method Description:
1955  {
1957 
1958  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
1959 
1960  switch (inAxis)
1961  {
1962  case Axis::NONE:
1963  {
1964  NdArray<uint32> returnArray = { static_cast<uint32>(
1965  stl_algorithms::min_element(cbegin(), cend(), comparitor) - cbegin()) };
1966  return returnArray;
1967  }
1968  case Axis::COL:
1969  {
1970  NdArray<uint32> returnArray(1, shape_.rows);
1971  for (uint32 row = 0; row < shape_.rows; ++row)
1972  {
1973  returnArray(0, row) = static_cast<uint32>(
1974  stl_algorithms::min_element(cbegin(row), cend(row), comparitor) - cbegin(row));
1975  }
1976 
1977  return returnArray;
1978  }
1979  case Axis::ROW:
1980  {
1981  NdArray<dtype> arrayTransposed = transpose();
1982  NdArray<uint32> returnArray(1, arrayTransposed.shape_.rows);
1983  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1984  {
1985  returnArray(0, row) =
1986  static_cast<uint32>(stl_algorithms::min_element(arrayTransposed.cbegin(row),
1987  arrayTransposed.cend(row),
1988  comparitor) -
1989  arrayTransposed.cbegin(row));
1990  }
1991 
1992  return returnArray;
1993  }
1994  default:
1995  {
1996  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1997  return {}; // get rid of compiler warning
1998  }
1999  }
2000  }
2001 
2002  //============================================================================
2003  // Method Description:
2012  {
2014 
2015  switch (inAxis)
2016  {
2017  case Axis::NONE:
2018  {
2019  std::vector<uint32> idx(size_);
2020  std::iota(idx.begin(), idx.end(), 0);
2021 
2022  const auto function = [this](uint32 i1, uint32 i2) noexcept -> bool
2023  { return (*this)[i1] < (*this)[i2]; };
2024 
2025  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2026  return NdArray<uint32>(idx);
2027  }
2028  case Axis::COL:
2029  {
2030  NdArray<uint32> returnArray(shape_);
2031  std::vector<uint32> idx(shape_.cols);
2032 
2033  for (uint32 row = 0; row < shape_.rows; ++row)
2034  {
2035  std::iota(idx.begin(), idx.end(), 0);
2036 
2037  const auto function = [this, row](uint32 i1, uint32 i2) noexcept -> bool
2038  { return operator()(row, i1) < operator()(row, i2); };
2039 
2040  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2041 
2042  for (uint32 col = 0; col < shape_.cols; ++col)
2043  {
2044  returnArray(row, col) = idx[col];
2045  }
2046  }
2047  return returnArray;
2048  }
2049  case Axis::ROW:
2050  {
2051  NdArray<dtype> arrayTransposed = transpose();
2052  NdArray<uint32> returnArray(shape_.cols, shape_.rows);
2053  std::vector<uint32> idx(arrayTransposed.shape_.cols);
2054 
2055  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
2056  {
2057  std::iota(idx.begin(), idx.end(), 0);
2058 
2059  const auto function = [&arrayTransposed, row](uint32 i1, uint32 i2) noexcept -> bool
2060  { return arrayTransposed(row, i1) < arrayTransposed(row, i2); };
2061 
2062  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2063 
2064  for (uint32 col = 0; col < arrayTransposed.shape_.cols; ++col)
2065  {
2066  returnArray(row, col) = idx[col];
2067  }
2068  }
2069  return returnArray.transpose();
2070  }
2071  default:
2072  {
2073  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2074  return {}; // get rid of compiler warning
2075  }
2076  }
2077  }
2078 
2079  //============================================================================
2080  // Method Description:
2088  template<typename dtypeOut,
2089  typename dtype_ = dtype,
2094  {
2095  NdArray<dtypeOut> outArray(shape_);
2097  cend(),
2098  outArray.begin(),
2099  [](dtype value) -> dtypeOut { return static_cast<dtypeOut>(value); });
2100 
2101  return outArray;
2102  }
2103 
2104  //============================================================================
2105  // Method Description:
2113  template<typename dtypeOut,
2114  typename dtype_ = dtype,
2119  {
2120  NdArray<dtypeOut> outArray(shape_);
2121 
2122  const auto function = [](const_reference value) -> dtypeOut
2123  { return std::complex<typename dtypeOut::value_type>(value); };
2124 
2125  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2126 
2127  return outArray;
2128  }
2129 
2130  //============================================================================
2131  // Method Description:
2139  template<typename dtypeOut,
2140  typename dtype_ = dtype,
2145  {
2146  NdArray<dtypeOut> outArray(shape_);
2147 
2148  if (is_same_v<dtypeOut, dtype>)
2149  {
2150  std::copy(cbegin(), cend(), outArray.begin());
2151  }
2152  else
2153  {
2154  const auto function = [](const_reference value) noexcept -> dtypeOut
2155  { return complex_cast<typename dtypeOut::value_type>(value); };
2156 
2157  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2158  }
2159 
2160  return outArray;
2161  }
2162 
2163  //============================================================================
2164  // Method Description:
2172  template<typename dtypeOut,
2173  typename dtype_ = dtype,
2178  {
2179  NdArray<dtypeOut> outArray(shape_);
2180 
2181  const auto function = [](const_reference value) -> dtypeOut { return static_cast<dtypeOut>(value.real()); };
2182 
2183  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2184 
2185  return outArray;
2186  }
2187 
2188  //============================================================================
2189  // Method Description:
2194  const_reference back() const noexcept
2195  {
2196  return *(cend() - 1);
2197  }
2198 
2199  //============================================================================
2200  // Method Description:
2205  reference back() noexcept
2206  {
2207  return *(end() - 1);
2208  }
2209 
2210  //============================================================================
2211  // Method Description:
2217  {
2218  return *(cend(row) - 1);
2219  }
2220 
2221  //============================================================================
2222  // Method Description:
2228  {
2229  return *(end(row) - 1);
2230  }
2231 
2232  //============================================================================
2233  // Method Description:
2241  {
2242  STATIC_ASSERT_INTEGER(dtype);
2243 
2245  end(),
2246  [](dtype& value) noexcept -> void { value = endian::byteSwap(value); });
2247 
2248  switch (endianess_)
2249  {
2250  case Endian::NATIVE:
2251  {
2253  break;
2254  }
2255  case Endian::LITTLE:
2256  {
2257  endianess_ = Endian::BIG;
2258  break;
2259  }
2260  case Endian::BIG:
2261  {
2262  endianess_ = Endian::LITTLE;
2263  break;
2264  }
2265  }
2266 
2267  return *this;
2268  }
2269 
2270  //============================================================================
2271  // Method Description:
2281  {
2283 
2284  NdArray<dtype> outArray(shape_);
2286  cend(),
2287  outArray.begin(),
2288  [inMin, inMax](dtype value) noexcept -> dtype
2289  {
2290 #ifdef __cpp_lib_clamp
2291  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
2292  { return lhs < rhs; };
2293 
2294  return std::clamp(value, inMin, inMax, comparitor);
2295 #else
2296  if (value < inMin)
2297  {
2298  return inMin;
2299  }
2300  else if (value > inMax)
2301  {
2302  return inMax;
2303  }
2304 
2305  return value;
2306 #endif
2307  });
2308 
2309  return outArray;
2310  }
2311 
2312  //============================================================================
2313  // Method Description:
2320  {
2321  return operator()(rSlice(), inColumn);
2322  }
2323 
2324  //============================================================================
2325  // Method Description:
2333  {
2335 
2336  switch (inAxis)
2337  {
2338  case Axis::NONE:
2339  {
2340  NdArray<bool> returnArray = { stl_algorithms::find(cbegin(), cend(), inValue) != cend() };
2341  return returnArray;
2342  }
2343  case Axis::COL:
2344  {
2345  NdArray<bool> returnArray(1, shape_.rows);
2346  for (uint32 row = 0; row < shape_.rows; ++row)
2347  {
2348  returnArray(0, row) = stl_algorithms::find(cbegin(row), cend(row), inValue) != cend(row);
2349  }
2350 
2351  return returnArray;
2352  }
2353  case Axis::ROW:
2354  {
2355  NdArray<dtype> transArray = transpose();
2356  NdArray<bool> returnArray(1, transArray.shape_.rows);
2357  for (uint32 row = 0; row < transArray.shape_.rows; ++row)
2358  {
2359  returnArray(0, row) =
2360  stl_algorithms::find(transArray.cbegin(row), transArray.cend(row), inValue) !=
2361  transArray.cend(row);
2362  }
2363 
2364  return returnArray;
2365  }
2366  default:
2367  {
2368  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2369  return {}; // get rid of compiler warning
2370  }
2371  }
2372  }
2373 
2374  //============================================================================
2375  // Method Description:
2383  {
2384  return NdArray<dtype>(*this);
2385  }
2386 
2387  //============================================================================
2388  // Method Description:
2397  {
2399 
2400  switch (inAxis)
2401  {
2402  case Axis::NONE:
2403  {
2404  NdArray<dtype> returnArray(1, size_);
2405  returnArray[0] = front();
2406  for (uint32 i = 1; i < size_; ++i)
2407  {
2408  returnArray[i] = returnArray[i - 1] * array_[i];
2409  }
2410 
2411  return returnArray;
2412  }
2413  case Axis::COL:
2414  {
2415  NdArray<dtype> returnArray(shape_);
2416  for (uint32 row = 0; row < shape_.rows; ++row)
2417  {
2418  returnArray(row, 0) = operator()(row, 0);
2419  for (uint32 col = 1; col < shape_.cols; ++col)
2420  {
2421  returnArray(row, col) = returnArray(row, col - 1) * operator()(row, col);
2422  }
2423  }
2424 
2425  return returnArray;
2426  }
2427  case Axis::ROW:
2428  {
2429  NdArray<dtype> returnArray(shape_);
2430  for (uint32 col = 0; col < shape_.cols; ++col)
2431  {
2432  returnArray(0, col) = operator()(0, col);
2433  for (uint32 row = 1; row < shape_.rows; ++row)
2434  {
2435  returnArray(row, col) = returnArray(row - 1, col) * operator()(row, col);
2436  }
2437  }
2438 
2439  return returnArray;
2440  }
2441  default:
2442  {
2443  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2444  return {}; // get rid of compiler warning
2445  }
2446  }
2447  }
2448 
2449  //============================================================================
2450  // Method Description:
2459  {
2461 
2462  switch (inAxis)
2463  {
2464  case Axis::NONE:
2465  {
2466  NdArray<dtype> returnArray(1, size_);
2467  returnArray[0] = front();
2468  for (uint32 i = 1; i < size_; ++i)
2469  {
2470  returnArray[i] = returnArray[i - 1] + array_[i];
2471  }
2472 
2473  return returnArray;
2474  }
2475  case Axis::COL:
2476  {
2477  NdArray<dtype> returnArray(shape_);
2478  for (uint32 row = 0; row < shape_.rows; ++row)
2479  {
2480  returnArray(row, 0) = operator()(row, 0);
2481  for (uint32 col = 1; col < shape_.cols; ++col)
2482  {
2483  returnArray(row, col) = returnArray(row, col - 1) + operator()(row, col);
2484  }
2485  }
2486 
2487  return returnArray;
2488  }
2489  case Axis::ROW:
2490  {
2491  NdArray<dtype> returnArray(shape_);
2492  for (uint32 col = 0; col < shape_.cols; ++col)
2493  {
2494  returnArray(0, col) = operator()(0, col);
2495  for (uint32 row = 1; row < shape_.rows; ++row)
2496  {
2497  returnArray(row, col) = returnArray(row - 1, col) + operator()(row, col);
2498  }
2499  }
2500 
2501  return returnArray;
2502  }
2503  default:
2504  {
2505  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2506  return {}; // get rid of compiler warning
2507  }
2508  }
2509  }
2510 
2511  //============================================================================
2512  // Method Description:
2516  pointer data() noexcept
2517  {
2518  return array_;
2519  }
2520 
2521  //============================================================================
2522  // Method Description:
2526  const_pointer data() const noexcept
2527  {
2528  return array_;
2529  }
2530 
2531  //============================================================================
2532  // Method Description:
2539  {
2540  ownsPtr_ = false;
2541  return data();
2542  }
2543 
2544  //============================================================================
2545  // Method Description:
2555  NdArray<dtype> diagonal(int32 inOffset = 0, Axis inAxis = Axis::ROW) const
2556  {
2557  switch (inAxis)
2558  {
2559  case Axis::ROW:
2560  {
2561  std::vector<dtype> diagnolValues;
2562  int32 col = inOffset;
2563  for (uint32 row = 0; row < shape_.rows; ++row)
2564  {
2565  if (col < 0)
2566  {
2567  ++col;
2568  continue;
2569  }
2570  if (col >= static_cast<int32>(shape_.cols))
2571  {
2572  break;
2573  }
2574 
2575  diagnolValues.push_back(operator()(row, static_cast<uint32>(col)));
2576  ++col;
2577  }
2578 
2579  return NdArray<dtype>(diagnolValues);
2580  }
2581  case Axis::COL:
2582  {
2583  std::vector<dtype> diagnolValues;
2584  uint32 col = 0;
2585  for (int32 row = inOffset; row < static_cast<int32>(shape_.rows); ++row)
2586  {
2587  if (row < 0)
2588  {
2589  ++col;
2590  continue;
2591  }
2592  if (col >= shape_.cols)
2593  {
2594  break;
2595  }
2596 
2597  diagnolValues.push_back(operator()(static_cast<uint32>(row), col));
2598  ++col;
2599  }
2600 
2601  return NdArray<dtype>(diagnolValues);
2602  }
2603  default:
2604  {
2605  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2606  return {}; // get rid of compiler warning
2607  }
2608  }
2609  }
2610 
2611  //============================================================================
2612  // Method Description:
2623  NdArray<dtype> dot(const NdArray<dtype>& inOtherArray) const
2624  {
2626 
2627  if (shape_ == inOtherArray.shape_ && (shape_.rows == 1 || shape_.cols == 1))
2628  {
2629  dtype dotProduct = std::inner_product(cbegin(), cend(), inOtherArray.cbegin(), dtype{ 0 });
2630  NdArray<dtype> returnArray = { dotProduct };
2631  return returnArray;
2632  }
2633  if (shape_.cols == inOtherArray.shape_.rows)
2634  {
2635  // 2D array, use matrix multiplication
2636  NdArray<dtype> returnArray(shape_.rows, inOtherArray.shape_.cols);
2637  auto otherArrayT = inOtherArray.transpose();
2638 
2639  for (uint32 i = 0; i < shape_.rows; ++i)
2640  {
2641  for (uint32 j = 0; j < otherArrayT.shape_.rows; ++j)
2642  {
2643  returnArray(i, j) =
2644  std::inner_product(otherArrayT.cbegin(j), otherArrayT.cend(j), cbegin(i), dtype{ 0 });
2645  }
2646  }
2647 
2648  return returnArray;
2649  }
2650 
2651  std::string errStr = "shapes of [" + utils::num2str(shape_.rows) + ", " + utils::num2str(shape_.cols) + "]";
2652  errStr += " and [" + utils::num2str(inOtherArray.shape_.rows) + ", " +
2653  utils::num2str(inOtherArray.shape_.cols) + "]";
2654  errStr += " are not consistent.";
2656 
2657  return NdArray<dtype>(); // get rid of compiler warning
2658  }
2659 
2660  //============================================================================
2661  // Method Description:
2669  void dump(const std::string& inFilename) const
2670  {
2671  filesystem::File f(inFilename);
2672  if (!f.hasExt())
2673  {
2674  f.withExt(".bin");
2675  }
2676 
2677  std::ofstream ofile(f.fullName().c_str(), std::ios::binary);
2678  if (!ofile.good())
2679  {
2680  THROW_RUNTIME_ERROR("Unable to open the input file:\n\t" + inFilename);
2681  }
2682 
2683  if (array_ != nullptr)
2684  {
2685  ofile.write(reinterpret_cast<const char*>(array_), size_ * sizeof(dtype));
2686  }
2687  ofile.close();
2688  }
2689 
2690  //============================================================================
2691  // Method Description:
2696  Endian endianess() const noexcept
2697  {
2698  STATIC_ASSERT_ARITHMETIC(dtype);
2699 
2700  return endianess_;
2701  }
2702 
2703  //============================================================================
2704  // Method Description:
2712  NdArray<dtype>& fill(value_type inFillValue) noexcept
2713  {
2714  stl_algorithms::fill(begin(), end(), inFillValue);
2715  return *this;
2716  }
2717 
2718  //============================================================================
2719  // Method Description:
2726  {
2728 
2729  std::vector<uint32> indices;
2730  uint32 idx = 0;
2731  for (auto value : *this)
2732  {
2733  if (value != dtype{ 0 })
2734  {
2735  indices.push_back(idx);
2736  }
2737  ++idx;
2738  }
2739 
2740  return NdArray<uint32>(indices);
2741  }
2742 
2743  //============================================================================
2744  // Method Description:
2752  {
2753  NdArray<dtype> outArray(1, size_);
2754  stl_algorithms::copy(cbegin(), cend(), outArray.begin());
2755  return outArray;
2756  }
2757 
2758  //============================================================================
2759  // Method Description:
2764  const_reference front() const noexcept
2765  {
2766  return *cbegin();
2767  }
2768 
2769  //============================================================================
2770  // Method Description:
2775  reference front() noexcept
2776  {
2777  return *begin();
2778  }
2779 
2780  //============================================================================
2781  // Method Description:
2787  {
2788  return *cbegin(row);
2789  }
2790 
2791  //============================================================================
2792  // Method Description:
2798  {
2799  return *begin(row);
2800  }
2801 
2802  //============================================================================
2803  // Method Description:
2810  {
2811  return operator[](inIndices);
2812  }
2813 
2814  //============================================================================
2815  // Method Description:
2824  {
2825  return operator[](inMask);
2826  }
2827 
2828  //============================================================================
2829  // Method Description:
2835  bool isempty() const noexcept
2836  {
2837  return size_ == 0;
2838  }
2839 
2840  //============================================================================
2841  // Method Description:
2847  bool isflat() const noexcept
2848  {
2849  return shape_.rows == 1 || shape_.cols == 1;
2850  }
2851 
2852  //============================================================================
2853  // Method Description:
2860  {
2862 
2863  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
2864 
2865  switch (inAxis)
2866  {
2867  case Axis::NONE:
2868  {
2869  return { stl_algorithms::is_sorted(cbegin(), cend(), comparitor) };
2870  }
2871  case Axis::ROW:
2872  {
2873  NdArray<bool> returnArray(shape_.cols, 1);
2874  auto transposedArray = transpose();
2875  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
2876  {
2877  returnArray(0, row) = stl_algorithms::is_sorted(transposedArray.cbegin(row),
2878  transposedArray.cend(row),
2879  comparitor);
2880  }
2881 
2882  return returnArray;
2883  }
2884  case Axis::COL:
2885  {
2886  NdArray<bool> returnArray(1, shape_.rows);
2887  for (uint32 row = 0; row < shape_.rows; ++row)
2888  {
2889  returnArray(0, row) = stl_algorithms::is_sorted(cbegin(row), cend(row), comparitor);
2890  }
2891 
2892  return returnArray;
2893  }
2894  default:
2895  {
2896  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2897  return {}; // get rid of compiler warning
2898  }
2899  }
2900  }
2901 
2902  //============================================================================
2903  // Method Description:
2908  bool issquare() const noexcept
2909  {
2910  return shape_.issquare();
2911  }
2912 
2913  //============================================================================
2914  // Method Description:
2922  {
2923  if (size_ != 1)
2924  {
2925  THROW_INVALID_ARGUMENT_ERROR("Can only convert an array of size 1 to a C++ scaler");
2926  }
2927 
2928  return front();
2929  }
2930 
2931  //============================================================================
2932  // Method Description:
2941  {
2943 
2944  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
2945 
2946  switch (inAxis)
2947  {
2948  case Axis::NONE:
2949  {
2950  NdArray<dtype> returnArray = { *stl_algorithms::max_element(cbegin(), cend(), comparitor) };
2951  return returnArray;
2952  }
2953  case Axis::COL:
2954  {
2955  NdArray<dtype> returnArray(1, shape_.rows);
2956  for (uint32 row = 0; row < shape_.rows; ++row)
2957  {
2958  returnArray(0, row) = *stl_algorithms::max_element(cbegin(row), cend(row), comparitor);
2959  }
2960 
2961  return returnArray;
2962  }
2963  case Axis::ROW:
2964  {
2965  NdArray<dtype> transposedArray = transpose();
2966  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
2967  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
2968  {
2969  returnArray(0, row) = *stl_algorithms::max_element(transposedArray.cbegin(row),
2970  transposedArray.cend(row),
2971  comparitor);
2972  }
2973 
2974  return returnArray;
2975  }
2976  default:
2977  {
2978  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2979  return {}; // get rid of compiler warning
2980  }
2981  }
2982  }
2983 
2984  //============================================================================
2985  // Method Description:
2994  {
2996 
2997  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
2998 
2999  switch (inAxis)
3000  {
3001  case Axis::NONE:
3002  {
3003  NdArray<dtype> returnArray = { *stl_algorithms::min_element(cbegin(), cend(), comparitor) };
3004  return returnArray;
3005  }
3006  case Axis::COL:
3007  {
3008  NdArray<dtype> returnArray(1, shape_.rows);
3009  for (uint32 row = 0; row < shape_.rows; ++row)
3010  {
3011  returnArray(0, row) = *stl_algorithms::min_element(cbegin(row), cend(row), comparitor);
3012  }
3013 
3014  return returnArray;
3015  }
3016  case Axis::ROW:
3017  {
3018  NdArray<dtype> transposedArray = transpose();
3019  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3020  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3021  {
3022  returnArray(0, row) = *stl_algorithms::min_element(transposedArray.cbegin(row),
3023  transposedArray.cend(row),
3024  comparitor);
3025  }
3026 
3027  return returnArray;
3028  }
3029  default:
3030  {
3031  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3032  return {}; // get rid of compiler warning
3033  }
3034  }
3035  }
3036 
3037  //============================================================================
3038  // Method Description:
3049  {
3051 
3052  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
3053 
3054  if (size_ == 0)
3055  {
3056  THROW_RUNTIME_ERROR("Median is undefined for an array of size = 0.");
3057  }
3058 
3059  switch (inAxis)
3060  {
3061  case Axis::NONE:
3062  {
3063  NdArray<dtype> copyArray(*this);
3064 
3065  const uint32 middleIdx = size_ / 2; // integer division
3066  stl_algorithms::nth_element(copyArray.begin(),
3067  copyArray.begin() + middleIdx,
3068  copyArray.end(),
3069  comparitor);
3070 
3071  dtype medianValue = copyArray.array_[middleIdx];
3072  if (size_ % 2 == 0)
3073  {
3074  const uint32 lhsIndex = middleIdx - 1;
3075  stl_algorithms::nth_element(copyArray.begin(),
3076  copyArray.begin() + lhsIndex,
3077  copyArray.end(),
3078  comparitor);
3079  medianValue =
3080  (medianValue + copyArray.array_[lhsIndex]) / dtype{ 2 }; // potentially integer division, ok
3081  }
3082 
3083  return { medianValue };
3084  }
3085  case Axis::COL:
3086  {
3087  NdArray<dtype> copyArray(*this);
3088  NdArray<dtype> returnArray(1, shape_.rows);
3089 
3090  const bool isEven = shape_.cols % 2 == 0;
3091  for (uint32 row = 0; row < shape_.rows; ++row)
3092  {
3093  const uint32 middleIdx = shape_.cols / 2; // integer division
3094  stl_algorithms::nth_element(copyArray.begin(row),
3095  copyArray.begin(row) + middleIdx,
3096  copyArray.end(row),
3097  comparitor);
3098 
3099  dtype medianValue = copyArray(row, middleIdx);
3100  if (isEven)
3101  {
3102  const uint32 lhsIndex = middleIdx - 1;
3103  stl_algorithms::nth_element(copyArray.begin(row),
3104  copyArray.begin(row) + lhsIndex,
3105  copyArray.end(row),
3106  comparitor);
3107  medianValue = (medianValue + copyArray(row, lhsIndex)) /
3108  dtype{ 2 }; // potentially integer division, ok
3109  }
3110 
3111  returnArray(0, row) = medianValue;
3112  }
3113 
3114  return returnArray;
3115  }
3116  case Axis::ROW:
3117  {
3118  NdArray<dtype> transposedArray = transpose();
3119  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3120 
3121  const bool isEven = shape_.rows % 2 == 0;
3122  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3123  {
3124  const uint32 middleIdx = transposedArray.shape_.cols / 2; // integer division
3125  stl_algorithms::nth_element(transposedArray.begin(row),
3126  transposedArray.begin(row) + middleIdx,
3127  transposedArray.end(row),
3128  comparitor);
3129 
3130  dtype medianValue = transposedArray(row, middleIdx);
3131  if (isEven)
3132  {
3133  const uint32 lhsIndex = middleIdx - 1;
3134  stl_algorithms::nth_element(transposedArray.begin(row),
3135  transposedArray.begin(row) + lhsIndex,
3136  transposedArray.end(row),
3137  comparitor);
3138  medianValue = (medianValue + transposedArray(row, lhsIndex)) /
3139  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:
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 { return i != dtype{ 0 }; };
3359 
3360  switch (inAxis)
3361  {
3362  case Axis::NONE:
3363  {
3364  NdArray<bool> returnArray = { stl_algorithms::none_of(cbegin(), cend(), function) };
3365  return returnArray;
3366  }
3367  case Axis::COL:
3368  {
3369  NdArray<bool> returnArray(1, shape_.rows);
3370  for (uint32 row = 0; row < shape_.rows; ++row)
3371  {
3372  returnArray(0, row) = stl_algorithms::none_of(cbegin(row), cend(row), function);
3373  }
3374 
3375  return returnArray;
3376  }
3377  case Axis::ROW:
3378  {
3379  NdArray<dtype> arrayTransposed = transpose();
3380  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
3381  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
3382  {
3383  returnArray(0, row) =
3384  stl_algorithms::none_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
3385  }
3386 
3387  return returnArray;
3388  }
3389  default:
3390  {
3391  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3392  return {}; // get rid of compiler warning
3393  }
3394  }
3395  }
3396 
3397  //============================================================================
3398  // Method Description:
3407  std::pair<NdArray<uint32>, NdArray<uint32>> nonzero() const;
3408 
3409  //============================================================================
3410  // Method Description:
3416  uint32 numCols() const noexcept
3417  {
3418  return shape_.cols;
3419  }
3420 
3421  //============================================================================
3422  // Method Description:
3428  uint32 numRows() const noexcept
3429  {
3430  return shape_.rows;
3431  }
3432 
3433  //============================================================================
3434  // Method Description:
3438  NdArray<dtype>& ones() noexcept
3439  {
3441 
3442  fill(dtype{ 1 });
3443  return *this;
3444  }
3445 
3446  //============================================================================
3447  // Method Description:
3452  bool ownsInternalData() noexcept
3453  {
3454  return ownsPtr_;
3455  }
3456 
3457  //============================================================================
3458  // Method Description:
3473  {
3475 
3476  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
3477 
3478  switch (inAxis)
3479  {
3480  case Axis::NONE:
3481  {
3482  if (inKth >= size_)
3483  {
3484  std::string errStr = "kth(=" + utils::num2str(inKth);
3485  errStr += ") out of bounds (" + utils::num2str(size_) + ")";
3487  }
3488 
3489  stl_algorithms::nth_element(begin(), begin() + inKth, end(), comparitor);
3490  break;
3491  }
3492  case Axis::COL:
3493  {
3494  if (inKth >= shape_.cols)
3495  {
3496  std::string errStr = "kth(=" + utils::num2str(inKth);
3497  errStr += ") out of bounds (" + utils::num2str(shape_.cols) + ")";
3499  }
3500 
3501  for (uint32 row = 0; row < shape_.rows; ++row)
3502  {
3503  stl_algorithms::nth_element(begin(row), begin(row) + inKth, end(row), comparitor);
3504  }
3505  break;
3506  }
3507  case Axis::ROW:
3508  {
3509  if (inKth >= shape_.rows)
3510  {
3511  std::string errStr = "kth(=" + utils::num2str(inKth);
3512  errStr += ") out of bounds (" + utils::num2str(shape_.rows) + ")";
3514  }
3515 
3516  NdArray<dtype> transposedArray = transpose();
3517  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3518  {
3519  stl_algorithms::nth_element(transposedArray.begin(row),
3520  transposedArray.begin(row) + inKth,
3521  transposedArray.end(row),
3522  comparitor);
3523  }
3524  *this = transposedArray.transpose();
3525  break;
3526  }
3527  }
3528 
3529  return *this;
3530  }
3531 
3532  //============================================================================
3533  // Method Description:
3537  void print() const
3538  {
3540 
3541  std::cout << *this;
3542  }
3543 
3544  //============================================================================
3545  // Method Description:
3554  {
3556 
3557  switch (inAxis)
3558  {
3559  case Axis::NONE:
3560  {
3561  dtype product = std::accumulate(cbegin(), cend(), dtype{ 1 }, std::multiplies<dtype>());
3562  NdArray<dtype> returnArray = { product };
3563  return returnArray;
3564  }
3565  case Axis::COL:
3566  {
3567  NdArray<dtype> returnArray(1, shape_.rows);
3568  for (uint32 row = 0; row < shape_.rows; ++row)
3569  {
3570  returnArray(0, row) =
3571  std::accumulate(cbegin(row), cend(row), dtype{ 1 }, std::multiplies<dtype>());
3572  }
3573 
3574  return returnArray;
3575  }
3576  case Axis::ROW:
3577  {
3578  NdArray<dtype> transposedArray = transpose();
3579  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3580  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3581  {
3582  returnArray(0, row) = std::accumulate(transposedArray.cbegin(row),
3583  transposedArray.cend(row),
3584  dtype{ 1 },
3585  std::multiplies<dtype>());
3586  }
3587 
3588  return returnArray;
3589  }
3590  default:
3591  {
3592  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3593  return {}; // get rid of compiler warning
3594  }
3595  }
3596  }
3597 
3598  //============================================================================
3599  // Method Description:
3608  {
3610 
3611  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
3612 
3613  switch (inAxis)
3614  {
3615  case Axis::NONE:
3616  {
3617  const auto result = stl_algorithms::minmax_element(cbegin(), cend(), comparitor);
3618  NdArray<dtype> returnArray = { *result.second - *result.first };
3619  return returnArray;
3620  }
3621  case Axis::COL:
3622  {
3623  NdArray<dtype> returnArray(1, shape_.rows);
3624  for (uint32 row = 0; row < shape_.rows; ++row)
3625  {
3626  const auto result = stl_algorithms::minmax_element(cbegin(row), cend(row), comparitor);
3627  returnArray(0, row) = *result.second - *result.first;
3628  }
3629 
3630  return returnArray;
3631  }
3632  case Axis::ROW:
3633  {
3634  NdArray<dtype> transposedArray = transpose();
3635  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3636  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3637  {
3638  const auto result = stl_algorithms::minmax_element(transposedArray.cbegin(row),
3639  transposedArray.cend(row),
3640  comparitor);
3641  returnArray(0, row) = *result.second - *result.first;
3642  }
3643 
3644  return returnArray;
3645  }
3646  default:
3647  {
3648  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3649  return {}; // get rid of compiler warning
3650  }
3651  }
3652  }
3653 
3654  //============================================================================
3655  // Method Description:
3663  NdArray<dtype>& put(int32 inIndex, value_type inValue)
3664  {
3665  at(inIndex) = inValue;
3666 
3667  return *this;
3668  }
3669 
3670  //============================================================================
3671  // Method Description:
3680  NdArray<dtype>& put(int32 inRow, int32 inCol, value_type inValue)
3681  {
3682  at(inRow, inCol) = inValue;
3683 
3684  return *this;
3685  }
3686 
3687  //============================================================================
3688  // Method Description:
3696  NdArray<dtype>& put(const NdArray<uint32>& inIndices, value_type inValue)
3697  {
3698  for (auto index : inIndices)
3699  {
3700  put(index, inValue);
3701  }
3702 
3703  return *this;
3704  }
3705 
3706  //============================================================================
3707  // Method Description:
3715  NdArray<dtype>& put(const NdArray<uint32>& inIndices, const NdArray<dtype>& inValues)
3716  {
3717  if (inIndices.size() != inValues.size())
3718  {
3719  THROW_INVALID_ARGUMENT_ERROR("Input indices do not match values dimensions.");
3720  }
3721 
3722  uint32 counter = 0;
3723  for (auto index : inIndices)
3724  {
3725  put(index, inValues[counter++]);
3726  }
3727 
3728  return *this;
3729  }
3730 
3731  //============================================================================
3732  // Method Description:
3740  NdArray<dtype>& put(const Slice& inSlice, value_type inValue)
3741  {
3742  Slice inSliceCopy(inSlice);
3743  inSliceCopy.makePositiveAndValidate(size_);
3744 
3745  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
3746  {
3747  put(i, inValue);
3748  }
3749 
3750  return *this;
3751  }
3752 
3753  //============================================================================
3754  // Method Description:
3762  NdArray<dtype>& put(const Slice& inSlice, const NdArray<dtype>& inValues)
3763  {
3764  Slice inSliceCopy(inSlice);
3765  inSliceCopy.makePositiveAndValidate(size_);
3766 
3767  std::vector<uint32> indices;
3768  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
3769  {
3770  indices.push_back(i);
3771  }
3772 
3773  return put(NdArray<uint32>(indices), inValues);
3774  }
3775 
3776  //============================================================================
3777  // Method Description:
3786  NdArray<dtype>& put(const Slice& inRowSlice, const Slice& inColSlice, value_type inValue)
3787  {
3788  Slice inRowSliceCopy(inRowSlice);
3789  Slice inColSliceCopy(inColSlice);
3790 
3791  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3792  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3793 
3794  std::vector<uint32> indices;
3795  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3796  {
3797  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3798  {
3799  put(row, col, inValue);
3800  }
3801  }
3802 
3803  return *this;
3804  }
3805 
3806  //============================================================================
3807  // Method Description:
3816  NdArray<dtype>& put(const Slice& inRowSlice, int32 inColIndex, value_type inValue)
3817  {
3818  Slice inRowSliceCopy(inRowSlice);
3819  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3820 
3821  std::vector<uint32> indices;
3822  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3823  {
3824  put(row, inColIndex, inValue);
3825  }
3826 
3827  return *this;
3828  }
3829 
3830  //============================================================================
3831  // Method Description:
3840  NdArray<dtype>& put(int32 inRowIndex, const Slice& inColSlice, value_type inValue)
3841  {
3842  Slice inColSliceCopy(inColSlice);
3843  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3844 
3845  std::vector<uint32> indices;
3846  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3847  {
3848  put(inRowIndex, col, inValue);
3849  }
3850 
3851  return *this;
3852  }
3853 
3854  //============================================================================
3855  // Method Description:
3864  NdArray<dtype>& put(const Slice& inRowSlice, const Slice& inColSlice, const NdArray<dtype>& inValues)
3865  {
3866  Slice inRowSliceCopy(inRowSlice);
3867  Slice inColSliceCopy(inColSlice);
3868 
3869  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3870  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3871 
3872  std::vector<uint32> indices;
3873  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3874  {
3875  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3876  {
3877  const uint32 index = row * shape_.cols + col;
3878  indices.push_back(index);
3879  }
3880  }
3881 
3882  return put(NdArray<uint32>(indices), inValues);
3883  }
3884 
3885  //============================================================================
3886  // Method Description:
3895  NdArray<dtype>& put(const Slice& inRowSlice, int32 inColIndex, const NdArray<dtype>& inValues)
3896  {
3897  Slice inRowSliceCopy(inRowSlice);
3898  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3899 
3900  std::vector<uint32> indices;
3901  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3902  {
3903  const uint32 index = row * shape_.cols + inColIndex;
3904  indices.push_back(index);
3905  }
3906 
3907  return put(NdArray<uint32>(indices), inValues);
3908  }
3909 
3910  //============================================================================
3911  // Method Description:
3920  NdArray<dtype>& put(int32 inRowIndex, const Slice& inColSlice, const NdArray<dtype>& inValues)
3921  {
3922  Slice inColSliceCopy(inColSlice);
3923  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3924 
3925  std::vector<uint32> indices;
3926  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3927  {
3928  const uint32 index = inRowIndex * shape_.cols + col;
3929  indices.push_back(index);
3930  }
3931 
3932  return put(NdArray<uint32>(indices), inValues);
3933  }
3934 
3935  //============================================================================
3936  // Method Description:
3943  {
3944  if (inMask.shape() != shape_)
3945  {
3946  THROW_INVALID_ARGUMENT_ERROR("input inMask must be the same shape as the array it is masking.");
3947  }
3948 
3949  return put(inMask.flatnonzero(), inValue);
3950  }
3951 
3952  //============================================================================
3953  // Method Description:
3959  NdArray<dtype>& putMask(const NdArray<bool>& inMask, const NdArray<dtype>& inValues)
3960  {
3961  if (inMask.shape() != shape_)
3962  {
3963  THROW_INVALID_ARGUMENT_ERROR("input inMask must be the same shape as the array it is masking.");
3964  }
3965 
3966  return put(inMask.flatnonzero(), inValues);
3967  }
3968 
3969  //============================================================================
3970  // Method Description:
3977  NdArray<dtype>& ravel() noexcept
3978  {
3979  reshape(size_);
3980  return *this;
3981  }
3982 
3983  //============================================================================
3984  // Method Description:
3993  NdArray<dtype> repeat(uint32 inNumRows, uint32 inNumCols) const
3994  {
3995  NdArray<dtype> returnArray(shape_.rows * inNumRows, shape_.cols * inNumCols);
3996 
3997  for (uint32 row = 0; row < inNumRows; ++row)
3998  {
3999  for (uint32 col = 0; col < inNumCols; ++col)
4000  {
4001  std::vector<uint32> indices(shape_.size());
4002 
4003  const uint32 rowStart = row * shape_.rows;
4004  const uint32 colStart = col * shape_.cols;
4005 
4006  const uint32 rowEnd = (row + 1) * shape_.rows;
4007  const uint32 colEnd = (col + 1) * shape_.cols;
4008 
4009  uint32 counter = 0;
4010  for (uint32 rowIdx = rowStart; rowIdx < rowEnd; ++rowIdx)
4011  {
4012  for (uint32 colIdx = colStart; colIdx < colEnd; ++colIdx)
4013  {
4014  indices[counter++] = rowIdx * returnArray.shape_.cols + colIdx;
4015  }
4016  }
4017 
4018  returnArray.put(NdArray<uint32>(indices), *this);
4019  }
4020  }
4021 
4022  return returnArray;
4023  }
4024 
4025  //============================================================================
4026  // Method Description:
4034  NdArray<dtype> repeat(const Shape& inRepeatShape) const
4035  {
4036  return repeat(inRepeatShape.rows, inRepeatShape.cols);
4037  }
4038 
4039  //============================================================================
4040  // Method Description:
4046  void replace(value_type oldValue, value_type newValue)
4047  {
4049 
4050  stl_algorithms::replace(begin(), end(), oldValue, newValue);
4051  }
4052 
4053  //============================================================================
4054  // Method Description:
4065  {
4066  if (inSize != size_)
4067  {
4068  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into shape ";
4069  errStr += "[" + utils::num2str(1) + ", " + utils::num2str(inSize) + "]";
4070  THROW_RUNTIME_ERROR(errStr);
4071  }
4072 
4073  shape_.rows = 1;
4074  shape_.cols = inSize;
4075 
4076  return *this;
4077  }
4078 
4079  //============================================================================
4080  // Method Description:
4091  NdArray<dtype>& reshape(int32 inNumRows, int32 inNumCols)
4092  {
4093  if (inNumRows < 0)
4094  {
4095  if (size_ % inNumCols == 0)
4096  {
4097  return reshape(size_ / inNumCols, inNumCols);
4098  }
4099 
4100  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into a shape ";
4101  errStr += "with " + utils::num2str(inNumCols) + " columns";
4103  }
4104 
4105  if (inNumCols < 0)
4106  {
4107  if (size_ % inNumRows == 0)
4108  {
4109  return reshape(inNumRows, size_ / inNumRows);
4110  }
4111 
4112  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into a shape ";
4113  errStr += "with " + utils::num2str(inNumRows) + " rows";
4115  }
4116 
4117  if (static_cast<uint32>(inNumRows * inNumCols) != size_)
4118  {
4119  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into shape ";
4120  errStr += "[" + utils::num2str(inNumRows) + ", " + utils::num2str(inNumCols) + "]";
4122  }
4123 
4124  shape_.rows = static_cast<uint32>(inNumRows);
4125  shape_.cols = static_cast<uint32>(inNumCols);
4126 
4127  return *this;
4128  }
4129 
4130  //============================================================================
4131  // Method Description:
4141  NdArray<dtype>& reshape(const Shape& inShape)
4142  {
4143  return reshape(inShape.rows, inShape.cols);
4144  }
4145 
4146  //============================================================================
4147  // Method Description:
4156  NdArray<dtype>& resizeFast(uint32 inNumRows, uint32 inNumCols)
4157  {
4158  newArray(Shape(inNumRows, inNumCols));
4159  return *this;
4160  }
4161 
4162  //============================================================================
4163  // Method Description:
4172  {
4173  return resizeFast(inShape.rows, inShape.cols);
4174  }
4175 
4176  //============================================================================
4177  // Method Description:
4188  NdArray<dtype>& resizeSlow(uint32 inNumRows, uint32 inNumCols)
4189  {
4190  std::vector<dtype> oldData(size_);
4191  stl_algorithms::copy(begin(), end(), oldData.begin());
4192 
4193  const Shape inShape(inNumRows, inNumCols);
4194  const Shape oldShape = shape_;
4195 
4196  newArray(inShape);
4197 
4198  for (uint32 row = 0; row < inShape.rows; ++row)
4199  {
4200  for (uint32 col = 0; col < inShape.cols; ++col)
4201  {
4202  if (row >= oldShape.rows || col >= oldShape.cols)
4203  {
4204  operator()(row, col) = dtype{ 0 }; // zero fill
4205  }
4206  else
4207  {
4208  operator()(row, col) = oldData[row * oldShape.cols + col];
4209  }
4210  }
4211  }
4212 
4213  return *this;
4214  }
4215 
4216  //============================================================================
4217  // Method Description:
4228  {
4229  return resizeSlow(inShape.rows, inShape.cols);
4230  }
4231 
4232  //============================================================================
4233  // Method Description:
4242  NdArray<dtype> round(uint8 inNumDecimals = 0) const
4243  {
4244  STATIC_ASSERT_FLOAT(dtype);
4245 
4246  NdArray<dtype> returnArray(shape_);
4247  const double multFactor = utils::power(10.0, inNumDecimals);
4248  const auto function = [multFactor](dtype value) noexcept -> dtype
4249  { return static_cast<dtype>(std::nearbyint(static_cast<double>(value) * multFactor) / multFactor); };
4250 
4251  stl_algorithms::transform(cbegin(), cend(), returnArray.begin(), function);
4252 
4253  return returnArray;
4254  }
4255 
4256  //============================================================================
4257  // Method Description:
4264  {
4265  return NdArray<dtype>(cbegin(inRow), cend(inRow));
4266  }
4267 
4268  //============================================================================
4269  // Method Description:
4276  Shape shape() const noexcept
4277  {
4278  return shape_;
4279  }
4280 
4281  //============================================================================
4282  // Method Description:
4289  size_type size() const noexcept
4290  {
4291  return size_;
4292  }
4293 
4294  //============================================================================
4295  // Method Description:
4304  {
4306 
4307  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
4308 
4309  switch (inAxis)
4310  {
4311  case Axis::NONE:
4312  {
4313  stl_algorithms::sort(begin(), end(), comparitor);
4314  break;
4315  }
4316  case Axis::COL:
4317  {
4318  for (uint32 row = 0; row < shape_.rows; ++row)
4319  {
4320  stl_algorithms::sort(begin(row), end(row), comparitor);
4321  }
4322  break;
4323  }
4324  case Axis::ROW:
4325  {
4326  NdArray<dtype> transposedArray = transpose();
4327  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
4328  {
4329  stl_algorithms::sort(transposedArray.begin(row), transposedArray.end(row), comparitor);
4330  }
4331 
4332  *this = transposedArray.transpose();
4333  break;
4334  }
4335  }
4336 
4337  return *this;
4338  }
4339 
4340  //============================================================================
4341  // Method Description:
4346  std::string str() const
4347  {
4349 
4350  std::string out;
4351  out += "[";
4352  for (uint32 row = 0; row < shape_.rows; ++row)
4353  {
4354  out += "[";
4355  for (uint32 col = 0; col < shape_.cols; ++col)
4356  {
4357  out += utils::value2str(operator()(row, col)) + ", ";
4358  }
4359 
4360  if (row == shape_.rows - 1)
4361  {
4362  out += "]";
4363  }
4364  else
4365  {
4366  out += "]\n";
4367  }
4368  }
4369  out += "]\n";
4370  return out;
4371  }
4372 
4373  //============================================================================
4374  // Method Description:
4383  {
4385 
4386  switch (inAxis)
4387  {
4388  case Axis::NONE:
4389  {
4390  NdArray<dtype> returnArray = { std::accumulate(cbegin(), cend(), dtype{ 0 }) };
4391  return returnArray;
4392  }
4393  case Axis::COL:
4394  {
4395  NdArray<dtype> returnArray(1, shape_.rows);
4396  for (uint32 row = 0; row < shape_.rows; ++row)
4397  {
4398  returnArray(0, row) = std::accumulate(cbegin(row), cend(row), dtype{ 0 });
4399  }
4400 
4401  return returnArray;
4402  }
4403  case Axis::ROW:
4404  {
4405  NdArray<dtype> transposedArray = transpose();
4406  const Shape transShape = transposedArray.shape();
4407  NdArray<dtype> returnArray(1, transShape.rows);
4408  for (uint32 row = 0; row < transShape.rows; ++row)
4409  {
4410  returnArray(0, row) =
4411  std::accumulate(transposedArray.cbegin(row), transposedArray.cend(row), dtype{ 0 });
4412  }
4413 
4414  return returnArray;
4415  }
4416  default:
4417  {
4418  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
4419  return {}; // get rid of compiler warning
4420  }
4421  }
4422  }
4423 
4424  //============================================================================
4425  // Method Description:
4433  {
4434  return transpose();
4435  }
4436 
4437  //============================================================================
4438  // Method Description:
4444  void swapCols(int32 colIdx1, int32 colIdx2) noexcept
4445  {
4446  for (int32 row = 0; row < static_cast<int32>(shape_.rows); ++row)
4447  {
4448  std::swap(operator()(row, colIdx1), operator()(row, colIdx2));
4449  }
4450  }
4451 
4452  //============================================================================
4453  // Method Description:
4459  void swapRows(int32 rowIdx1, int32 rowIdx2) noexcept
4460  {
4461  for (int32 col = 0; col < static_cast<int32>(shape_.cols); ++col)
4462  {
4463  std::swap(operator()(rowIdx1, col), operator()(rowIdx2, col));
4464  }
4465  }
4466 
4467  //============================================================================
4468  // Method Description:
4478  void tofile(const std::string& inFilename) const
4479  {
4480  dump(inFilename);
4481  }
4482 
4483  //============================================================================
4484  // Method Description:
4495  void tofile(const std::string& inFilename, const char inSep) const
4496  {
4498 
4499  filesystem::File f(inFilename);
4500  if (!f.hasExt())
4501  {
4502  f.withExt("txt");
4503  }
4504 
4505  std::ofstream ofile(f.fullName().c_str());
4506  if (!ofile.good())
4507  {
4508  THROW_RUNTIME_ERROR("Input file could not be opened:\n\t" + inFilename);
4509  }
4510 
4511  uint32 counter = 0;
4512  for (auto value : *this)
4513  {
4514  ofile << value;
4515  if (counter++ != size_ - 1)
4516  {
4517  ofile << inSep;
4518  }
4519  }
4520  ofile.close();
4521  }
4522 
4523  //============================================================================
4524  // Method Description:
4532  NdArray<uint32> toIndices(Slice inSlice, Axis inAxis = Axis::ROW) const
4533  {
4534  uint32 numElements = 0;
4535  switch (inAxis)
4536  {
4537  case Axis::NONE:
4538  {
4539  numElements = inSlice.numElements(size_);
4540  break;
4541  }
4542  case Axis::ROW:
4543  {
4544  numElements = inSlice.numElements(shape_.rows);
4545  break;
4546  }
4547  case Axis::COL:
4548  {
4549  numElements = inSlice.numElements(shape_.cols);
4550  break;
4551  }
4552  default:
4553  {
4554  // not actually possible, getting rid of compiler warning
4555  THROW_INVALID_ARGUMENT_ERROR("Invalid 'inAxis' option");
4556  }
4557  }
4558 
4559  if (numElements == 0)
4560  {
4561  return {};
4562  }
4563 
4564  NdArray<uint32> indices(1, numElements);
4565  indices[0] = inSlice.start;
4566  for (uint32 i = 1; i < indices.size(); ++i)
4567  {
4568  indices[i] = static_cast<uint32>(indices[i - 1] + inSlice.step);
4569  }
4570 
4571  return indices;
4572  }
4573 
4574  //============================================================================
4575  // Method Description:
4580  std::vector<dtype> toStlVector() const
4581  {
4582  return std::vector<dtype>(cbegin(), cend());
4583  }
4584 
4585  //============================================================================
4586  // Method Description:
4597  value_type trace(uint32 inOffset = 0, Axis inAxis = Axis::ROW) const noexcept
4598  {
4600 
4601  uint32 rowStart = 0;
4602  uint32 colStart = 0;
4603  switch (inAxis)
4604  {
4605  case Axis::ROW:
4606  {
4607  rowStart += inOffset;
4608  break;
4609  }
4610  case Axis::COL:
4611  {
4612  colStart += inOffset;
4613  break;
4614  }
4615  default:
4616  {
4617  // if the user input NONE, override back to ROW
4618  inAxis = Axis::ROW;
4619  break;
4620  }
4621  }
4622 
4623  if (rowStart >= shape_.rows || colStart >= shape_.cols)
4624  {
4625  return dtype{ 0 };
4626  }
4627 
4628  uint32 col = colStart;
4629  dtype sum = 0;
4630  for (uint32 row = rowStart; row < shape_.rows; ++row)
4631  {
4632  if (col >= shape_.cols)
4633  {
4634  break;
4635  }
4636  sum += operator()(row, col++);
4637  }
4638 
4639  return sum;
4640  }
4641 
4642  //============================================================================
4643  // Method Description:
4651  {
4652  NdArray<dtype> transArray(shape_.cols, shape_.rows);
4653  for (uint32 row = 0; row < shape_.rows; ++row)
4654  {
4655  for (uint32 col = 0; col < shape_.cols; ++col)
4656  {
4657  transArray(col, row) = operator()(row, col);
4658  }
4659  }
4660  return transArray;
4661  }
4662 
4663  //============================================================================
4664  // Method Description:
4668  NdArray<dtype>& zeros() noexcept
4669  {
4671 
4672  fill(dtype{ 0 });
4673  return *this;
4674  }
4675 
4676  private:
4677  //====================================Attributes==============================
4678  allocator_type allocator_{};
4679  Shape shape_{ 0, 0 };
4680  size_type size_{ 0 };
4681  Endian endianess_{ Endian::NATIVE };
4682  pointer array_{ nullptr };
4683  bool ownsPtr_{ false };
4684 
4685  //============================================================================
4686  // Method Description:
4689  void deleteArray() noexcept
4690  {
4691  if (ownsPtr_ && array_ != nullptr)
4692  {
4693  allocator_.deallocate(array_, size_);
4694  }
4695 
4696  array_ = nullptr;
4697  shape_.rows = shape_.cols = 0;
4698  size_ = 0;
4699  ownsPtr_ = false;
4700  endianess_ = Endian::NATIVE;
4701  }
4702 
4703  //============================================================================
4704  // Method Description:
4707  void newArray()
4708  {
4709  if (size_ > 0)
4710  {
4711  array_ = allocator_.allocate(size_);
4712  ownsPtr_ = true;
4713  }
4714  }
4715 
4716  //============================================================================
4717  // Method Description:
4722  void newArray(const Shape& inShape)
4723  {
4724  deleteArray();
4725 
4726  shape_ = inShape;
4727  size_ = inShape.size();
4728  newArray();
4729  }
4730  };
4731 
4732  // NOTE: this needs to be defined outside of the class to get rid of a compiler
4733  // error in Visual Studio
4734  template<typename dtype, class _Alloc>
4735  std::pair<NdArray<uint32>, NdArray<uint32>> NdArray<dtype, _Alloc>::nonzero() const
4736  {
4738 
4739  std::vector<uint32> rowIndices;
4740  std::vector<uint32> colIndices;
4741 
4742  for (uint32 row = 0; row < shape_.rows; ++row)
4743  {
4744  for (uint32 col = 0; col < shape_.cols; ++col)
4745  {
4746  if (operator()(row, col) != dtype{ 0 })
4747  {
4748  rowIndices.push_back(row);
4749  colIndices.push_back(col);
4750  }
4751  }
4752  }
4753 
4754  return std::make_pair(NdArray<uint32>(rowIndices), NdArray<uint32>(colIndices));
4755  }
4756 } // namespace nc
#define THROW_RUNTIME_ERROR(msg)
Definition: Error.hpp:38
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:36
#define STATIC_ASSERT_FLOAT(dtype)
Definition: StaticAsserts.hpp:45
#define STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype)
Definition: StaticAsserts.hpp:49
#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:818
Custom column const_iterator for NdArray.
Definition: NdArrayIterators.hpp:492
Custom const_iterator for NdArray.
Definition: NdArrayIterators.hpp:42
Holds 1D and 2D arrays, the main work horse of the NumCpp library.
Definition: NdArrayCore.hpp:72
uint32 numCols() const noexcept
Definition: NdArrayCore.hpp:3416
NdArray(std::vector< std::array< dtype, Dim1Size >> &in2dArray, bool copy=true)
Definition: NdArrayCore.hpp:323
const_reverse_column_iterator rcolbegin() const noexcept
Definition: NdArrayCore.hpp:1429
NdArray< dtype > at(const NdArray< int32 > &rowIndices, const NdArray< int32 > &colIndices) const
Definition: NdArrayCore.hpp:1159
NdArray< dtypeOut > astype() const
Definition: NdArrayCore.hpp:2093
NdArray< dtype > & put(int32 inIndex, value_type inValue)
Definition: NdArrayCore.hpp:3663
size_type size() const noexcept
Definition: NdArrayCore.hpp:4289
reverse_iterator rbegin() noexcept
Definition: NdArrayCore.hpp:1325
NdArray< dtype > & resizeSlow(uint32 inNumRows, uint32 inNumCols)
Definition: NdArrayCore.hpp:4188
NdArray< dtype > & put(const Slice &inRowSlice, const Slice &inColSlice, value_type inValue)
Definition: NdArrayCore.hpp:3786
NdArray< bool > issorted(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2859
const_iterator cbegin() const noexcept
Definition: NdArrayCore.hpp:1221
NdArray< dtype > operator[](const Indices &inIndices) const
Definition: NdArrayCore.hpp:761
const_reference at(int32 inIndex) const
Definition: NdArrayCore.hpp:1016
const_column_iterator ccolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1310
NdArrayConstColumnIterator< dtype, size_type, const_pointer, difference_type > const_column_iterator
Definition: NdArrayCore.hpp:97
NdArray< dtype > round(uint8 inNumDecimals=0) const
Definition: NdArrayCore.hpp:4242
NdArray< bool > any(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1843
const_pointer data() const noexcept
Definition: NdArrayCore.hpp:2526
NdArray< uint32 > toIndices(Slice inSlice, Axis inAxis=Axis::ROW) const
Definition: NdArrayCore.hpp:4532
NdArray< dtype > at(const Slice &inRowSlice, int32 inColIndex) const
Definition: NdArrayCore.hpp:1129
iterator end() noexcept
Definition: NdArrayCore.hpp:1479
NdArray< dtype > operator()(Slice inRowSlice, int32 inColIndex) const
Definition: NdArrayCore.hpp:815
NdArray< dtype > & put(const Slice &inRowSlice, const Slice &inColSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3864
NdArray(std::vector< dtype > &inVector, bool copy=true)
Definition: NdArrayCore.hpp:263
NdArray< dtype > prod(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3553
NdArray< dtype > copy() const
Definition: NdArrayCore.hpp:2382
NdArray< dtype > & resizeFast(const Shape &inShape)
Definition: NdArrayCore.hpp:4171
std::vector< dtype > toStlVector() const
Definition: NdArrayCore.hpp:4580
reference back(size_type row)
Definition: NdArrayCore.hpp:2227
iterator end(size_type inRow)
Definition: NdArrayCore.hpp:1491
NdArray< dtype > flatten() const
Definition: NdArrayCore.hpp:2751
NdArray(const std::initializer_list< std::initializer_list< dtype >> &inList)
Definition: NdArrayCore.hpp:170
void tofile(const std::string &inFilename, const char inSep) const
Definition: NdArrayCore.hpp:4495
const_column_iterator ccolbegin() const noexcept
Definition: NdArrayCore.hpp:1298
typename AllocTraits::pointer pointer
Definition: NdArrayCore.hpp:84
Slice cSlice(int32 inStartIdx=0, uint32 inStepSize=1) const noexcept
Definition: NdArrayCore.hpp:969
reverse_iterator rbegin(size_type inRow)
Definition: NdArrayCore.hpp:1337
Shape shape() const noexcept
Definition: NdArrayCore.hpp:4276
NdArray< dtype > & byteswap() noexcept
Definition: NdArrayCore.hpp:2240
const_reverse_column_iterator rcolend() const noexcept
Definition: NdArrayCore.hpp:1737
uint32 numRows() const noexcept
Definition: NdArrayCore.hpp:3428
const dtype & const_reference
Definition: NdArrayCore.hpp:87
NdArray< dtype > & put(const Slice &inRowSlice, int32 inColIndex, value_type inValue)
Definition: NdArrayCore.hpp:3816
NdArray< dtype > & partition(uint32 inKth, Axis inAxis=Axis::NONE)
Definition: NdArrayCore.hpp:3472
bool issquare() const noexcept
Definition: NdArrayCore.hpp:2908
NdArrayIterator< dtype, pointer, difference_type > iterator
Definition: NdArrayCore.hpp:91
bool isflat() const noexcept
Definition: NdArrayCore.hpp:2847
Endian endianess() const noexcept
Definition: NdArrayCore.hpp:2696
void tofile(const std::string &inFilename) const
Definition: NdArrayCore.hpp:4478
const_reverse_column_iterator crcolbegin() const noexcept
Definition: NdArrayCore.hpp:1452
const_reverse_column_iterator crcolend(size_type inCol) const
Definition: NdArrayCore.hpp:1772
column_iterator colbegin(size_type inCol)
Definition: NdArrayCore.hpp:1260
NdArrayColumnIterator< dtype, size_type, pointer, difference_type > column_iterator
Definition: NdArrayCore.hpp:96
NdArray< bool > none(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3354
NdArray< dtype > at(const Slice &inSlice) const
Definition: NdArrayCore.hpp:1099
reference at(int32 inIndex)
Definition: NdArrayCore.hpp:995
NdArray< dtype > & sort(Axis inAxis=Axis::NONE)
Definition: NdArrayCore.hpp:4303
pointer data() noexcept
Definition: NdArrayCore.hpp:2516
bool isempty() const noexcept
Definition: NdArrayCore.hpp:2835
column_iterator colbegin() noexcept
Definition: NdArrayCore.hpp:1248
const_reference front(size_type row) const
Definition: NdArrayCore.hpp:2786
reverse_column_iterator rcolend(size_type inCol)
Definition: NdArrayCore.hpp:1722
NdArray< dtype > sum(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:4382
NdArray(Iterator inFirst, Iterator inLast)
Definition: NdArrayCore.hpp:419
NdArray< dtype > operator[](const Slice &inSlice) const
Definition: NdArrayCore.hpp:713
reverse_column_iterator rcolbegin() noexcept
Definition: NdArrayCore.hpp:1402
NdArrayConstIterator< dtype, const_pointer, difference_type > const_iterator
Definition: NdArrayCore.hpp:92
const_iterator cbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1233
const_column_iterator ccolend(size_type inCol) const
Definition: NdArrayCore.hpp:1695
NdArray< dtype > cumsum(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2458
NdArray< dtype > median(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3048
NdArray< dtype > getByMask(const NdArray< bool > &inMask) const
Definition: NdArrayCore.hpp:2823
const_iterator cend(size_type inRow) const
Definition: NdArrayCore.hpp:1541
NdArray< dtype > column(uint32 inColumn)
Definition: NdArrayCore.hpp:2319
const_reverse_column_iterator rcolend(size_type inCol) const
Definition: NdArrayCore.hpp:1749
NdArray< dtype > & putMask(const NdArray< bool > &inMask, value_type inValue)
Definition: NdArrayCore.hpp:3942
const_iterator end(size_type inRow) const
Definition: NdArrayCore.hpp:1518
reference back() noexcept
Definition: NdArrayCore.hpp:2205
const_reverse_column_iterator crcolend() const noexcept
Definition: NdArrayCore.hpp:1760
const_reference back(size_type row) const
Definition: NdArrayCore.hpp:2216
reverse_column_iterator rcolbegin(size_type inCol)
Definition: NdArrayCore.hpp:1414
NdArray(const std::deque< std::deque< dtype >> &in2dDeque)
Definition: NdArrayCore.hpp:367
NdArray< dtype > & put(int32 inRow, int32 inCol, value_type inValue)
Definition: NdArrayCore.hpp:3680
iterator begin(size_type inRow)
Definition: NdArrayCore.hpp:1183
const_reverse_iterator rend() const noexcept
Definition: NdArrayCore.hpp:1583
NdArray< dtype > clip(value_type inMin, value_type inMax) const
Definition: NdArrayCore.hpp:2280
const_reverse_column_iterator rcolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1441
NdArray< dtype > & operator=(NdArray< dtype > &&rhs) noexcept
Definition: NdArrayCore.hpp:606
typename AllocTraits::difference_type difference_type
Definition: NdArrayCore.hpp:89
NdArray< uint32 > argmin(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1954
const_iterator end() const noexcept
Definition: NdArrayCore.hpp:1506
bool ownsInternalData() noexcept
Definition: NdArrayCore.hpp:3452
NdArray< dtype > & fill(value_type inFillValue) noexcept
Definition: NdArrayCore.hpp:2712
column_iterator colend() noexcept
Definition: NdArrayCore.hpp:1633
NdArray(std::initializer_list< dtype > inList)
Definition: NdArrayCore.hpp:153
NdArray< dtype > operator()(Slice inRowSlice, Slice inColSlice) const
Definition: NdArrayCore.hpp:787
NdArray< dtype > & put(const NdArray< uint32 > &inIndices, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3715
const_reference back() const noexcept
Definition: NdArrayCore.hpp:2194
NdArray< dtype > operator()(int32 inRowIndex, Slice inColSlice) const
Definition: NdArrayCore.hpp:837
std::pair< NdArray< uint32 >, NdArray< uint32 > > nonzero() const
Definition: NdArrayCore.hpp:4735
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: NdArrayCore.hpp:94
NdArray(const_pointer inPtr, UIntType1 numRows, UIntType2 numCols)
Definition: NdArrayCore.hpp:462
NdArray< dtype > cumprod(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2396
uint64 nbytes() const noexcept
Definition: NdArrayCore.hpp:3176
const_reference at(int32 inRowIndex, int32 inColIndex) const
Definition: NdArrayCore.hpp:1069
NdArray< dtype > transpose() const
Definition: NdArrayCore.hpp:4650
NdArray< dtype > swapaxes() const
Definition: NdArrayCore.hpp:4432
NdArray< dtype > & put(int32 inRowIndex, const Slice &inColSlice, value_type inValue)
Definition: NdArrayCore.hpp:3840
NdArray(const std::list< dtype > &inList)
Definition: NdArrayCore.hpp:399
NdArray()=default
NdArray< dtype > at(int32 inRowIndex, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:1144
const_reference front() const noexcept
Definition: NdArrayCore.hpp:2764
NdArray< dtype > repeat(const Shape &inRepeatShape) const
Definition: NdArrayCore.hpp:4034
~NdArray() noexcept
Definition: NdArrayCore.hpp:553
NdArray< dtype > min(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2993
NdArray< dtype > & reshape(const Shape &inShape)
Definition: NdArrayCore.hpp:4141
reference front() noexcept
Definition: NdArrayCore.hpp:2775
NdArray(size_type inNumRows, size_type inNumCols)
Definition: NdArrayCore.hpp:127
Allocator allocator_type
Definition: NdArrayCore.hpp:83
void print() const
Definition: NdArrayCore.hpp:3537
void swapCols(int32 colIdx1, int32 colIdx2) noexcept
Definition: NdArrayCore.hpp:4444
const_reverse_column_iterator crcolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1464
reverse_iterator rend(size_type inRow)
Definition: NdArrayCore.hpp:1568
NdArray< uint32 > flatnonzero() const
Definition: NdArrayCore.hpp:2725
NdArray(size_type inSquareSize)
Definition: NdArrayCore.hpp:113
NdArray< dtype > operator()(int32 rowIndex, const Indices &colIndices) const
Definition: NdArrayCore.hpp:894
reverse_iterator rend() noexcept
Definition: NdArrayCore.hpp:1556
const_reverse_iterator rend(size_type inRow) const
Definition: NdArrayCore.hpp:1595
NdArray< dtype > getByIndices(const NdArray< uint32 > &inIndices) const
Definition: NdArrayCore.hpp:2809
typename AllocTraits::const_pointer const_pointer
Definition: NdArrayCore.hpp:85
NdArray< dtype > & resizeSlow(const Shape &inShape)
Definition: NdArrayCore.hpp:4227
const_reverse_iterator crbegin() const noexcept
Definition: NdArrayCore.hpp:1375
const_column_iterator colend(size_type inCol) const
Definition: NdArrayCore.hpp:1672
std::reverse_iterator< iterator > reverse_iterator
Definition: NdArrayCore.hpp:93
NdArray< dtype > operator()(const Indices &rowIndices, Slice colSlice) const
Definition: NdArrayCore.hpp:878
NdArray(const std::vector< std::vector< dtype >> &in2dVector)
Definition: NdArrayCore.hpp:288
const_reverse_iterator rbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1364
const_iterator cend() const noexcept
Definition: NdArrayCore.hpp:1529
std::string str() const
Definition: NdArrayCore.hpp:4346
std::reverse_iterator< const_column_iterator > const_reverse_column_iterator
Definition: NdArrayCore.hpp:99
reference operator[](int32 inIndex) noexcept
Definition: NdArrayCore.hpp:632
NdArray< dtype > & reshape(int32 inNumRows, int32 inNumCols)
Definition: NdArrayCore.hpp:4091
NdArray(NdArray< dtype > &&inOtherArray) noexcept
Definition: NdArrayCore.hpp:536
NdArray< dtype > & nans() noexcept
Definition: NdArrayCore.hpp:3160
NdArray< dtype > & put(const NdArray< uint32 > &inIndices, value_type inValue)
Definition: NdArrayCore.hpp:3696
NdArray< dtype > ptp(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3607
const_reference operator()(int32 inRowIndex, int32 inColIndex) const noexcept
Definition: NdArrayCore.hpp:690
reference front(size_type row)
Definition: NdArrayCore.hpp:2797
NdArray< dtype > diagonal(int32 inOffset=0, Axis inAxis=Axis::ROW) const
Definition: NdArrayCore.hpp:2555
NdArray(pointer inPtr, uint32 numRows, uint32 numCols, BoolType takeOwnership) noexcept
Definition: NdArrayCore.hpp:504
NdArray< dtype > & putMask(const NdArray< bool > &inMask, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3959
NdArray< dtype > operator[](const NdArray< bool > &inMask) const
Definition: NdArrayCore.hpp:734
NdArray< dtype > row(uint32 inRow)
Definition: NdArrayCore.hpp:4263
NdArray< dtype > operator()(const Indices &rowIndices, int32 colIndex) const
Definition: NdArrayCore.hpp:861
const_iterator begin(size_type inRow) const
Definition: NdArrayCore.hpp:1210
iterator begin() noexcept
Definition: NdArrayCore.hpp:1171
NdArray< dtype > & put(const Slice &inSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3762
const_column_iterator colbegin() const noexcept
Definition: NdArrayCore.hpp:1275
NdArray< dtype > max(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2940
std::reverse_iterator< column_iterator > reverse_column_iterator
Definition: NdArrayCore.hpp:98
void swapRows(int32 rowIdx1, int32 rowIdx2) noexcept
Definition: NdArrayCore.hpp:4459
NdArray< dtype > & operator=(const NdArray< dtype > &rhs)
Definition: NdArrayCore.hpp:565
value_type item() const
Definition: NdArrayCore.hpp:2921
reference operator()(int32 inRowIndex, int32 inColIndex) noexcept
Definition: NdArrayCore.hpp:667
const_column_iterator colend() const noexcept
Definition: NdArrayCore.hpp:1660
NdArray< dtype > & resizeFast(uint32 inNumRows, uint32 inNumCols)
Definition: NdArrayCore.hpp:4156
const_reverse_iterator crend() const noexcept
Definition: NdArrayCore.hpp:1606
NdArray< dtype > & ones() noexcept
Definition: NdArrayCore.hpp:3438
NdArray< dtype > operator()(RowIndices rowIndices, ColIndices colIndices) const
Definition: NdArrayCore.hpp:929
NdArray< dtype > & zeros() noexcept
Definition: NdArrayCore.hpp:4668
const_column_iterator colbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1287
NdArray< dtype > dot(const NdArray< dtype > &inOtherArray) const
Definition: NdArrayCore.hpp:2623
NdArray< dtype > repeat(uint32 inNumRows, uint32 inNumCols) const
Definition: NdArrayCore.hpp:3993
NdArray< dtype > & reshape(size_type inSize)
Definition: NdArrayCore.hpp:4064
NdArray< bool > contains(value_type inValue, Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2332
const_column_iterator ccolend() const noexcept
Definition: NdArrayCore.hpp:1683
NdArray< uint32 > argmax(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1896
value_type trace(uint32 inOffset=0, Axis inAxis=Axis::ROW) const noexcept
Definition: NdArrayCore.hpp:4597
reverse_column_iterator rcolend() noexcept
Definition: NdArrayCore.hpp:1710
NdArray(std::array< dtype, ArraySize > &inArray, bool copy=true)
Definition: NdArrayCore.hpp:206
NdArray< dtype > & put(int32 inRowIndex, const Slice &inColSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3920
const_reverse_iterator rbegin() const noexcept
Definition: NdArrayCore.hpp:1352
NdArray(const_pointer inPtr, size_type size)
Definition: NdArrayCore.hpp:438
NdArray(const std::deque< dtype > &inDeque)
Definition: NdArrayCore.hpp:350
NdArray(std::array< std::array< dtype, Dim1Size >, Dim0Size > &in2dArray, bool copy=true)
Definition: NdArrayCore.hpp:234
void dump(const std::string &inFilename) const
Definition: NdArrayCore.hpp:2669
dtype & reference
Definition: NdArrayCore.hpp:86
pointer dataRelease() noexcept
Definition: NdArrayCore.hpp:2538
reference at(int32 inRowIndex, int32 inColIndex)
Definition: NdArrayCore.hpp:1038
NdArray< dtype > at(const Slice &inRowSlice, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:1114
NdArray< dtype > operator()(Slice rowSlice, const Indices &colIndices) const
Definition: NdArrayCore.hpp:911
NdArray(const NdArray< dtype > &inOtherArray)
Definition: NdArrayCore.hpp:518
NdArray< uint32 > argsort(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2011
uint32 size_type
Definition: NdArrayCore.hpp:88
const_iterator begin() const noexcept
Definition: NdArrayCore.hpp:1198
NdArray< dtype > & operator=(value_type inValue) noexcept
Definition: NdArrayCore.hpp:589
NdArray< dtype > newbyteorder(Endian inEndianess) const
Definition: NdArrayCore.hpp:3191
column_iterator colend(size_type inCol)
Definition: NdArrayCore.hpp:1645
NdArray< dtype > & put(const Slice &inSlice, value_type inValue)
Definition: NdArrayCore.hpp:3740
const_reference operator[](int32 inIndex) const noexcept
Definition: NdArrayCore.hpp:649
NdArray< dtype > & ravel() noexcept
Definition: NdArrayCore.hpp:3977
dtype value_type
Definition: NdArrayCore.hpp:82
void replace(value_type oldValue, value_type newValue)
Definition: NdArrayCore.hpp:4046
NdArray< dtype > & put(const Slice &inRowSlice, int32 inColIndex, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3895
Slice rSlice(int32 inStartIdx=0, uint32 inStepSize=1) const noexcept
Definition: NdArrayCore.hpp:983
const_reverse_iterator crend(size_type inRow) const
Definition: NdArrayCore.hpp:1618
const_reverse_iterator crbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1387
NdArray(pointer inPtr, size_type size, BoolType takeOwnership) noexcept
Definition: NdArrayCore.hpp:484
NdArray(const Shape &inShape)
Definition: NdArrayCore.hpp:140
NdArray< bool > all(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1791
Custom iterator for NdArray.
Definition: NdArrayIterators.hpp:318
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:104
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:141
uint32 numElements(uint32 inArraySize)
Definition: Slice.hpp:194
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(GeneratorType &generator, dtype inDofN, dtype inDofD)
Definition: f.hpp:58
bool any_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:78
void sort(RandomIt first, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:705
bool none_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:408
ForwardIt max_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:287
void stable_sort(RandomIt first, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:743
OutputIt transform(InputIt first, InputIt last, OutputIt destination, UnaryOperation unaryFunction)
Definition: StlAlgorithms.hpp:784
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:227
InputIt find(InputIt first, InputIt last, const T &value) noexcept
Definition: StlAlgorithms.hpp:207
constexpr OutputIt unique_copy(InputIt first, InputIt last, OutputIt destination) noexcept
Definition: StlAlgorithms.hpp:835
std::pair< ForwardIt, ForwardIt > minmax_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:366
void replace(ForwardIt first, ForwardIt last, const T &oldValue, const T &newValue) noexcept
Definition: StlAlgorithms.hpp:471
bool is_sorted(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:247
OutputIt copy(InputIt first, InputIt last, OutputIt destination) noexcept
Definition: StlAlgorithms.hpp:99
void nth_element(RandomIt first, RandomIt nth, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:428
ForwardIt min_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:326
void fill(ForwardIt first, ForwardIt last, const T &value) noexcept
Definition: StlAlgorithms.hpp:185
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
void swap(NdArray< dtype > &inArray1, NdArray< dtype > &inArray2) noexcept
Definition: swap.hpp:42
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:47
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:56
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