NumCpp  2.4.2
A Templatized Header Only C++ Implementation of the Python NumPy Library
NdArrayCore.hpp
Go to the documentation of this file.
1 #pragma once
29 
39 #include "NumCpp/Core/Shape.hpp"
40 #include "NumCpp/Core/Slice.hpp"
41 #include "NumCpp/Core/Types.hpp"
43 #include "NumCpp/Utils/num2str.hpp"
44 #include "NumCpp/Utils/power.hpp"
45 #include "NumCpp/Utils/sqr.hpp"
47 
48 #include <array>
49 #include <cmath>
50 #include <deque>
51 #include <forward_list>
52 #include <fstream>
53 #include <initializer_list>
54 #include <iostream>
55 #include <iterator>
56 #include <list>
57 #include <memory>
58 #include <numeric>
59 #include <set>
60 #include <string>
61 #include <type_traits>
62 #include <utility>
63 #include <vector>
64 
65 namespace nc
66 {
67  //================================================================================
68  // Class Description:
70  template<typename dtype, class Allocator = std::allocator<dtype>>
71  class NdArray
72  {
73  private:
74  STATIC_ASSERT_VALID_DTYPE(dtype);
75  static_assert(is_same_v<dtype, typename Allocator::value_type>, "value_type and Allocator::value_type must match");
76 
77  using AllocType = typename std::allocator_traits<Allocator>::template rebind_alloc<dtype>;
78  using AllocTraits = std::allocator_traits<AllocType>;
79 
80  public:
81  using value_type = dtype;
82  using allocator_type = Allocator;
83  using pointer = typename AllocTraits::pointer;
84  using const_pointer = typename AllocTraits::const_pointer;
85  using reference = dtype&;
86  using const_reference = const dtype&;
87  using size_type = uint32;
88  using difference_type = typename AllocTraits::difference_type;
89 
92  using reverse_iterator = std::reverse_iterator<iterator>;
93  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
94 
97  using reverse_column_iterator = std::reverse_iterator<column_iterator>;
98  using const_reverse_column_iterator = std::reverse_iterator<const_column_iterator>;
99 
100  //============================================================================
101  // Method Description:
104  NdArray() = default;
105 
106  //============================================================================
107  // Method Description:
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:
141  explicit NdArray(const Shape& inShape) :
142  shape_(inShape),
143  size_(shape_.size())
144  {
145  newArray();
146  }
147 
148  //============================================================================
149  // Method Description:
155  NdArray(const std::initializer_list<dtype>& inList) :
156  shape_(1, static_cast<uint32>(inList.size())),
157  size_(shape_.size())
158  {
159  newArray();
160  if (size_ > 0)
161  {
162  stl_algorithms::copy(inList.begin(), inList.end(), begin());
163  }
164  }
165 
166  //============================================================================
167  // Method Description:
173  NdArray(const std::initializer_list<std::initializer_list<dtype> >& inList) :
174  shape_(static_cast<uint32>(inList.size()), 0)
175  {
176  for (const auto& list : inList)
177  {
178  if (shape_.cols == 0)
179  {
180  shape_.cols = static_cast<uint32>(list.size());
181  }
182  else if (list.size() != shape_.cols)
183  {
184  THROW_INVALID_ARGUMENT_ERROR("All rows of the initializer list needs to have the same number of elements");
185  }
186  }
187 
188  size_ = shape_.size();
189  newArray();
190  uint32 row = 0;
191  for (const auto& list : inList)
192  {
193  const auto ptr = begin() += row * shape_.cols;
194  stl_algorithms::copy(list.begin(), list.end(), ptr);
195  ++row;
196  }
197  }
198 
199  //============================================================================
200  // Method Description:
207  template<size_t ArraySize,
208  std::enable_if_t<is_valid_dtype_v<dtype>, int> = 0>
209  NdArray(std::array<dtype, ArraySize>& inArray, bool copy = true) :
210  shape_(1, static_cast<uint32>(ArraySize)),
211  size_(shape_.size())
212  {
213  if (copy)
214  {
215  newArray();
216  if (size_ > 0)
217  {
218  stl_algorithms::copy(inArray.begin(), inArray.end(), begin());
219  }
220  }
221  else
222  {
223  array_ = inArray.data();
224  ownsPtr_ = false;
225  }
226  }
227 
228  //============================================================================
229  // Method Description:
236  template<size_t Dim0Size, size_t Dim1Size>
237  NdArray(std::array<std::array<dtype, Dim1Size>, Dim0Size>& in2dArray, bool copy = true) :
238  shape_(static_cast<uint32>(Dim0Size), static_cast<uint32>(Dim1Size)),
239  size_(shape_.size())
240  {
241  if (copy)
242  {
243  newArray();
244  if (size_ > 0)
245  {
246  const auto start = in2dArray.front().begin();
247  stl_algorithms::copy(start, start + size_, begin());
248  }
249  }
250  else
251  {
252  array_ = in2dArray.front().data();
253  ownsPtr_ = false;
254  }
255  }
256 
257  //============================================================================
258  // Method Description:
265  template<std::enable_if_t<is_valid_dtype_v<dtype>, int> = 0>
266  NdArray(std::vector<dtype>& inVector, bool copy = true) :
267  shape_(1, static_cast<uint32>(inVector.size())),
268  size_(shape_.size())
269  {
270  if (copy)
271  {
272  newArray();
273  if (size_ > 0)
274  {
275  stl_algorithms::copy(inVector.begin(), inVector.end(), begin());
276  }
277  }
278  else
279  {
280  array_ = inVector.data();
281  ownsPtr_ = false;
282  }
283  }
284 
285  //============================================================================
286  // Method Description:
291  explicit NdArray(const std::vector<std::vector<dtype>>& in2dVector) :
292  shape_(static_cast<uint32>(in2dVector.size()), 0)
293  {
294  for (const auto& row : in2dVector)
295  {
296  if (shape_.cols == 0)
297  {
298  shape_.cols = static_cast<uint32>(row.size());
299  }
300  else if (row.size() != shape_.cols)
301  {
302  THROW_INVALID_ARGUMENT_ERROR("All rows of the 2d vector need to have the same number of elements");
303  }
304  }
305 
306  size_ = shape_.size();
307 
308  newArray();
309  auto currentPosition = begin();
310  for (const auto& row : in2dVector)
311  {
312  stl_algorithms::copy(row.begin(), row.end(), currentPosition);
313  currentPosition += shape_.cols;
314  }
315  }
316 
317  //============================================================================
318  // Method Description:
325  template<size_t Dim1Size>
326  NdArray(std::vector<std::array<dtype, Dim1Size>>& in2dArray, bool copy = true) :
327  shape_(static_cast<uint32>(in2dArray.size()), static_cast<uint32>(Dim1Size)),
328  size_(shape_.size())
329  {
330  if (copy)
331  {
332  newArray();
333  if (size_ > 0)
334  {
335  const auto start = in2dArray.front().begin();
336  stl_algorithms::copy(start, start + size_, begin());
337  }
338  }
339  else
340  {
341  array_ = in2dArray.front().data();
342  ownsPtr_ = false;
343  }
344  }
345 
346  //============================================================================
347  // Method Description:
352  template<std::enable_if_t<is_valid_dtype_v<dtype>, int> = 0>
353  explicit NdArray(const std::deque<dtype>& inDeque) :
354  shape_(1, static_cast<uint32>(inDeque.size())),
355  size_(shape_.size())
356  {
357  newArray();
358  if (size_ > 0)
359  {
360  stl_algorithms::copy(inDeque.begin(), inDeque.end(), begin());
361  }
362  }
363 
364  //============================================================================
365  // Method Description:
370  explicit NdArray(const std::deque<std::deque<dtype>>& in2dDeque) :
371  shape_(static_cast<uint32>(in2dDeque.size()), 0)
372  {
373  for (const auto& row : in2dDeque)
374  {
375  if (shape_.cols == 0)
376  {
377  shape_.cols = static_cast<uint32>(row.size());
378  }
379  else if (row.size() != shape_.cols)
380  {
381  THROW_INVALID_ARGUMENT_ERROR("All rows of the 2d vector need to have the same number of elements");
382  }
383  }
384 
385  size_ = shape_.size();
386 
387  newArray();
388  auto currentPosition = begin();
389  for (const auto& row : in2dDeque)
390  {
391  stl_algorithms::copy(row.begin(), row.end(), currentPosition);
392  currentPosition += shape_.cols;
393  }
394  }
395 
396  //============================================================================
397  // Method Description:
403  explicit NdArray(const std::list<dtype>& inList) :
404  shape_(1, static_cast<uint32>(inList.size())),
405  size_(shape_.size())
406  {
407  newArray();
408  if (size_ > 0)
409  {
410  stl_algorithms::copy(inList.begin(), inList.end(), begin());
411  }
412  }
413 
414  //============================================================================
415  // Method Description:
421  template<typename Iterator,
422  std::enable_if_t<std::is_same<typename std::iterator_traits<Iterator>::value_type, dtype>::value, int> = 0>
423  NdArray(Iterator inFirst, Iterator inLast) :
424  shape_(1, static_cast<uint32>(std::distance(inFirst, inLast))),
425  size_(shape_.size())
426  {
427  newArray();
428  if (size_ > 0)
429  {
430  stl_algorithms::copy(inFirst, inLast, begin());
431  }
432  }
433 
434  //============================================================================
435  // Method Description:
443  shape_(1, size),
444  size_(size)
445  {
446  newArray();
447  if (inPtr != nullptr && size_ > 0)
448  {
449  stl_algorithms::copy(inPtr, inPtr + size_, begin());
450  }
451  }
452 
453  //============================================================================
454  // Method Description:
462  template<typename UIntType1, typename UIntType2,
463  std::enable_if_t<!std::is_same<UIntType1, bool>::value, int> = 0,
464  std::enable_if_t<!std::is_same<UIntType2, bool>::value, int> = 0>
465  NdArray(const_pointer inPtr, UIntType1 numRows, UIntType2 numCols) :
466  shape_(numRows, numCols),
467  size_(shape_.size())
468  {
469  newArray();
470  if (inPtr != nullptr && size_ > 0)
471  {
472  stl_algorithms::copy(inPtr, inPtr + size_, begin());
473  }
474  }
475 
476  //============================================================================
477  // Method Description:
486  template<typename Bool,
487  std::enable_if_t<std::is_same<Bool, bool>::value, int> = 0>
488  NdArray(pointer inPtr, size_type size, Bool takeOwnership) noexcept :
489  shape_(1, size),
490  size_(size),
491  array_(inPtr),
492  ownsPtr_(takeOwnership)
493  {}
494 
495  //============================================================================
496  // Method Description:
506  template<typename Bool,
507  std::enable_if_t<std::is_same<Bool, bool>::value, int> = 0>
508  NdArray(pointer inPtr, uint32 numRows, uint32 numCols, Bool takeOwnership) noexcept :
509  shape_(numRows, numCols),
510  size_(numRows * numCols),
511  array_(inPtr),
512  ownsPtr_(takeOwnership)
513  {}
514 
515  //============================================================================
516  // Method Description:
522  NdArray(const NdArray<dtype>& inOtherArray) :
523  shape_(inOtherArray.shape_),
524  size_(inOtherArray.size_),
525  endianess_(inOtherArray.endianess_)
526  {
527  newArray();
528  if (size_ > 0)
529  {
530  stl_algorithms::copy(inOtherArray.cbegin(), inOtherArray.cend(), begin());
531  }
532  }
533 
534  //============================================================================
535  // Method Description:
541  NdArray(NdArray<dtype>&& inOtherArray) noexcept :
542  shape_(inOtherArray.shape_),
543  size_(inOtherArray.size_),
544  endianess_(inOtherArray.endianess_),
545  array_(inOtherArray.array_),
546  ownsPtr_(inOtherArray.ownsPtr_)
547  {
548  inOtherArray.shape_.rows = inOtherArray.shape_.cols = 0;
549  inOtherArray.size_ = 0;
550  inOtherArray.ownsPtr_ = false;
551  inOtherArray.array_ = nullptr;
552  }
553 
554  //============================================================================
555  // Method Description:
558  ~NdArray() noexcept
559  {
560  deleteArray();
561  }
562 
563  //============================================================================
564  // Method Description:
573  {
574  if (&rhs != this)
575  {
576  if (rhs.size_ > 0)
577  {
578  newArray(rhs.shape_);
579  endianess_ = rhs.endianess_;
580 
581  stl_algorithms::copy(rhs.cbegin(), rhs.cend(), begin());
582  }
583  }
584 
585  return *this;
586  }
587 
588  //============================================================================
589  // Method Description:
599  {
600  if (array_ != nullptr)
601  {
602  stl_algorithms::fill(begin(), end(), inValue);
603  }
604 
605  return *this;
606  }
607 
608  //============================================================================
609  // Method Description:
618  {
619  if (&rhs != this)
620  {
621  deleteArray();
622  shape_ = rhs.shape_;
623  size_ = rhs.size_;
624  endianess_ = rhs.endianess_;
625  array_ = rhs.array_;
626  ownsPtr_ = rhs.ownsPtr_;
627 
628  rhs.shape_.rows = rhs.shape_.cols = rhs.size_ = 0;
629  rhs.array_ = nullptr;
630  rhs.ownsPtr_ = false;
631  }
632 
633  return *this;
634  }
635 
636  //============================================================================
637  // Method Description:
645  reference operator[](int32 inIndex) noexcept
646  {
647  if (inIndex < 0)
648  {
649  inIndex += size_;
650  }
651 
652  return array_[inIndex];
653  }
654 
655  //============================================================================
656  // Method Description:
664  const_reference operator[](int32 inIndex) const noexcept
665  {
666  if (inIndex < 0)
667  {
668  inIndex += size_;
669  }
670 
671  return array_[inIndex];
672  }
673 
674  //============================================================================
675  // Method Description:
683  reference operator()(int32 inRowIndex, int32 inColIndex) noexcept
684  {
685  if (inRowIndex < 0)
686  {
687  inRowIndex += shape_.rows;
688  }
689 
690  if (inColIndex < 0)
691  {
692  inColIndex += shape_.cols;
693  }
694 
695  return array_[inRowIndex * shape_.cols + inColIndex];
696  }
697 
698  //============================================================================
699  // Method Description:
707  const_reference operator()(int32 inRowIndex, int32 inColIndex) const noexcept
708  {
709  if (inRowIndex < 0)
710  {
711  inRowIndex += shape_.rows;
712  }
713 
714  if (inColIndex < 0)
715  {
716  inColIndex += shape_.cols;
717  }
718 
719  return array_[inRowIndex * shape_.cols + inColIndex];
720  }
721 
722  //============================================================================
723  // Method Description:
732  NdArray<dtype> operator[](const Slice& inSlice) const
733  {
734  Slice inSliceCopy(inSlice);
735 
736  uint32 counter = 0;
737  NdArray<dtype> returnArray(1, inSliceCopy.numElements(size_));
738  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
739  {
740  returnArray[counter++] = at(i);
741  }
742 
743  return returnArray;
744  }
745 
746  //============================================================================
747  // Method Description:
756  {
757  if (inMask.shape() != shape_)
758  {
759  THROW_INVALID_ARGUMENT_ERROR("input inMask must have the same shape as the NdArray it will be masking.");
760  }
761 
762  auto indices = inMask.flatnonzero();
763  auto outArray = NdArray<dtype>(1, indices.size());
764  for (size_type i = 0; i < indices.size(); ++i)
765  {
766  outArray[i] = operator[](indices[i]);
767  }
768 
769  return outArray;
770  }
771 
772  //============================================================================
773  // Method Description:
782  {
783  if (inIndices.max().item() > size_ - 1)
784  {
785  THROW_INVALID_ARGUMENT_ERROR("input indices must be less than the array size.");
786  }
787 
788  auto outArray = NdArray<dtype>(1, static_cast<size_type>(inIndices.size()));
789  size_type i = 0;
790  for (auto& index : inIndices)
791  {
792  outArray[i++] = operator[](index);
793  }
794 
795  return outArray;
796  }
797 
798  //============================================================================
799  // Method Description:
808  NdArray<dtype> operator()(const Slice& inRowSlice, const Slice& inColSlice) const
809  {
810  Slice inRowSliceCopy(inRowSlice);
811  Slice inColSliceCopy(inColSlice);
812 
813  NdArray<dtype> returnArray(inRowSliceCopy.numElements(shape_.rows), inColSliceCopy.numElements(shape_.cols));
814 
815  uint32 rowCounter = 0;
816  uint32 colCounter = 0;
817  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
818  {
819  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
820  {
821  returnArray(rowCounter, colCounter++) = at(row, col);
822  }
823  colCounter = 0;
824  ++rowCounter;
825  }
826 
827  return returnArray;
828  }
829 
830  //============================================================================
831  // Method Description:
840  NdArray<dtype> operator()(const Slice& inRowSlice, int32 inColIndex) const
841  {
842  Slice inRowSliceCopy(inRowSlice);
843 
844  NdArray<dtype> returnArray(inRowSliceCopy.numElements(shape_.rows), 1);
845 
846  uint32 rowCounter = 0;
847  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
848  {
849  returnArray(rowCounter++, 0) = at(row, inColIndex);
850  }
851 
852  return returnArray;
853  }
854 
855  //============================================================================
856  // Method Description:
865  NdArray<dtype> operator()(int32 inRowIndex, const Slice& inColSlice) const
866  {
867  Slice inColSliceCopy(inColSlice);
868 
869  NdArray<dtype> returnArray(1, inColSliceCopy.numElements(shape_.cols));
870 
871  uint32 colCounter = 0;
872  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
873  {
874  returnArray(0, colCounter++) = at(inRowIndex, col);
875  }
876 
877  return returnArray;
878  }
879 
880  //============================================================================
881  // Method Description:
890  Slice cSlice(int32 inStartIdx = 0, uint32 inStepSize = 1) const noexcept
891  {
892  return Slice(inStartIdx, shape_.cols, inStepSize);
893  }
894 
895  //============================================================================
896  // Method Description:
905  Slice rSlice(int32 inStartIdx = 0, uint32 inStepSize = 1) const noexcept
906  {
907  return Slice(inStartIdx, shape_.rows, inStepSize);
908  }
909 
910  //============================================================================
911  // Method Description:
919  reference at(int32 inIndex)
920  {
921  // this doesn't allow for calling the first element as -size_...
922  // but why would you really want to do that anyway?
923  if (std::abs(inIndex) > static_cast<int64>(size_ - 1))
924  {
925  std::string errStr = "Input index " + utils::num2str(inIndex);
926  errStr += " is out of bounds for array of size " + utils::num2str(size_) + ".";
928  }
929 
930  return operator[](inIndex);
931  }
932 
933  //============================================================================
934  // Method Description:
942  const_reference at(int32 inIndex) const
943  {
944  // this doesn't allow for calling the first element as -size_...
945  // but why would you really want to do that anyway?
946  if (std::abs(inIndex) > static_cast<int64>(size_ - 1))
947  {
948  std::string errStr = "Input index " + utils::num2str(inIndex);
949  errStr += " is out of bounds for array of size " + utils::num2str(size_) + ".";
951  }
952 
953  return operator[](inIndex);
954  }
955 
956  //============================================================================
957  // Method Description:
965  reference at(int32 inRowIndex, int32 inColIndex)
966  {
967  // this doesn't allow for calling the first element as -size_...
968  // but why would you really want to do that anyway?
969  if (std::abs(inRowIndex) > static_cast<int32>(shape_.rows - 1))
970  {
971  std::string errStr = "Row index " + utils::num2str(inRowIndex);
972  errStr += " is out of bounds for array of size " + utils::num2str(shape_.rows) + ".";
974  }
975 
976  // this doesn't allow for calling the first element as -size_...
977  // but why would you really want to that anyway?
978  if (std::abs(inColIndex) > static_cast<int32>(shape_.cols - 1))
979  {
980  std::string errStr = "Column index " + utils::num2str(inColIndex);
981  errStr += " is out of bounds for array of size " + utils::num2str(shape_.cols) + ".";
983  }
984 
985  return operator()(inRowIndex, inColIndex);
986  }
987 
988  //============================================================================
989  // Method Description:
997  const_reference at(int32 inRowIndex, int32 inColIndex) const
998  {
999  // this doesn't allow for calling the first element as -size_...
1000  // but why would you really want to do that anyway?
1001  if (std::abs(inRowIndex) > static_cast<int32>(shape_.rows - 1))
1002  {
1003  std::string errStr = "Row index " + utils::num2str(inRowIndex);
1004  errStr += " is out of bounds for array of size " + utils::num2str(shape_.rows) + ".";
1006  }
1007 
1008  // this doesn't allow for calling the first element as -size_...
1009  // but why would you really want to do that anyway?
1010  if (std::abs(inColIndex) > static_cast<int32>(shape_.cols - 1))
1011  {
1012  std::string errStr = "Column index " + utils::num2str(inColIndex);
1013  errStr += " is out of bounds for array of size " + utils::num2str(shape_.cols) + ".";
1015  }
1016 
1017  return operator()(inRowIndex, inColIndex);
1018  }
1019 
1020  //============================================================================
1021  // Method Description:
1029  NdArray<dtype> at(const Slice& inSlice) const
1030  {
1031  // the slice operator already provides bounds checking. just including
1032  // the at method for completeness
1033  return operator[](inSlice);
1034  }
1035 
1036  //============================================================================
1037  // Method Description:
1045  NdArray<dtype> at(const Slice& inRowSlice, const Slice& inColSlice) const
1046  {
1047  // the slice operator already provides bounds checking. just including
1048  // the at method for completeness
1049  return operator()(inRowSlice, inColSlice);
1050  }
1051 
1052  //============================================================================
1053  // Method Description:
1061  NdArray<dtype> at(const Slice& inRowSlice, int32 inColIndex) const
1062  {
1063  // the slice operator already provides bounds checking. just including
1064  // the at method for completeness
1065  return operator()(inRowSlice, inColIndex);
1066  }
1067 
1068  //============================================================================
1069  // Method Description:
1077  NdArray<dtype> at(int32 inRowIndex, const Slice& inColSlice) const
1078  {
1079  // the slice operator already provides bounds checking. just including
1080  // the at method for completeness
1081  return operator()(inRowIndex, inColSlice);
1082  }
1083 
1084  //============================================================================
1085  // Method Description:
1090  iterator begin() noexcept
1091  {
1092  return iterator(array_);
1093  }
1094 
1095  //============================================================================
1096  // Method Description:
1105  {
1106  if (inRow >= shape_.rows)
1107  {
1108  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1109  }
1110 
1111  return begin() += (inRow * shape_.cols);
1112  }
1113 
1114  //============================================================================
1115  // Method Description:
1120  const_iterator begin() const noexcept
1121  {
1122  return cbegin();
1123  }
1124 
1125  //============================================================================
1126  // Method Description:
1135  {
1136  return cbegin(inRow);
1137  }
1138 
1139  //============================================================================
1140  // Method Description:
1146  const_iterator cbegin() const noexcept
1147  {
1148  return const_iterator(array_);
1149  }
1150 
1151  //============================================================================
1152  // Method Description:
1161  {
1162  if (inRow >= shape_.rows)
1163  {
1164  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1165  }
1166 
1167  return cbegin() += (inRow * shape_.cols);
1168  }
1169 
1170  //============================================================================
1171  // Method Description:
1177  {
1178  return column_iterator(array_, shape_.rows, shape_.cols);
1179  }
1180 
1181  //============================================================================
1182  // Method Description:
1191  {
1192  if (inCol >= shape_.cols)
1193  {
1194  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1195  }
1196 
1197  return colbegin() += (inCol * shape_.rows);
1198  }
1199 
1200  //============================================================================
1201  // Method Description:
1207  {
1208  return ccolbegin();
1209  }
1210 
1211  //============================================================================
1212  // Method Description:
1221  {
1222  return ccolbegin(inCol);
1223  }
1224 
1225  //============================================================================
1226  // Method Description:
1233  {
1234  return const_column_iterator(array_, shape_.rows, shape_.cols);
1235  }
1236 
1237  //============================================================================
1238  // Method Description:
1247  {
1248  if (inCol >= shape_.cols)
1249  {
1250  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1251  }
1252 
1253  return ccolbegin() += (inCol * shape_.rows);
1254  }
1255 
1256  //============================================================================
1257  // Method Description:
1263  {
1264  return reverse_iterator(end());
1265  }
1266 
1267  //============================================================================
1268  // Method Description:
1277  {
1278  if (inRow >= shape_.rows)
1279  {
1280  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1281  }
1282 
1283  return rbegin() += (shape_.rows - inRow - 1) * shape_.cols;
1284  }
1285 
1286  //============================================================================
1287  // Method Description:
1293  {
1294  return crbegin();
1295  }
1296 
1297  //============================================================================
1298  // Method Description:
1307  {
1308  return crbegin(inRow);
1309  }
1310 
1311  //============================================================================
1312  // Method Description:
1319  {
1320  return const_reverse_iterator(cend());
1321  }
1322 
1323  //============================================================================
1324  // Method Description:
1333  {
1334  if (inRow >= shape_.rows)
1335  {
1336  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1337  }
1338 
1339  return crbegin() += (shape_.rows - inRow - 1) * shape_.cols;
1340  }
1341 
1342  //============================================================================
1343  // Method Description:
1349  {
1350  return reverse_column_iterator(colend());
1351  }
1352 
1353  //============================================================================
1354  // Method Description:
1363  {
1364  if (inCol >= shape_.cols)
1365  {
1366  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1367  }
1368 
1369  return rcolbegin() += (shape_.cols - inCol - 1) * shape_.rows;
1370  }
1371 
1372  //============================================================================
1373  // Method Description:
1379  {
1380  return crcolbegin();
1381  }
1382 
1383  //============================================================================
1384  // Method Description:
1393  {
1394  return crcolbegin(inCol);
1395  }
1396 
1397  //============================================================================
1398  // Method Description:
1405  {
1407  }
1408 
1409  //============================================================================
1410  // Method Description:
1419  {
1420  if (inCol >= shape_.cols)
1421  {
1422  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1423  }
1424 
1425  return crcolbegin() += (shape_.cols - inCol - 1) * shape_.rows;
1426  }
1427 
1428  //============================================================================
1429  // Method Description:
1434  iterator end() noexcept
1435  {
1436  return begin() += size_;
1437  }
1438 
1439  //============================================================================
1440  // Method Description:
1449  {
1450  if (inRow >= shape_.rows)
1451  {
1452  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1453  }
1454 
1455  return begin(inRow) += shape_.cols;
1456  }
1457 
1458  //============================================================================
1459  // Method Description:
1464  const_iterator end() const noexcept
1465  {
1466  return cend();
1467  }
1468 
1469  //============================================================================
1470  // Method Description:
1479  {
1480  return cend(inRow);
1481  }
1482 
1483  //============================================================================
1484  // Method Description:
1490  const_iterator cend() const noexcept
1491  {
1492  return cbegin() += size_;
1493  }
1494 
1495  //============================================================================
1496  // Method Description:
1505  {
1506  if (inRow >= shape_.rows)
1507  {
1508  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1509  }
1510 
1511  return cbegin(inRow) += shape_.cols;
1512  }
1513 
1514  //============================================================================
1515  // Method Description:
1521  {
1522  return rbegin() += size_;
1523  }
1524 
1525  //============================================================================
1526  // Method Description:
1535  {
1536  if (inRow >= shape_.rows)
1537  {
1538  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1539  }
1540 
1541  return rbegin(inRow) += shape_.cols;
1542  }
1543 
1544  //============================================================================
1545  // Method Description:
1550  const_reverse_iterator rend() const noexcept
1551  {
1552  return crend();
1553  }
1554 
1555  //============================================================================
1556  // Method Description:
1565  {
1566  return crend(inRow);
1567  }
1568 
1569  //============================================================================
1570  // Method Description:
1577  {
1578  return crbegin() += size_;
1579  }
1580 
1581  //============================================================================
1582  // Method Description:
1591  {
1592  if (inRow >= shape_.rows)
1593  {
1594  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1595  }
1596 
1597  return crbegin(inRow) += shape_.cols;
1598  }
1599 
1600  //============================================================================
1601  // Method Description:
1607  {
1608  return colbegin() += size_;
1609  }
1610 
1611  //============================================================================
1612  // Method Description:
1621  {
1622  if (inCol >= shape_.cols)
1623  {
1624  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1625  }
1626 
1627  return colbegin(inCol) += shape_.rows;
1628  }
1629 
1630  //============================================================================
1631  // Method Description:
1636  const_column_iterator colend() const noexcept
1637  {
1638  return ccolend();
1639  }
1640 
1641  //============================================================================
1642  // Method Description:
1651  {
1652  return ccolend(inCol);
1653  }
1654 
1655  //============================================================================
1656  // Method Description:
1662  const_column_iterator ccolend() const noexcept
1663  {
1664  return ccolbegin() += size_;
1665  }
1666 
1667  //============================================================================
1668  // Method Description:
1677  {
1678  if (inCol >= shape_.cols)
1679  {
1680  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1681  }
1682 
1683  return ccolbegin(inCol) += shape_.rows;
1684  }
1685 
1686  //============================================================================
1687  // Method Description:
1693  {
1694  return rcolbegin() += size_;
1695  }
1696 
1697  //============================================================================
1698  // Method Description:
1707  {
1708  if (inCol >= shape_.cols)
1709  {
1710  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1711  }
1712 
1713  return rcolbegin(inCol) += shape_.rows;
1714  }
1715 
1716  //============================================================================
1717  // Method Description:
1723  {
1724  return crcolend();
1725  }
1726 
1727  //============================================================================
1728  // Method Description:
1737  {
1738  return crcolend(inCol);
1739  }
1740 
1741  //============================================================================
1742  // Method Description:
1749  {
1750  return crcolbegin() += size_;
1751  }
1752 
1753  //============================================================================
1754  // Method Description:
1763  {
1764  if (inCol >= shape_.cols)
1765  {
1766  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1767  }
1768 
1769  return crcolbegin(inCol) += shape_.rows;
1770  }
1771 
1772  //============================================================================
1773  // Method Description:
1784  {
1786 
1787  const auto function = [](dtype i) -> bool
1788  {
1789  return i != dtype{ 0 };
1790  };
1791 
1792  switch (inAxis)
1793  {
1794  case Axis::NONE:
1795  {
1796  NdArray<bool> returnArray = { stl_algorithms::all_of(cbegin(), cend(), function) };
1797  return returnArray;
1798  }
1799  case Axis::COL:
1800  {
1801  NdArray<bool> returnArray(1, shape_.rows);
1802  for (uint32 row = 0; row < shape_.rows; ++row)
1803  {
1804  returnArray(0, row) = stl_algorithms::all_of(cbegin(row), cend(row), function);
1805  }
1806 
1807  return returnArray;
1808  }
1809  case Axis::ROW:
1810  {
1811  NdArray<dtype> arrayTransposed = transpose();
1812  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
1813  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1814  {
1815  returnArray(0, row) = stl_algorithms::all_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
1816  }
1817 
1818  return returnArray;
1819  }
1820  default:
1821  {
1822  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1823  return {}; // get rid of compiler warning
1824  }
1825  }
1826  }
1827 
1828  //============================================================================
1829  // Method Description:
1840  {
1842 
1843  const auto function = [](dtype i) -> bool
1844  {
1845  return i != dtype{ 0 };
1846  };
1847 
1848  switch (inAxis)
1849  {
1850  case Axis::NONE:
1851  {
1852  NdArray<bool> returnArray = { stl_algorithms::any_of(cbegin(), cend(), function) };
1853  return returnArray;
1854  }
1855  case Axis::COL:
1856  {
1857  NdArray<bool> returnArray(1, shape_.rows);
1858  for (uint32 row = 0; row < shape_.rows; ++row)
1859  {
1860  returnArray(0, row) = stl_algorithms::any_of(cbegin(row), cend(row), function);
1861  }
1862 
1863  return returnArray;
1864  }
1865  case Axis::ROW:
1866  {
1867  NdArray<dtype> arrayTransposed = transpose();
1868  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
1869  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1870  {
1871  returnArray(0, row) = stl_algorithms::any_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
1872  }
1873 
1874  return returnArray;
1875  }
1876  default:
1877  {
1878  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1879  return {}; // get rid of compiler warning
1880  }
1881  }
1882  }
1883 
1884  //============================================================================
1885  // Method Description:
1897  {
1899 
1900  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
1901  {
1902  return lhs < rhs;
1903  };
1904 
1905  switch (inAxis)
1906  {
1907  case Axis::NONE:
1908  {
1909  NdArray<uint32> returnArray = { static_cast<uint32>(stl_algorithms::max_element(cbegin(),
1910  cend(), comparitor) - cbegin()) };
1911  return returnArray;
1912  }
1913  case Axis::COL:
1914  {
1915  NdArray<uint32> returnArray(1, shape_.rows);
1916  for (uint32 row = 0; row < shape_.rows; ++row)
1917  {
1918  returnArray(0, row) = static_cast<uint32>(stl_algorithms::max_element(cbegin(row),
1919  cend(row), comparitor) - cbegin(row));
1920  }
1921 
1922  return returnArray;
1923  }
1924  case Axis::ROW:
1925  {
1926  NdArray<dtype> arrayTransposed = transpose();
1927  NdArray<uint32> returnArray(1, arrayTransposed.shape_.rows);
1928  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1929  {
1930  returnArray(0, row) = static_cast<uint32>(stl_algorithms::max_element(arrayTransposed.cbegin(row),
1931  arrayTransposed.cend(row), comparitor) - 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:
1957  {
1959 
1960  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
1961  {
1962  return lhs < rhs;
1963  };
1964 
1965  switch (inAxis)
1966  {
1967  case Axis::NONE:
1968  {
1969  NdArray<uint32> returnArray = { static_cast<uint32>(stl_algorithms::min_element(cbegin(),
1970  cend(), comparitor) - cbegin()) };
1971  return returnArray;
1972  }
1973  case Axis::COL:
1974  {
1975  NdArray<uint32> returnArray(1, shape_.rows);
1976  for (uint32 row = 0; row < shape_.rows; ++row)
1977  {
1978  returnArray(0, row) = static_cast<uint32>(stl_algorithms::min_element(cbegin(row),
1979  cend(row), comparitor) - cbegin(row));
1980  }
1981 
1982  return returnArray;
1983  }
1984  case Axis::ROW:
1985  {
1986  NdArray<dtype> arrayTransposed = transpose();
1987  NdArray<uint32> returnArray(1, arrayTransposed.shape_.rows);
1988  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1989  {
1990  returnArray(0, row) = static_cast<uint32>(stl_algorithms::min_element(arrayTransposed.cbegin(row),
1991  arrayTransposed.cend(row), comparitor) - arrayTransposed.cbegin(row));
1992  }
1993 
1994  return returnArray;
1995  }
1996  default:
1997  {
1998  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1999  return {}; // get rid of compiler warning
2000  }
2001  }
2002  }
2003 
2004  //============================================================================
2005  // Method Description:
2016  {
2018 
2019  switch (inAxis)
2020  {
2021  case Axis::NONE:
2022  {
2023  std::vector<uint32> idx(size_);
2024  std::iota(idx.begin(), idx.end(), 0);
2025 
2026  const auto function = [this](uint32 i1, uint32 i2) noexcept -> bool
2027  {
2028  return (*this)[i1] < (*this)[i2];
2029  };
2030 
2031  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2032  return NdArray<uint32>(idx);
2033  }
2034  case Axis::COL:
2035  {
2036  NdArray<uint32> returnArray(shape_);
2037  for (uint32 row = 0; row < shape_.rows; ++row)
2038  {
2039  std::vector<uint32> idx(shape_.cols);
2040  std::iota(idx.begin(), idx.end(), 0);
2041 
2042  const auto function = [this, row](uint32 i1, uint32 i2) noexcept -> bool
2043  {
2044  return operator()(row, i1) < operator()(row, i2);
2045  };
2046 
2047  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2048 
2049  for (uint32 col = 0; col < shape_.cols; ++col)
2050  {
2051  returnArray(row, col) = idx[col];
2052  }
2053  }
2054  return returnArray;
2055  }
2056  case Axis::ROW:
2057  {
2058  NdArray<dtype> arrayTransposed = transpose();
2059  NdArray<uint32> returnArray(shape_.cols, shape_.rows);
2060  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
2061  {
2062  std::vector<uint32> idx(arrayTransposed.shape_.cols);
2063  std::iota(idx.begin(), idx.end(), 0);
2064 
2065  const auto function = [&arrayTransposed, row](uint32 i1, uint32 i2) noexcept -> bool
2066  {
2067  return arrayTransposed(row, i1) < arrayTransposed(row, i2);
2068  };
2069 
2070  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2071 
2072  for (uint32 col = 0; col < arrayTransposed.shape_.cols; ++col)
2073  {
2074  returnArray(row, col) = idx[col];
2075  }
2076  }
2077  return returnArray.transpose();
2078  }
2079  default:
2080  {
2081  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2082  return {}; // get rid of compiler warning
2083  }
2084  }
2085  }
2086 
2087  //============================================================================
2088  // Method Description:
2097  template<typename dtypeOut, typename dtype_ = dtype,
2102  {
2103  NdArray<dtypeOut> outArray(shape_);
2104 
2105  if (is_same_v<dtypeOut, dtype>)
2106  {
2107  std::copy(cbegin(), cend(), outArray.begin());
2108  }
2109  else
2110  {
2111  const auto function = [](dtype value) -> dtypeOut
2112  {
2113  return static_cast<dtypeOut>(value);
2114  };
2115 
2116  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2117  }
2118 
2119  return outArray;
2120  }
2121 
2122  //============================================================================
2123  // Method Description:
2132  template<typename dtypeOut, typename dtype_ = dtype,
2137  {
2138  NdArray<dtypeOut> outArray(shape_);
2139 
2140  const auto function = [](const_reference value) -> dtypeOut
2141  {
2142  return std::complex<typename dtypeOut::value_type>(value);
2143  };
2144 
2145  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2146 
2147  return outArray;
2148  }
2149 
2150  //============================================================================
2151  // Method Description:
2160  template<typename dtypeOut, typename dtype_ = dtype,
2165  {
2166  NdArray<dtypeOut> outArray(shape_);
2167 
2168  if (std::is_same<dtypeOut, dtype>::value)
2169  {
2170  std::copy(cbegin(), cend(), outArray.begin());
2171  }
2172  else
2173  {
2174  const auto function = [](const_reference value) noexcept -> dtypeOut
2175  {
2176  return complex_cast<typename dtypeOut::value_type>(value);
2177  };
2178 
2179  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2180  }
2181 
2182  return outArray;
2183  }
2184 
2185  //============================================================================
2186  // Method Description:
2195  template<typename dtypeOut, typename dtype_ = dtype,
2200  {
2201  NdArray<dtypeOut> outArray(shape_);
2202 
2203  const auto function = [](const_reference value) -> dtypeOut
2204  {
2205  return static_cast<dtypeOut>(value.real());
2206  };
2207 
2208  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2209 
2210  return outArray;
2211  }
2212 
2213  //============================================================================
2214  // Method Description:
2220  const_reference back() const noexcept
2221  {
2222  return *(cend() - 1);
2223  }
2224 
2225  //============================================================================
2226  // Method Description:
2232  reference back() noexcept
2233  {
2234  return *(end() - 1);
2235  }
2236 
2237  //============================================================================
2238  // Method Description:
2245  {
2246  return *(cend(row) - 1);
2247  }
2248 
2249  //============================================================================
2250  // Method Description:
2257  {
2258  return *(end(row) - 1);
2259  }
2260 
2261  //============================================================================
2262  // Method Description:
2271  {
2272  STATIC_ASSERT_INTEGER(dtype);
2273 
2275  [](dtype& value) noexcept -> void
2276  {
2277  value = endian::byteSwap(value);
2278  }
2279  );
2280 
2281  switch (endianess_)
2282  {
2283  case Endian::NATIVE:
2284  {
2286  break;
2287  }
2288  case Endian::LITTLE:
2289  {
2290  endianess_ = Endian::BIG;
2291  break;
2292  }
2293  case Endian::BIG:
2294  {
2295  endianess_ = Endian::LITTLE;
2296  break;
2297  }
2298  }
2299 
2300  return *this;
2301  }
2302 
2303  //============================================================================
2304  // Method Description:
2315  {
2317 
2318  NdArray<dtype> outArray(shape_);
2319  stl_algorithms::transform(cbegin(), cend(), outArray.begin(),
2320  [inMin, inMax](dtype value) noexcept -> dtype
2321  {
2322 #ifdef __cpp_lib_clamp
2323  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
2324  {
2325  return lhs < rhs;
2326  };
2327 
2328  return std::clamp(value, inMin, inMax, comparitor);
2329 #else
2330  if (value < inMin)
2331  {
2332  return inMin;
2333  }
2334  else if (value > inMax)
2335  {
2336  return inMax;
2337  }
2338 
2339  return value;
2340 #endif
2341  });
2342 
2343  return outArray;
2344  }
2345 
2346  //============================================================================
2347  // Method Description:
2355  {
2356  return operator()(rSlice(), inColumn);
2357  }
2358 
2359  //============================================================================
2360  // Method Description:
2369  {
2371 
2372  switch (inAxis)
2373  {
2374  case Axis::NONE:
2375  {
2376  NdArray<bool> returnArray = { stl_algorithms::find(cbegin(), cend(), inValue) != cend() };
2377  return returnArray;
2378  }
2379  case Axis::COL:
2380  {
2381  NdArray<bool> returnArray(1, shape_.rows);
2382  for (uint32 row = 0; row < shape_.rows; ++row)
2383  {
2384  returnArray(0, row) = stl_algorithms::find(cbegin(row), cend(row), inValue) != cend(row);
2385  }
2386 
2387  return returnArray;
2388  }
2389  case Axis::ROW:
2390  {
2391  NdArray<dtype> transArray = transpose();
2392  NdArray<bool> returnArray(1, transArray.shape_.rows);
2393  for (uint32 row = 0; row < transArray.shape_.rows; ++row)
2394  {
2395  returnArray(0, row) = stl_algorithms::find(transArray.cbegin(row), transArray.cend(row), inValue) != transArray.cend(row);
2396  }
2397 
2398  return returnArray;
2399  }
2400  default:
2401  {
2402  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2403  return {}; // get rid of compiler warning
2404  }
2405  }
2406  }
2407 
2408  //============================================================================
2409  // Method Description:
2418  {
2419  return NdArray<dtype>(*this);
2420  }
2421 
2422  //============================================================================
2423  // Method Description:
2434  {
2436 
2437  switch (inAxis)
2438  {
2439  case Axis::NONE:
2440  {
2441  NdArray<dtype> returnArray(1, size_);
2442  returnArray[0] = front();
2443  for (uint32 i = 1; i < size_; ++i)
2444  {
2445  returnArray[i] = returnArray[i - 1] * array_[i];
2446  }
2447 
2448  return returnArray;
2449  }
2450  case Axis::COL:
2451  {
2452  NdArray<dtype> returnArray(shape_);
2453  for (uint32 row = 0; row < shape_.rows; ++row)
2454  {
2455  returnArray(row, 0) = operator()(row, 0);
2456  for (uint32 col = 1; col < shape_.cols; ++col)
2457  {
2458  returnArray(row, col) = returnArray(row, col - 1) * operator()(row, col);
2459  }
2460  }
2461 
2462  return returnArray;
2463  }
2464  case Axis::ROW:
2465  {
2466  NdArray<dtype> returnArray(shape_);
2467  for (uint32 col = 0; col < shape_.cols; ++col)
2468  {
2469  returnArray(0, col) = operator()(0, col);
2470  for (uint32 row = 1; row < shape_.rows; ++row)
2471  {
2472  returnArray(row, col) = returnArray(row - 1, col) * operator()(row, col);
2473  }
2474  }
2475 
2476  return returnArray;
2477  }
2478  default:
2479  {
2480  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2481  return {}; // get rid of compiler warning
2482  }
2483  }
2484  }
2485 
2486  //============================================================================
2487  // Method Description:
2498  {
2500 
2501  switch (inAxis)
2502  {
2503  case Axis::NONE:
2504  {
2505  NdArray<dtype> returnArray(1, size_);
2506  returnArray[0] = front();
2507  for (uint32 i = 1; i < size_; ++i)
2508  {
2509  returnArray[i] = returnArray[i - 1] + array_[i];
2510  }
2511 
2512  return returnArray;
2513  }
2514  case Axis::COL:
2515  {
2516  NdArray<dtype> returnArray(shape_);
2517  for (uint32 row = 0; row < shape_.rows; ++row)
2518  {
2519  returnArray(row, 0) = operator()(row, 0);
2520  for (uint32 col = 1; col < shape_.cols; ++col)
2521  {
2522  returnArray(row, col) = returnArray(row, col - 1) + operator()(row, col);
2523  }
2524  }
2525 
2526  return returnArray;
2527  }
2528  case Axis::ROW:
2529  {
2530  NdArray<dtype> returnArray(shape_);
2531  for (uint32 col = 0; col < shape_.cols; ++col)
2532  {
2533  returnArray(0, col) = operator()(0, col);
2534  for (uint32 row = 1; row < shape_.rows; ++row)
2535  {
2536  returnArray(row, col) = returnArray(row - 1, col) + operator()(row, col);
2537  }
2538  }
2539 
2540  return returnArray;
2541  }
2542  default:
2543  {
2544  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2545  return {}; // get rid of compiler warning
2546  }
2547  }
2548  }
2549 
2550  //============================================================================
2551  // Method Description:
2555  pointer data() noexcept
2556  {
2557  return array_;
2558  }
2559 
2560  //============================================================================
2561  // Method Description:
2565  const_pointer data() const noexcept
2566  {
2567  return array_;
2568  }
2569 
2570  //============================================================================
2571  // Method Description:
2578  {
2579  ownsPtr_ = false;
2580  return data();
2581  }
2582 
2583  //============================================================================
2584  // Method Description:
2594  NdArray<dtype> diagonal(int32 inOffset = 0, Axis inAxis = Axis::ROW) const
2595  {
2596  switch (inAxis)
2597  {
2598  case Axis::ROW:
2599  {
2600  std::vector<dtype> diagnolValues;
2601  int32 col = inOffset;
2602  for (uint32 row = 0; row < shape_.rows; ++row)
2603  {
2604  if (col < 0)
2605  {
2606  ++col;
2607  continue;
2608  }
2609  if (col >= static_cast<int32>(shape_.cols))
2610  {
2611  break;
2612  }
2613 
2614  diagnolValues.push_back(operator()(row, static_cast<uint32>(col)));
2615  ++col;
2616  }
2617 
2618  return NdArray<dtype>(diagnolValues);
2619  }
2620  case Axis::COL:
2621  {
2622  std::vector<dtype> diagnolValues;
2623  uint32 col = 0;
2624  for (int32 row = inOffset; row < static_cast<int32>(shape_.rows); ++row)
2625  {
2626  if (row < 0)
2627  {
2628  ++col;
2629  continue;
2630  }
2631  if (col >= shape_.cols)
2632  {
2633  break;
2634  }
2635 
2636  diagnolValues.push_back(operator()(static_cast<uint32>(row), col));
2637  ++col;
2638  }
2639 
2640  return NdArray<dtype>(diagnolValues);
2641  }
2642  default:
2643  {
2644  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2645  return {}; // get rid of compiler warning
2646  }
2647  }
2648  }
2649 
2650  //============================================================================
2651  // Method Description:
2664  NdArray<dtype> dot(const NdArray<dtype>& inOtherArray) const
2665  {
2667 
2668  if (shape_ == inOtherArray.shape_ && (shape_.rows == 1 || shape_.cols == 1))
2669  {
2670  dtype dotProduct = std::inner_product(cbegin(), cend(), inOtherArray.cbegin(), dtype{ 0 });
2671  NdArray<dtype> returnArray = { dotProduct };
2672  return returnArray;
2673  }
2674  if (shape_.cols == inOtherArray.shape_.rows)
2675  {
2676  // 2D array, use matrix multiplication
2677  NdArray<dtype> returnArray(shape_.rows, inOtherArray.shape_.cols);
2678  auto otherArrayT = inOtherArray.transpose();
2679 
2680  for (uint32 i = 0; i < shape_.rows; ++i)
2681  {
2682  for (uint32 j = 0; j < otherArrayT.shape_.rows; ++j)
2683  {
2684  returnArray(i, j) = std::inner_product(otherArrayT.cbegin(j), otherArrayT.cend(j), cbegin(i), dtype{ 0 });
2685  }
2686  }
2687 
2688  return returnArray;
2689  }
2690 
2691  std::string errStr = "shapes of [" + utils::num2str(shape_.rows) + ", " + utils::num2str(shape_.cols) + "]";
2692  errStr += " and [" + utils::num2str(inOtherArray.shape_.rows) + ", " + utils::num2str(inOtherArray.shape_.cols) + "]";
2693  errStr += " are not consistent.";
2695 
2696  return NdArray<dtype>(); // get rid of compiler warning
2697  }
2698 
2699  //============================================================================
2700  // Method Description:
2708  void dump(const std::string& inFilename) const
2709  {
2710  filesystem::File f(inFilename);
2711  if (!f.hasExt())
2712  {
2713  f.withExt(".bin");
2714  }
2715 
2716  std::ofstream ofile(f.fullName().c_str(), std::ios::binary);
2717  if (!ofile.good())
2718  {
2719  THROW_RUNTIME_ERROR("Unable to open the input file:\n\t" + inFilename);
2720  }
2721 
2722  if (array_ != nullptr)
2723  {
2724  ofile.write(reinterpret_cast<const char*>(array_), size_ * sizeof(dtype));
2725  }
2726  ofile.close();
2727  }
2728 
2729  //============================================================================
2730  // Method Description:
2736  Endian endianess() const noexcept
2737  {
2738  STATIC_ASSERT_ARITHMETIC(dtype);
2739 
2740  return endianess_;
2741  }
2742 
2743  //============================================================================
2744  // Method Description:
2754  NdArray<dtype>& fill(value_type inFillValue) noexcept
2755  {
2756  stl_algorithms::fill(begin(), end(), inFillValue);
2757  return *this;
2758  }
2759 
2760  //============================================================================
2761  // Method Description:
2769  {
2771 
2772  std::vector<uint32> indices;
2773  uint32 idx = 0;
2774  for (auto value : *this)
2775  {
2776  if (value != dtype{ 0 })
2777  {
2778  indices.push_back(idx);
2779  }
2780  ++idx;
2781  }
2782 
2783  return NdArray<uint32>(indices);
2784  }
2785 
2786  //============================================================================
2787  // Method Description:
2796  {
2797  NdArray<dtype> outArray(1, size_);
2798  stl_algorithms::copy(cbegin(), cend(), outArray.begin());
2799  return outArray;
2800  }
2801 
2802  //============================================================================
2803  // Method Description:
2809  const_reference front() const noexcept
2810  {
2811  return *cbegin();
2812  }
2813 
2814  //============================================================================
2815  // Method Description:
2821  reference front() noexcept
2822  {
2823  return *begin();
2824  }
2825 
2826  //============================================================================
2827  // Method Description:
2834  {
2835  return *cbegin(row);
2836  }
2837 
2838  //============================================================================
2839  // Method Description:
2846  {
2847  return *begin(row);
2848  }
2849 
2850  //============================================================================
2851  // Method Description:
2860  {
2861  return operator[](inIndices);
2862  }
2863 
2864  //============================================================================
2865  // Method Description:
2876  {
2877  return operator[](inMask);
2878  }
2879 
2880  //============================================================================
2881  // Method Description:
2888  bool isempty() const noexcept
2889  {
2890  return size_ == 0;
2891  }
2892 
2893  //============================================================================
2894  // Method Description:
2901  bool isflat() const noexcept
2902  {
2903  return shape_.rows == 1 || shape_.cols == 1;
2904  }
2905 
2906  //============================================================================
2907  // Method Description:
2914  {
2916 
2917  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
2918  {
2919  return lhs < rhs;
2920  };
2921 
2922  switch (inAxis)
2923  {
2924  case Axis::NONE:
2925  {
2926  return { stl_algorithms::is_sorted(cbegin(), cend(), comparitor) };
2927  }
2928  case Axis::ROW:
2929  {
2930  NdArray<bool> returnArray(shape_.cols, 1);
2931  auto transposedArray = transpose();
2932  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
2933  {
2934  returnArray(0, row) = stl_algorithms::is_sorted(transposedArray.cbegin(row),
2935  transposedArray.cend(row), comparitor);
2936  }
2937 
2938  return returnArray;
2939  }
2940  case Axis::COL:
2941  {
2942  NdArray<bool> returnArray(1, shape_.rows);
2943  for (uint32 row = 0; row < shape_.rows; ++row)
2944  {
2945  returnArray(0, row) = stl_algorithms::is_sorted(cbegin(row), cend(row), comparitor);
2946  }
2947 
2948  return returnArray;
2949  }
2950  default:
2951  {
2952  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2953  return {}; // get rid of compiler warning
2954  }
2955  }
2956  }
2957 
2958  //============================================================================
2959  // Method Description:
2964  bool issquare() const noexcept
2965  {
2966  return shape_.issquare();
2967  }
2968 
2969  //============================================================================
2970  // Method Description:
2979  {
2980  if (size_ != 1)
2981  {
2982  THROW_INVALID_ARGUMENT_ERROR("Can only convert an array of size 1 to a C++ scaler");
2983  }
2984 
2985  return front();
2986  }
2987 
2988  //============================================================================
2989  // Method Description:
3000  {
3002 
3003  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3004  {
3005  return lhs < rhs;
3006  };
3007 
3008  switch (inAxis)
3009  {
3010  case Axis::NONE:
3011  {
3012  NdArray<dtype> returnArray = { *stl_algorithms::max_element(cbegin(), cend(), comparitor) };
3013  return returnArray;
3014  }
3015  case Axis::COL:
3016  {
3017  NdArray<dtype> returnArray(1, shape_.rows);
3018  for (uint32 row = 0; row < shape_.rows; ++row)
3019  {
3020  returnArray(0, row) = *stl_algorithms::max_element(cbegin(row), cend(row), comparitor);
3021  }
3022 
3023  return returnArray;
3024  }
3025  case Axis::ROW:
3026  {
3027  NdArray<dtype> transposedArray = transpose();
3028  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3029  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3030  {
3031  returnArray(0, row) = *stl_algorithms::max_element(transposedArray.cbegin(row),
3032  transposedArray.cend(row), comparitor);
3033  }
3034 
3035  return returnArray;
3036  }
3037  default:
3038  {
3039  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3040  return {}; // get rid of compiler warning
3041  }
3042  }
3043  }
3044 
3045  //============================================================================
3046  // Method Description:
3057  {
3059 
3060  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3061  {
3062  return lhs < rhs;
3063  };
3064 
3065  switch (inAxis)
3066  {
3067  case Axis::NONE:
3068  {
3069  NdArray<dtype> returnArray = { *stl_algorithms::min_element(cbegin(), cend(), comparitor) };
3070  return returnArray;
3071  }
3072  case Axis::COL:
3073  {
3074  NdArray<dtype> returnArray(1, shape_.rows);
3075  for (uint32 row = 0; row < shape_.rows; ++row)
3076  {
3077  returnArray(0, row) = *stl_algorithms::min_element(cbegin(row), cend(row), comparitor);
3078  }
3079 
3080  return returnArray;
3081  }
3082  case Axis::ROW:
3083  {
3084  NdArray<dtype> transposedArray = transpose();
3085  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3086  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3087  {
3088  returnArray(0, row) = *stl_algorithms::min_element(transposedArray.cbegin(row),
3089  transposedArray.cend(row), comparitor);
3090  }
3091 
3092  return returnArray;
3093  }
3094  default:
3095  {
3096  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3097  return {}; // get rid of compiler warning
3098  }
3099  }
3100  }
3101 
3102  //============================================================================
3103  // Method Description:
3116  {
3118 
3119  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3120  {
3121  return lhs < rhs;
3122  };
3123 
3124  if (size_ == 0)
3125  {
3126  THROW_RUNTIME_ERROR("Median is undefined for an array of size = 0.");
3127  }
3128 
3129  switch (inAxis)
3130  {
3131  case Axis::NONE:
3132  {
3133  NdArray<dtype> copyArray(*this);
3134 
3135  const uint32 middleIdx = size_ / 2; // integer division
3136  stl_algorithms::nth_element(copyArray.begin(), copyArray.begin() + middleIdx, copyArray.end(), comparitor);
3137 
3138  dtype medianValue = copyArray.array_[middleIdx];
3139  if (size_ % 2 == 0)
3140  {
3141  const uint32 lhsIndex = middleIdx - 1;
3142  stl_algorithms::nth_element(copyArray.begin(), copyArray.begin() + lhsIndex, copyArray.end(), comparitor);
3143  medianValue = (medianValue + copyArray.array_[lhsIndex]) / dtype{2}; // potentially integer division, ok
3144  }
3145 
3146  return { medianValue };
3147  }
3148  case Axis::COL:
3149  {
3150  NdArray<dtype> copyArray(*this);
3151  NdArray<dtype> returnArray(1, shape_.rows);
3152 
3153  const bool isEven = shape_.cols % 2 == 0;
3154  for (uint32 row = 0; row < shape_.rows; ++row)
3155  {
3156  const uint32 middleIdx = shape_.cols / 2; // integer division
3157  stl_algorithms::nth_element(copyArray.begin(row), copyArray.begin(row) + middleIdx,
3158  copyArray.end(row), comparitor);
3159 
3160  dtype medianValue = copyArray(row, middleIdx);
3161  if (isEven)
3162  {
3163  const uint32 lhsIndex = middleIdx - 1;
3164  stl_algorithms::nth_element(copyArray.begin(row), copyArray.begin(row) + lhsIndex,
3165  copyArray.end(row), comparitor);
3166  medianValue = (medianValue + copyArray(row, lhsIndex)) / dtype{2}; // potentially integer division, ok
3167  }
3168 
3169  returnArray(0, row) = medianValue;
3170  }
3171 
3172  return returnArray;
3173  }
3174  case Axis::ROW:
3175  {
3176  NdArray<dtype> transposedArray = transpose();
3177  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3178 
3179  const bool isEven = shape_.rows % 2 == 0;
3180  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3181  {
3182  const uint32 middleIdx = transposedArray.shape_.cols / 2; // integer division
3183  stl_algorithms::nth_element(transposedArray.begin(row), transposedArray.begin(row) + middleIdx,
3184  transposedArray.end(row), comparitor);
3185 
3186  dtype medianValue = transposedArray(row, middleIdx);
3187  if (isEven)
3188  {
3189  const uint32 lhsIndex = middleIdx - 1;
3190  stl_algorithms::nth_element(transposedArray.begin(row), transposedArray.begin(row) + lhsIndex,
3191  transposedArray.end(row), comparitor);
3192  medianValue = (medianValue + transposedArray(row, lhsIndex)) / dtype{2}; // potentially integer division, ok
3193  }
3194 
3195  returnArray(0, row) = medianValue;
3196  }
3197 
3198  return returnArray;
3199  }
3200  default:
3201  {
3202  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3203  return {}; // get rid of compiler warning
3204  }
3205  }
3206  }
3207 
3208  //============================================================================
3209  // Method Description:
3213  NdArray<dtype>& nans() noexcept
3214  {
3215  STATIC_ASSERT_FLOAT(dtype);
3216 
3218  return *this;
3219  }
3220 
3221  //============================================================================
3222  // Method Description:
3230  uint64 nbytes() const noexcept
3231  {
3232  return static_cast<uint64>(sizeof(dtype) * size_);
3233  }
3234 
3235  //============================================================================
3236  // Method Description:
3247  NdArray<dtype> newbyteorder(Endian inEndianess) const
3248  {
3249  STATIC_ASSERT_INTEGER(dtype);
3250 
3251  const bool nativeIsLittle = endian::isLittleEndian();
3252 
3253  switch (endianess_)
3254  {
3255  case Endian::NATIVE:
3256  {
3257  switch (inEndianess)
3258  {
3259  case Endian::NATIVE:
3260  {
3261  return NdArray(*this);
3262  }
3263  case Endian::BIG:
3264  {
3265  if (nativeIsLittle)
3266  {
3267  NdArray<dtype> outArray(shape_);
3268 
3269  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3270 
3271  outArray.endianess_ = Endian::BIG;
3272  return outArray;
3273  }
3274  else
3275  {
3276  auto outArray = NdArray(*this);
3277  outArray.endianess_ = Endian::BIG;
3278  return outArray;
3279  }
3280  }
3281  case Endian::LITTLE:
3282  {
3283  if (nativeIsLittle)
3284  {
3285  auto outArray = NdArray(*this);
3286  outArray.endianess_ = Endian::LITTLE;
3287  return outArray;
3288  }
3289  else
3290  {
3291  NdArray<dtype> outArray(shape_);
3292 
3293  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3294 
3295  outArray.endianess_ = Endian::LITTLE;
3296  return outArray;
3297  }
3298  }
3299  default:
3300  {
3301  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3302  return {}; // get rid of compiler warning
3303  }
3304  }
3305  break;
3306  }
3307  case Endian::BIG:
3308  {
3309  switch (inEndianess)
3310  {
3311  case Endian::NATIVE:
3312  {
3313  if (nativeIsLittle)
3314  {
3315  NdArray<dtype> outArray(shape_);
3316 
3317  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3318 
3319  outArray.endianess_ = Endian::NATIVE;
3320  return outArray;
3321  }
3322  else
3323  {
3324  auto outArray = NdArray(*this);
3325  outArray.endianess_ = Endian::NATIVE;
3326  return outArray;
3327  }
3328  }
3329  case Endian::BIG:
3330  {
3331  return NdArray(*this);
3332  }
3333  case Endian::LITTLE:
3334  {
3335  NdArray<dtype> outArray(shape_);
3336 
3337  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3338 
3339  outArray.endianess_ = Endian::LITTLE;
3340  return outArray;
3341  }
3342  default:
3343  {
3344  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3345  return {}; // get rid of compiler warning
3346  }
3347  }
3348  break;
3349  }
3350  case Endian::LITTLE:
3351  {
3352  switch (inEndianess)
3353  {
3354  case Endian::NATIVE:
3355  {
3356  if (nativeIsLittle)
3357  {
3358  auto outArray = NdArray(*this);
3359  outArray.endianess_ = Endian::NATIVE;
3360  return outArray;
3361  }
3362  else
3363  {
3364  NdArray<dtype> outArray(shape_);
3365 
3366  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3367 
3368  outArray.endianess_ = Endian::NATIVE;
3369  return outArray;
3370  }
3371  }
3372  case Endian::BIG:
3373  {
3374  NdArray<dtype> outArray(shape_);
3375 
3376  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3377 
3378  outArray.endianess_ = Endian::BIG;
3379  return outArray;
3380  }
3381  case Endian::LITTLE:
3382  {
3383  return NdArray(*this);
3384  }
3385  default:
3386  {
3387  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3388  return {}; // get rid of compiler warning
3389  }
3390  }
3391  break;
3392  }
3393  default:
3394  {
3395  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3396  return {}; // get rid of compiler warning
3397  }
3398  }
3399  }
3400 
3401  //============================================================================
3402  // Method Description:
3413  {
3415 
3416  const auto function = [](dtype i) -> bool
3417  {
3418  return i != dtype{ 0 };
3419  };
3420 
3421  switch (inAxis)
3422  {
3423  case Axis::NONE:
3424  {
3425  NdArray<bool> returnArray = { stl_algorithms::none_of(cbegin(), cend(), function) };
3426  return returnArray;
3427  }
3428  case Axis::COL:
3429  {
3430  NdArray<bool> returnArray(1, shape_.rows);
3431  for (uint32 row = 0; row < shape_.rows; ++row)
3432  {
3433  returnArray(0, row) = stl_algorithms::none_of(cbegin(row), cend(row), function);
3434  }
3435 
3436  return returnArray;
3437  }
3438  case Axis::ROW:
3439  {
3440  NdArray<dtype> arrayTransposed = transpose();
3441  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
3442  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
3443  {
3444  returnArray(0, row) = stl_algorithms::none_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
3445  }
3446 
3447  return returnArray;
3448  }
3449  default:
3450  {
3451  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3452  return {}; // get rid of compiler warning
3453  }
3454  }
3455  }
3456 
3457  //============================================================================
3458  // Method Description:
3468  std::pair<NdArray<uint32>, NdArray<uint32>> nonzero() const;
3469 
3470  //============================================================================
3471  // Method Description:
3478  uint32 numCols() const noexcept
3479  {
3480  return shape_.cols;
3481  }
3482 
3483  //============================================================================
3484  // Method Description:
3491  uint32 numRows() const noexcept
3492  {
3493  return shape_.rows;
3494  }
3495 
3496  //============================================================================
3497  // Method Description:
3501  NdArray<dtype>& ones() noexcept
3502  {
3504 
3505  fill(dtype{ 1 });
3506  return *this;
3507  }
3508 
3509  //============================================================================
3510  // Method Description:
3515  bool ownsInternalData() noexcept
3516  {
3517  return ownsPtr_;
3518  }
3519 
3520  //============================================================================
3521  // Method Description:
3537  {
3539 
3540  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3541  {
3542  return lhs < rhs;
3543  };
3544 
3545  switch (inAxis)
3546  {
3547  case Axis::NONE:
3548  {
3549  if (inKth >= size_)
3550  {
3551  std::string errStr = "kth(=" + utils::num2str(inKth);
3552  errStr += ") out of bounds (" + utils::num2str(size_) + ")";
3554  }
3555 
3556  stl_algorithms::nth_element(begin(), begin() + inKth, end(), comparitor);
3557  break;
3558  }
3559  case Axis::COL:
3560  {
3561  if (inKth >= shape_.cols)
3562  {
3563  std::string errStr = "kth(=" + utils::num2str(inKth);
3564  errStr += ") out of bounds (" + utils::num2str(shape_.cols) + ")";
3566  }
3567 
3568  for (uint32 row = 0; row < shape_.rows; ++row)
3569  {
3570  stl_algorithms::nth_element(begin(row), begin(row) + inKth, end(row), comparitor);
3571  }
3572  break;
3573  }
3574  case Axis::ROW:
3575  {
3576  if (inKth >= shape_.rows)
3577  {
3578  std::string errStr = "kth(=" + utils::num2str(inKth);
3579  errStr += ") out of bounds (" + utils::num2str(shape_.rows) + ")";
3581  }
3582 
3583  NdArray<dtype> transposedArray = transpose();
3584  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3585  {
3586  stl_algorithms::nth_element(transposedArray.begin(row), transposedArray.begin(row) + inKth,
3587  transposedArray.end(row), comparitor);
3588  }
3589  *this = transposedArray.transpose();
3590  break;
3591  }
3592  }
3593 
3594  return *this;
3595  }
3596 
3597  //============================================================================
3598  // Method Description:
3602  void print() const
3603  {
3605 
3606  std::cout << *this;
3607  }
3608 
3609  //============================================================================
3610  // Method Description:
3621  {
3623 
3624  switch (inAxis)
3625  {
3626  case Axis::NONE:
3627  {
3628  dtype product = std::accumulate(cbegin(), cend(),
3629  dtype{ 1 }, std::multiplies<dtype>());
3630  NdArray<dtype> returnArray = { product };
3631  return returnArray;
3632  }
3633  case Axis::COL:
3634  {
3635  NdArray<dtype> returnArray(1, shape_.rows);
3636  for (uint32 row = 0; row < shape_.rows; ++row)
3637  {
3638  returnArray(0, row) = std::accumulate(cbegin(row), cend(row),
3639  dtype{ 1 }, std::multiplies<dtype>());
3640  }
3641 
3642  return returnArray;
3643  }
3644  case Axis::ROW:
3645  {
3646  NdArray<dtype> transposedArray = transpose();
3647  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3648  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3649  {
3650  returnArray(0, row) = std::accumulate(transposedArray.cbegin(row), transposedArray.cend(row),
3651  dtype{ 1 }, std::multiplies<dtype>());
3652  }
3653 
3654  return returnArray;
3655  }
3656  default:
3657  {
3658  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3659  return {}; // get rid of compiler warning
3660  }
3661  }
3662  }
3663 
3664  //============================================================================
3665  // Method Description:
3676  {
3678 
3679  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3680  {
3681  return lhs < rhs;
3682  };
3683 
3684  switch (inAxis)
3685  {
3686  case Axis::NONE:
3687  {
3688  const auto result = stl_algorithms::minmax_element(cbegin(), cend(), comparitor);
3689  NdArray<dtype> returnArray = { *result.second - *result.first };
3690  return returnArray;
3691  }
3692  case Axis::COL:
3693  {
3694  NdArray<dtype> returnArray(1, shape_.rows);
3695  for (uint32 row = 0; row < shape_.rows; ++row)
3696  {
3697  const auto result = stl_algorithms::minmax_element(cbegin(row), cend(row), comparitor);
3698  returnArray(0, row) = *result.second - *result.first;
3699  }
3700 
3701  return returnArray;
3702  }
3703  case Axis::ROW:
3704  {
3705  NdArray<dtype> transposedArray = transpose();
3706  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3707  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3708  {
3709  const auto result = stl_algorithms::minmax_element(transposedArray.cbegin(row), transposedArray.cend(row), comparitor);
3710  returnArray(0, row) = *result.second - *result.first;
3711  }
3712 
3713  return returnArray;
3714  }
3715  default:
3716  {
3717  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3718  return {}; // get rid of compiler warning
3719  }
3720  }
3721  }
3722 
3723  //============================================================================
3724  // Method Description:
3732  NdArray<dtype>& put(int32 inIndex, value_type inValue)
3733  {
3734  at(inIndex) = inValue;
3735 
3736  return *this;
3737  }
3738 
3739  //============================================================================
3740  // Method Description:
3749  NdArray<dtype>& put(int32 inRow, int32 inCol, value_type inValue)
3750  {
3751  at(inRow, inCol) = inValue;
3752 
3753  return *this;
3754  }
3755 
3756  //============================================================================
3757  // Method Description:
3765  NdArray<dtype>& put(const NdArray<uint32>& inIndices, value_type inValue)
3766  {
3767  for (auto index : inIndices)
3768  {
3769  put(index, inValue);
3770  }
3771 
3772  return *this;
3773  }
3774 
3775  //============================================================================
3776  // Method Description:
3784  NdArray<dtype>& put(const NdArray<uint32>& inIndices, const NdArray<dtype>& inValues)
3785  {
3786  if (inIndices.size() != inValues.size())
3787  {
3788  THROW_INVALID_ARGUMENT_ERROR("Input indices do not match values dimensions.");
3789  }
3790 
3791  uint32 counter = 0;
3792  for (auto index : inIndices)
3793  {
3794  put(index, inValues[counter++]);
3795  }
3796 
3797  return *this;
3798  }
3799 
3800  //============================================================================
3801  // Method Description:
3809  NdArray<dtype>& put(const Slice& inSlice, value_type inValue)
3810  {
3811  Slice inSliceCopy(inSlice);
3812  inSliceCopy.makePositiveAndValidate(size_);
3813 
3814  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
3815  {
3816  put(i, inValue);
3817  }
3818 
3819  return *this;
3820  }
3821 
3822  //============================================================================
3823  // Method Description:
3831  NdArray<dtype>& put(const Slice& inSlice, const NdArray<dtype>& inValues)
3832  {
3833  Slice inSliceCopy(inSlice);
3834  inSliceCopy.makePositiveAndValidate(size_);
3835 
3836  std::vector<uint32> indices;
3837  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
3838  {
3839  indices.push_back(i);
3840  }
3841 
3842  return put(NdArray<uint32>(indices), inValues);
3843  }
3844 
3845  //============================================================================
3846  // Method Description:
3855  NdArray<dtype>& put(const Slice& inRowSlice, const Slice& inColSlice, value_type inValue)
3856  {
3857  Slice inRowSliceCopy(inRowSlice);
3858  Slice inColSliceCopy(inColSlice);
3859 
3860  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3861  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3862 
3863  std::vector<uint32> indices;
3864  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3865  {
3866  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3867  {
3868  put(row, col, inValue);
3869  }
3870  }
3871 
3872  return *this;
3873  }
3874 
3875  //============================================================================
3876  // Method Description:
3885  NdArray<dtype>& put(const Slice& inRowSlice, int32 inColIndex, value_type inValue)
3886  {
3887  Slice inRowSliceCopy(inRowSlice);
3888  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3889 
3890  std::vector<uint32> indices;
3891  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3892  {
3893  put(row, inColIndex, inValue);
3894  }
3895 
3896  return *this;
3897  }
3898 
3899  //============================================================================
3900  // Method Description:
3909  NdArray<dtype>& put(int32 inRowIndex, const Slice& inColSlice, value_type inValue)
3910  {
3911  Slice inColSliceCopy(inColSlice);
3912  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3913 
3914  std::vector<uint32> indices;
3915  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3916  {
3917  put(inRowIndex, col, inValue);
3918  }
3919 
3920  return *this;
3921  }
3922 
3923  //============================================================================
3924  // Method Description:
3933  NdArray<dtype>& put(const Slice& inRowSlice, const Slice& inColSlice, const NdArray<dtype>& inValues)
3934  {
3935  Slice inRowSliceCopy(inRowSlice);
3936  Slice inColSliceCopy(inColSlice);
3937 
3938  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3939  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3940 
3941  std::vector<uint32> indices;
3942  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3943  {
3944  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3945  {
3946  const uint32 index = row * shape_.cols + col;
3947  indices.push_back(index);
3948  }
3949  }
3950 
3951  return put(NdArray<uint32>(indices), inValues);
3952  }
3953 
3954  //============================================================================
3955  // Method Description:
3964  NdArray<dtype>& put(const Slice& inRowSlice, int32 inColIndex, const NdArray<dtype>& inValues)
3965  {
3966  Slice inRowSliceCopy(inRowSlice);
3967  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3968 
3969  std::vector<uint32> indices;
3970  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3971  {
3972  const uint32 index = row * shape_.cols + inColIndex;
3973  indices.push_back(index);
3974  }
3975 
3976  return put(NdArray<uint32>(indices), inValues);
3977  }
3978 
3979  //============================================================================
3980  // Method Description:
3989  NdArray<dtype>& put(int32 inRowIndex, const Slice& inColSlice, const NdArray<dtype>& inValues)
3990  {
3991  Slice inColSliceCopy(inColSlice);
3992  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3993 
3994  std::vector<uint32> indices;
3995  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3996  {
3997  const uint32 index = inRowIndex * shape_.cols + col;
3998  indices.push_back(index);
3999  }
4000 
4001  return put(NdArray<uint32>(indices), inValues);
4002  }
4003 
4004  //============================================================================
4005  // Method Description:
4012  {
4013  if (inMask.shape() != shape_)
4014  {
4015  THROW_INVALID_ARGUMENT_ERROR("input inMask must be the same shape as the array it is masking.");
4016  }
4017 
4018  return put(inMask.flatnonzero(), inValue);
4019  }
4020 
4021  //============================================================================
4022  // Method Description:
4028  NdArray<dtype>& putMask(const NdArray<bool>& inMask, const NdArray<dtype>& inValues)
4029  {
4030  if (inMask.shape() != shape_)
4031  {
4032  THROW_INVALID_ARGUMENT_ERROR("input inMask must be the same shape as the array it is masking.");
4033  }
4034 
4035  return put(inMask.flatnonzero(), inValues);
4036  }
4037 
4038  //============================================================================
4039  // Method Description:
4046  NdArray<dtype>& ravel() noexcept
4047  {
4048  reshape(size_);
4049  return *this;
4050  }
4051 
4052  //============================================================================
4053  // Method Description:
4063  NdArray<dtype> repeat(uint32 inNumRows, uint32 inNumCols) const
4064  {
4065  NdArray<dtype> returnArray(shape_.rows * inNumRows, shape_.cols * inNumCols);
4066 
4067  for (uint32 row = 0; row < inNumRows; ++row)
4068  {
4069  for (uint32 col = 0; col < inNumCols; ++col)
4070  {
4071  std::vector<uint32> indices(shape_.size());
4072 
4073  const uint32 rowStart = row * shape_.rows;
4074  const uint32 colStart = col * shape_.cols;
4075 
4076  const uint32 rowEnd = (row + 1) * shape_.rows;
4077  const uint32 colEnd = (col + 1) * shape_.cols;
4078 
4079  uint32 counter = 0;
4080  for (uint32 rowIdx = rowStart; rowIdx < rowEnd; ++rowIdx)
4081  {
4082  for (uint32 colIdx = colStart; colIdx < colEnd; ++colIdx)
4083  {
4084  indices[counter++] = rowIdx * returnArray.shape_.cols + colIdx;
4085  }
4086  }
4087 
4088  returnArray.put(NdArray<uint32>(indices), *this);
4089  }
4090  }
4091 
4092  return returnArray;
4093  }
4094 
4095  //============================================================================
4096  // Method Description:
4106  NdArray<dtype> repeat(const Shape& inRepeatShape) const
4107  {
4108  return repeat(inRepeatShape.rows, inRepeatShape.cols);
4109  }
4110 
4111  //============================================================================
4112  // Method Description:
4118  void replace(value_type oldValue, value_type newValue)
4119  {
4121 
4122  stl_algorithms::replace(begin(), end(), oldValue, newValue);
4123  }
4124 
4125  //============================================================================
4126  // Method Description:
4137  {
4138  if (inSize != size_)
4139  {
4140  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into shape ";
4141  errStr += "[" + utils::num2str(1) + ", " + utils::num2str(inSize) + "]";
4142  THROW_RUNTIME_ERROR(errStr);
4143  }
4144 
4145  shape_.rows = 1;
4146  shape_.cols = inSize;
4147 
4148  return *this;
4149  }
4150 
4151  //============================================================================
4152  // Method Description:
4163  NdArray<dtype>& reshape(int32 inNumRows, int32 inNumCols)
4164  {
4165  if (inNumRows < 0)
4166  {
4167  if (size_ % inNumCols == 0)
4168  {
4169  return reshape(size_ / inNumCols, inNumCols);
4170  }
4171 
4172  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into a shape ";
4173  errStr += "with " + utils::num2str(inNumCols) + " columns";
4175 
4176  }
4177 
4178  if (inNumCols < 0)
4179  {
4180  if (size_ % inNumRows == 0)
4181  {
4182  return reshape(inNumRows, size_ / inNumRows);
4183  }
4184 
4185  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into a shape ";
4186  errStr += "with " + utils::num2str(inNumRows) + " rows";
4188 
4189  }
4190 
4191  if (static_cast<uint32>(inNumRows * inNumCols) != size_)
4192  {
4193  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into shape ";
4194  errStr += "[" + utils::num2str(inNumRows) + ", " + utils::num2str(inNumCols) + "]";
4196  }
4197 
4198  shape_.rows = static_cast<uint32>(inNumRows);
4199  shape_.cols = static_cast<uint32>(inNumCols);
4200 
4201  return *this;
4202  }
4203 
4204  //============================================================================
4205  // Method Description:
4216  NdArray<dtype>& reshape(const Shape& inShape)
4217  {
4218  return reshape(inShape.rows, inShape.cols);
4219  }
4220 
4221  //============================================================================
4222  // Method Description:
4231  NdArray<dtype>& resizeFast(uint32 inNumRows, uint32 inNumCols)
4232  {
4233  newArray(Shape(inNumRows, inNumCols));
4234  return *this;
4235  }
4236 
4237  //============================================================================
4238  // Method Description:
4247  NdArray<dtype>& resizeFast(const Shape& inShape)
4248  {
4249  return resizeFast(inShape.rows, inShape.cols);
4250  }
4251 
4252  //============================================================================
4253  // Method Description:
4264  NdArray<dtype>& resizeSlow(uint32 inNumRows, uint32 inNumCols)
4265  {
4266  std::vector<dtype> oldData(size_);
4267  stl_algorithms::copy(begin(), end(), oldData.begin());
4268 
4269  const Shape inShape(inNumRows, inNumCols);
4270  const Shape oldShape = shape_;
4271 
4272  newArray(inShape);
4273 
4274  for (uint32 row = 0; row < inShape.rows; ++row)
4275  {
4276  for (uint32 col = 0; col < inShape.cols; ++col)
4277  {
4278  if (row >= oldShape.rows || col >= oldShape.cols)
4279  {
4280  operator()(row, col) = dtype{ 0 }; // zero fill
4281  }
4282  else
4283  {
4284  operator()(row, col) = oldData[row * oldShape.cols + col];
4285  }
4286  }
4287  }
4288 
4289  return *this;
4290  }
4291 
4292  //============================================================================
4293  // Method Description:
4304  NdArray<dtype>& resizeSlow(const Shape& inShape)
4305  {
4306  return resizeSlow(inShape.rows, inShape.cols);
4307  }
4308 
4309  //============================================================================
4310  // Method Description:
4321  NdArray<dtype> round(uint8 inNumDecimals = 0) const
4322  {
4323  STATIC_ASSERT_FLOAT(dtype);
4324 
4325  NdArray<dtype> returnArray(shape_);
4326  const double multFactor = utils::power(10.0, inNumDecimals);
4327  const auto function = [multFactor](dtype value) noexcept -> dtype
4328  {
4329  return static_cast<dtype>(std::nearbyint(static_cast<double>(value) * multFactor) / multFactor);
4330  };
4331 
4332  stl_algorithms::transform(cbegin(), cend(), returnArray.begin(), function);
4333 
4334  return returnArray;
4335  }
4336 
4337  //============================================================================
4338  // Method Description:
4346  {
4347  return NdArray<dtype>(cbegin(inRow), cend(inRow));
4348  }
4349 
4350  //============================================================================
4351  // Method Description:
4359  Shape shape() const noexcept
4360  {
4361  return shape_;
4362  }
4363 
4364  //============================================================================
4365  // Method Description:
4373  size_type size() const noexcept
4374  {
4375  return size_;
4376  }
4377 
4378  //============================================================================
4379  // Method Description:
4390  {
4392 
4393  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
4394  {
4395  return lhs < rhs;
4396  };
4397 
4398  switch (inAxis)
4399  {
4400  case Axis::NONE:
4401  {
4402  stl_algorithms::sort(begin(), end(), comparitor);
4403  break;
4404  }
4405  case Axis::COL:
4406  {
4407  for (uint32 row = 0; row < shape_.rows; ++row)
4408  {
4409  stl_algorithms::sort(begin(row), end(row), comparitor);
4410  }
4411  break;
4412  }
4413  case Axis::ROW:
4414  {
4415  NdArray<dtype> transposedArray = transpose();
4416  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
4417  {
4418  stl_algorithms::sort(transposedArray.begin(row), transposedArray.end(row), comparitor);
4419  }
4420 
4421  *this = transposedArray.transpose();
4422  break;
4423  }
4424  }
4425 
4426  return *this;
4427  }
4428 
4429  //============================================================================
4430  // Method Description:
4436  std::string str() const
4437  {
4439 
4440  std::string out;
4441  out += "[";
4442  for (uint32 row = 0; row < shape_.rows; ++row)
4443  {
4444  out += "[";
4445  for (uint32 col = 0; col < shape_.cols; ++col)
4446  {
4447  out += utils::value2str(operator()(row, col)) + ", ";
4448  }
4449 
4450  if (row == shape_.rows - 1)
4451  {
4452  out += "]";
4453  }
4454  else
4455  {
4456  out += "]\n";
4457  }
4458  }
4459  out += "]\n";
4460  return out;
4461  }
4462 
4463  //============================================================================
4464  // Method Description:
4475  {
4477 
4478  switch (inAxis)
4479  {
4480  case Axis::NONE:
4481  {
4482  NdArray<dtype> returnArray = { std::accumulate(cbegin(), cend(), dtype{ 0 }) };
4483  return returnArray;
4484  }
4485  case Axis::COL:
4486  {
4487  NdArray<dtype> returnArray(1, shape_.rows);
4488  for (uint32 row = 0; row < shape_.rows; ++row)
4489  {
4490  returnArray(0, row) = std::accumulate(cbegin(row), cend(row), dtype{ 0 });
4491  }
4492 
4493  return returnArray;
4494  }
4495  case Axis::ROW:
4496  {
4497  NdArray<dtype> transposedArray = transpose();
4498  const Shape transShape = transposedArray.shape();
4499  NdArray<dtype> returnArray(1, transShape.rows);
4500  for (uint32 row = 0; row < transShape.rows; ++row)
4501  {
4502  returnArray(0, row) = std::accumulate(transposedArray.cbegin(row), transposedArray.cend(row), dtype{ 0 });
4503  }
4504 
4505  return returnArray;
4506  }
4507  default:
4508  {
4509  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
4510  return {}; // get rid of compiler warning
4511  }
4512  }
4513  }
4514 
4515  //============================================================================
4516  // Method Description:
4525  {
4526  return transpose();
4527  }
4528 
4529  //============================================================================
4530  // Method Description:
4542  void tofile(const std::string& inFilename, const std::string& inSep = "") const
4543  {
4545 
4546  if (inSep.empty())
4547  {
4548  dump(inFilename);
4549  }
4550  else
4551  {
4552  filesystem::File f(inFilename);
4553  if (!f.hasExt())
4554  {
4555  f.withExt("txt");
4556  }
4557 
4558  std::ofstream ofile(f.fullName().c_str());
4559  if (!ofile.good())
4560  {
4561  THROW_RUNTIME_ERROR("Input file could not be opened:\n\t" + inFilename);
4562  }
4563 
4564  uint32 counter = 0;
4565  for (auto value : *this)
4566  {
4567  ofile << value;
4568  if (counter++ != size_ - 1)
4569  {
4570  ofile << inSep;
4571  }
4572  }
4573  ofile.close();
4574  }
4575  }
4576 
4577  //============================================================================
4578  // Method Description:
4584  std::vector<dtype> toStlVector() const
4585  {
4586  return std::vector<dtype>(cbegin(), cend());
4587  }
4588 
4589  //============================================================================
4590  // Method Description:
4601  value_type trace(uint32 inOffset = 0, Axis inAxis = Axis::ROW) const noexcept
4602  {
4604 
4605  uint32 rowStart = 0;
4606  uint32 colStart = 0;
4607  switch (inAxis)
4608  {
4609  case Axis::ROW:
4610  {
4611  rowStart += inOffset;
4612  break;
4613  }
4614  case Axis::COL:
4615  {
4616  colStart += inOffset;
4617  break;
4618  }
4619  default:
4620  {
4621  // if the user input NONE, override back to ROW
4622  inAxis = Axis::ROW;
4623  break;
4624  }
4625  }
4626 
4627  if (rowStart >= shape_.rows || colStart >= shape_.cols)
4628  {
4629  return dtype{ 0 };
4630  }
4631 
4632  uint32 col = colStart;
4633  dtype sum = 0;
4634  for (uint32 row = rowStart; row < shape_.rows; ++row)
4635  {
4636  if (col >= shape_.cols)
4637  {
4638  break;
4639  }
4640  sum += operator()(row, col++);
4641  }
4642 
4643  return sum;
4644  }
4645 
4646  //============================================================================
4647  // Method Description:
4656  {
4657  NdArray<dtype> transArray(shape_.cols, shape_.rows);
4658  for (uint32 row = 0; row < shape_.rows; ++row)
4659  {
4660  for (uint32 col = 0; col < shape_.cols; ++col)
4661  {
4662  transArray(col, row) = operator()(row, col);
4663  }
4664  }
4665  return transArray;
4666  }
4667 
4668  //============================================================================
4669  // Method Description:
4673  NdArray<dtype>& zeros() noexcept
4674  {
4676 
4677  fill(dtype{ 0 });
4678  return *this;
4679  }
4680 
4681  private:
4682  //====================================Attributes==============================
4683  allocator_type allocator_{};
4684  Shape shape_{ 0, 0 };
4685  size_type size_{ 0 };
4686  Endian endianess_{ Endian::NATIVE };
4687  pointer array_{ nullptr };
4688  bool ownsPtr_{ false };
4689 
4690  //============================================================================
4691  // Method Description:
4694  void deleteArray() noexcept
4695  {
4696  if (ownsPtr_ && array_ != nullptr)
4697  {
4698  allocator_.deallocate(array_, size_);
4699  }
4700 
4701  array_ = nullptr;
4702  shape_.rows = shape_.cols = 0;
4703  size_ = 0;
4704  ownsPtr_ = false;
4705  endianess_ = Endian::NATIVE;
4706  }
4707 
4708  //============================================================================
4709  // Method Description:
4712  void newArray()
4713  {
4714  if (size_ > 0)
4715  {
4716  array_ = allocator_.allocate(size_);
4717  ownsPtr_ = true;
4718  }
4719  }
4720 
4721  //============================================================================
4722  // Method Description:
4728  void newArray(const Shape& inShape)
4729  {
4730  deleteArray();
4731 
4732  shape_ = inShape;
4733  size_ = inShape.size();
4734  newArray();
4735  }
4736  };
4737 
4738  // NOTE: this needs to be defined outside of the class to get rid of a compiler
4739  // error in Visual Studio
4740  template<typename dtype, class _Alloc>
4741  std::pair<NdArray<uint32>, NdArray<uint32>> NdArray<dtype, _Alloc>::nonzero() const
4742  {
4744 
4745  std::vector<uint32> rowIndices;
4746  std::vector<uint32> colIndices;
4747 
4748  for (uint32 row = 0; row < shape_.rows; ++row)
4749  {
4750  for (uint32 col = 0; col < shape_.cols; ++col)
4751  {
4752  if (operator()(row, col) != dtype{ 0 })
4753  {
4754  rowIndices.push_back(row);
4755  colIndices.push_back(col);
4756  }
4757  }
4758  }
4759 
4760  return std::make_pair(NdArray<uint32>(rowIndices), NdArray<uint32>(colIndices));
4761  }
4762 } // namespace nc
#define THROW_RUNTIME_ERROR(msg)
Definition: Error.hpp:37
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:36
#define STATIC_ASSERT_FLOAT(dtype)
Definition: StaticAsserts.hpp:43
#define STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype)
Definition: StaticAsserts.hpp:50
#define STATIC_ASSERT_INTEGER(dtype)
Definition: StaticAsserts.hpp:40
#define STATIC_ASSERT_ARITHMETIC(dtype)
Definition: StaticAsserts.hpp:37
Custom column iterator for NdArray.
Definition: NdArrayIterators.hpp:834
Custom column const_iterator for NdArray.
Definition: NdArrayIterators.hpp:503
Custom const_iterator for NdArray.
Definition: NdArrayIterators.hpp:44
Holds 1D and 2D arrays, the main work horse of the NumCpp library.
Definition: NdArrayCore.hpp:72
uint32 numCols() const noexcept
Definition: NdArrayCore.hpp:3478
NdArray(std::vector< std::array< dtype, Dim1Size >> &in2dArray, bool copy=true)
Definition: NdArrayCore.hpp:326
const_reverse_column_iterator rcolbegin() const noexcept
Definition: NdArrayCore.hpp:1378
NdArray< dtypeOut > astype() const
Definition: NdArrayCore.hpp:2101
NdArray< dtype > & put(int32 inIndex, value_type inValue)
Definition: NdArrayCore.hpp:3732
size_type size() const noexcept
Definition: NdArrayCore.hpp:4373
reverse_iterator rbegin() noexcept
Definition: NdArrayCore.hpp:1262
NdArray< dtype > & resizeSlow(uint32 inNumRows, uint32 inNumCols)
Definition: NdArrayCore.hpp:4264
NdArray< dtype > & put(const Slice &inRowSlice, const Slice &inColSlice, value_type inValue)
Definition: NdArrayCore.hpp:3855
NdArray< bool > issorted(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2913
const_iterator cbegin() const noexcept
Definition: NdArrayCore.hpp:1146
const_reference at(int32 inIndex) const
Definition: NdArrayCore.hpp:942
const_column_iterator ccolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1246
NdArrayConstColumnIterator< dtype, size_type, const_pointer, difference_type > const_column_iterator
Definition: NdArrayCore.hpp:96
NdArray< dtype > round(uint8 inNumDecimals=0) const
Definition: NdArrayCore.hpp:4321
NdArray< bool > any(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1839
const_pointer data() const noexcept
Definition: NdArrayCore.hpp:2565
NdArray< dtype > at(const Slice &inRowSlice, int32 inColIndex) const
Definition: NdArrayCore.hpp:1061
iterator end() noexcept
Definition: NdArrayCore.hpp:1434
NdArray< dtype > & put(const Slice &inRowSlice, const Slice &inColSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3933
NdArray(std::vector< dtype > &inVector, bool copy=true)
Definition: NdArrayCore.hpp:266
NdArray(const std::initializer_list< std::initializer_list< dtype > > &inList)
Definition: NdArrayCore.hpp:173
NdArray< dtype > prod(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3620
NdArray< dtype > copy() const
Definition: NdArrayCore.hpp:2417
NdArray< dtype > & resizeFast(const Shape &inShape)
Definition: NdArrayCore.hpp:4247
std::vector< dtype > toStlVector() const
Definition: NdArrayCore.hpp:4584
reference back(size_type row)
Definition: NdArrayCore.hpp:2256
NdArray< dtype > operator()(const Slice &inRowSlice, int32 inColIndex) const
Definition: NdArrayCore.hpp:840
iterator end(size_type inRow)
Definition: NdArrayCore.hpp:1448
NdArray< dtype > flatten() const
Definition: NdArrayCore.hpp:2795
const_column_iterator ccolbegin() const noexcept
Definition: NdArrayCore.hpp:1232
typename AllocTraits::pointer pointer
Definition: NdArrayCore.hpp:83
Slice cSlice(int32 inStartIdx=0, uint32 inStepSize=1) const noexcept
Definition: NdArrayCore.hpp:890
reverse_iterator rbegin(size_type inRow)
Definition: NdArrayCore.hpp:1276
Shape shape() const noexcept
Definition: NdArrayCore.hpp:4359
NdArray< dtype > & byteswap() noexcept
Definition: NdArrayCore.hpp:2270
const_reverse_column_iterator rcolend() const noexcept
Definition: NdArrayCore.hpp:1722
uint32 numRows() const noexcept
Definition: NdArrayCore.hpp:3491
const dtype & const_reference
Definition: NdArrayCore.hpp:86
NdArray< dtype > & put(const Slice &inRowSlice, int32 inColIndex, value_type inValue)
Definition: NdArrayCore.hpp:3885
NdArray< dtype > & partition(uint32 inKth, Axis inAxis=Axis::NONE)
Definition: NdArrayCore.hpp:3536
bool issquare() const noexcept
Definition: NdArrayCore.hpp:2964
NdArrayIterator< dtype, pointer, difference_type > iterator
Definition: NdArrayCore.hpp:90
bool isflat() const noexcept
Definition: NdArrayCore.hpp:2901
Endian endianess() const noexcept
Definition: NdArrayCore.hpp:2736
const_reverse_column_iterator crcolbegin() const noexcept
Definition: NdArrayCore.hpp:1404
const_reverse_column_iterator crcolend(size_type inCol) const
Definition: NdArrayCore.hpp:1762
column_iterator colbegin(size_type inCol)
Definition: NdArrayCore.hpp:1190
NdArrayColumnIterator< dtype, size_type, pointer, difference_type > column_iterator
Definition: NdArrayCore.hpp:95
NdArray< bool > none(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3412
NdArray< dtype > at(const Slice &inSlice) const
Definition: NdArrayCore.hpp:1029
reference at(int32 inIndex)
Definition: NdArrayCore.hpp:919
NdArray< dtype > & sort(Axis inAxis=Axis::NONE)
Definition: NdArrayCore.hpp:4389
pointer data() noexcept
Definition: NdArrayCore.hpp:2555
bool isempty() const noexcept
Definition: NdArrayCore.hpp:2888
column_iterator colbegin() noexcept
Definition: NdArrayCore.hpp:1176
const_reference front(size_type row) const
Definition: NdArrayCore.hpp:2833
reverse_column_iterator rcolend(size_type inCol)
Definition: NdArrayCore.hpp:1706
NdArray< dtype > sum(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:4474
NdArray(Iterator inFirst, Iterator inLast)
Definition: NdArrayCore.hpp:423
NdArray< dtype > operator[](const Slice &inSlice) const
Definition: NdArrayCore.hpp:732
reverse_column_iterator rcolbegin() noexcept
Definition: NdArrayCore.hpp:1348
NdArrayConstIterator< dtype, const_pointer, difference_type > const_iterator
Definition: NdArrayCore.hpp:91
const_iterator cbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1160
const_column_iterator ccolend(size_type inCol) const
Definition: NdArrayCore.hpp:1676
NdArray< dtype > cumsum(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2497
NdArray< dtype > median(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3115
NdArray< dtype > getByMask(const NdArray< bool > &inMask) const
Definition: NdArrayCore.hpp:2875
const_iterator cend(size_type inRow) const
Definition: NdArrayCore.hpp:1504
NdArray< dtype > column(uint32 inColumn)
Definition: NdArrayCore.hpp:2354
const_reverse_column_iterator rcolend(size_type inCol) const
Definition: NdArrayCore.hpp:1736
NdArray< dtype > & putMask(const NdArray< bool > &inMask, value_type inValue)
Definition: NdArrayCore.hpp:4011
const_iterator end(size_type inRow) const
Definition: NdArrayCore.hpp:1478
reference back() noexcept
Definition: NdArrayCore.hpp:2232
const_reverse_column_iterator crcolend() const noexcept
Definition: NdArrayCore.hpp:1748
const_reference back(size_type row) const
Definition: NdArrayCore.hpp:2244
reverse_column_iterator rcolbegin(size_type inCol)
Definition: NdArrayCore.hpp:1362
NdArray(const std::deque< std::deque< dtype >> &in2dDeque)
Definition: NdArrayCore.hpp:370
NdArray< dtype > & put(int32 inRow, int32 inCol, value_type inValue)
Definition: NdArrayCore.hpp:3749
iterator begin(size_type inRow)
Definition: NdArrayCore.hpp:1104
const_reverse_iterator rend() const noexcept
Definition: NdArrayCore.hpp:1550
NdArray< dtype > clip(value_type inMin, value_type inMax) const
Definition: NdArrayCore.hpp:2314
const_reverse_column_iterator rcolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1392
NdArray< dtype > & operator=(NdArray< dtype > &&rhs) noexcept
Definition: NdArrayCore.hpp:617
typename AllocTraits::difference_type difference_type
Definition: NdArrayCore.hpp:88
NdArray< uint32 > argmin(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1956
const_iterator end() const noexcept
Definition: NdArrayCore.hpp:1464
bool ownsInternalData() noexcept
Definition: NdArrayCore.hpp:3515
NdArray< dtype > & fill(value_type inFillValue) noexcept
Definition: NdArrayCore.hpp:2754
column_iterator colend() noexcept
Definition: NdArrayCore.hpp:1606
NdArray< dtype > & put(const NdArray< uint32 > &inIndices, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3784
const_reference back() const noexcept
Definition: NdArrayCore.hpp:2220
std::pair< NdArray< uint32 >, NdArray< uint32 > > nonzero() const
Definition: NdArrayCore.hpp:4741
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: NdArrayCore.hpp:93
NdArray(const_pointer inPtr, UIntType1 numRows, UIntType2 numCols)
Definition: NdArrayCore.hpp:465
NdArray< dtype > cumprod(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2433
uint64 nbytes() const noexcept
Definition: NdArrayCore.hpp:3230
const_reference at(int32 inRowIndex, int32 inColIndex) const
Definition: NdArrayCore.hpp:997
NdArray< dtype > transpose() const
Definition: NdArrayCore.hpp:4655
NdArray< dtype > swapaxes() const
Definition: NdArrayCore.hpp:4524
NdArray< dtype > & put(int32 inRowIndex, const Slice &inColSlice, value_type inValue)
Definition: NdArrayCore.hpp:3909
NdArray(const std::list< dtype > &inList)
Definition: NdArrayCore.hpp:403
NdArray()=default
NdArray< dtype > at(int32 inRowIndex, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:1077
const_reference front() const noexcept
Definition: NdArrayCore.hpp:2809
NdArray< dtype > repeat(const Shape &inRepeatShape) const
Definition: NdArrayCore.hpp:4106
~NdArray() noexcept
Definition: NdArrayCore.hpp:558
NdArray< dtype > min(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3056
NdArray(pointer inPtr, uint32 numRows, uint32 numCols, Bool takeOwnership) noexcept
Definition: NdArrayCore.hpp:508
NdArray< dtype > & reshape(const Shape &inShape)
Definition: NdArrayCore.hpp:4216
reference front() noexcept
Definition: NdArrayCore.hpp:2821
NdArray(size_type inNumRows, size_type inNumCols)
Definition: NdArrayCore.hpp:127
Allocator allocator_type
Definition: NdArrayCore.hpp:82
void print() const
Definition: NdArrayCore.hpp:3602
const_reverse_column_iterator crcolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1418
reverse_iterator rend(size_type inRow)
Definition: NdArrayCore.hpp:1534
NdArray< uint32 > flatnonzero() const
Definition: NdArrayCore.hpp:2768
NdArray(size_type inSquareSize)
Definition: NdArrayCore.hpp:113
reverse_iterator rend() noexcept
Definition: NdArrayCore.hpp:1520
const_reverse_iterator rend(size_type inRow) const
Definition: NdArrayCore.hpp:1564
NdArray< dtype > getByIndices(const NdArray< uint32 > &inIndices) const
Definition: NdArrayCore.hpp:2859
typename AllocTraits::const_pointer const_pointer
Definition: NdArrayCore.hpp:84
NdArray< dtype > & resizeSlow(const Shape &inShape)
Definition: NdArrayCore.hpp:4304
const_reverse_iterator crbegin() const noexcept
Definition: NdArrayCore.hpp:1318
const_column_iterator colend(size_type inCol) const
Definition: NdArrayCore.hpp:1650
std::reverse_iterator< iterator > reverse_iterator
Definition: NdArrayCore.hpp:92
NdArray(const std::initializer_list< dtype > &inList)
Definition: NdArrayCore.hpp:155
NdArray(const std::vector< std::vector< dtype >> &in2dVector)
Definition: NdArrayCore.hpp:291
const_reverse_iterator rbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1306
const_iterator cend() const noexcept
Definition: NdArrayCore.hpp:1490
std::string str() const
Definition: NdArrayCore.hpp:4436
std::reverse_iterator< const_column_iterator > const_reverse_column_iterator
Definition: NdArrayCore.hpp:98
reference operator[](int32 inIndex) noexcept
Definition: NdArrayCore.hpp:645
NdArray< dtype > & reshape(int32 inNumRows, int32 inNumCols)
Definition: NdArrayCore.hpp:4163
NdArray(NdArray< dtype > &&inOtherArray) noexcept
Definition: NdArrayCore.hpp:541
NdArray< dtype > & nans() noexcept
Definition: NdArrayCore.hpp:3213
NdArray< dtype > & put(const NdArray< uint32 > &inIndices, value_type inValue)
Definition: NdArrayCore.hpp:3765
NdArray< dtype > ptp(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3675
const_reference operator()(int32 inRowIndex, int32 inColIndex) const noexcept
Definition: NdArrayCore.hpp:707
reference front(size_type row)
Definition: NdArrayCore.hpp:2845
NdArray< dtype > diagonal(int32 inOffset=0, Axis inAxis=Axis::ROW) const
Definition: NdArrayCore.hpp:2594
NdArray< dtype > & putMask(const NdArray< bool > &inMask, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:4028
NdArray< dtype > operator[](const NdArray< bool > &inMask) const
Definition: NdArrayCore.hpp:755
NdArray< dtype > row(uint32 inRow)
Definition: NdArrayCore.hpp:4345
const_iterator begin(size_type inRow) const
Definition: NdArrayCore.hpp:1134
iterator begin() noexcept
Definition: NdArrayCore.hpp:1090
NdArray< dtype > & put(const Slice &inSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3831
NdArray< dtype > operator()(const Slice &inRowSlice, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:808
const_column_iterator colbegin() const noexcept
Definition: NdArrayCore.hpp:1206
NdArray< dtype > max(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2999
std::reverse_iterator< column_iterator > reverse_column_iterator
Definition: NdArrayCore.hpp:97
NdArray< dtype > & operator=(const NdArray< dtype > &rhs)
Definition: NdArrayCore.hpp:572
value_type item() const
Definition: NdArrayCore.hpp:2978
reference operator()(int32 inRowIndex, int32 inColIndex) noexcept
Definition: NdArrayCore.hpp:683
const_column_iterator colend() const noexcept
Definition: NdArrayCore.hpp:1636
NdArray< dtype > & resizeFast(uint32 inNumRows, uint32 inNumCols)
Definition: NdArrayCore.hpp:4231
const_reverse_iterator crend() const noexcept
Definition: NdArrayCore.hpp:1576
NdArray< dtype > & ones() noexcept
Definition: NdArrayCore.hpp:3501
NdArray< dtype > & zeros() noexcept
Definition: NdArrayCore.hpp:4673
const_column_iterator colbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1220
NdArray< dtype > dot(const NdArray< dtype > &inOtherArray) const
Definition: NdArrayCore.hpp:2664
NdArray< dtype > repeat(uint32 inNumRows, uint32 inNumCols) const
Definition: NdArrayCore.hpp:4063
NdArray< dtype > & reshape(size_type inSize)
Definition: NdArrayCore.hpp:4136
NdArray< bool > contains(value_type inValue, Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2368
const_column_iterator ccolend() const noexcept
Definition: NdArrayCore.hpp:1662
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:4601
reverse_column_iterator rcolend() noexcept
Definition: NdArrayCore.hpp:1692
NdArray(std::array< dtype, ArraySize > &inArray, bool copy=true)
Definition: NdArrayCore.hpp:209
NdArray< dtype > & put(int32 inRowIndex, const Slice &inColSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3989
const_reverse_iterator rbegin() const noexcept
Definition: NdArrayCore.hpp:1292
NdArray< dtype > operator()(int32 inRowIndex, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:865
NdArray(const_pointer inPtr, size_type size)
Definition: NdArrayCore.hpp:442
NdArray(const std::deque< dtype > &inDeque)
Definition: NdArrayCore.hpp:353
NdArray(std::array< std::array< dtype, Dim1Size >, Dim0Size > &in2dArray, bool copy=true)
Definition: NdArrayCore.hpp:237
void dump(const std::string &inFilename) const
Definition: NdArrayCore.hpp:2708
dtype & reference
Definition: NdArrayCore.hpp:85
pointer dataRelease() noexcept
Definition: NdArrayCore.hpp:2577
reference at(int32 inRowIndex, int32 inColIndex)
Definition: NdArrayCore.hpp:965
NdArray< dtype > at(const Slice &inRowSlice, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:1045
NdArray(const NdArray< dtype > &inOtherArray)
Definition: NdArrayCore.hpp:522
NdArray< uint32 > argsort(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2015
NdArray< dtype > operator[](const NdArray< size_type > &inIndices) const
Definition: NdArrayCore.hpp:781
uint32 size_type
Definition: NdArrayCore.hpp:87
const_iterator begin() const noexcept
Definition: NdArrayCore.hpp:1120
NdArray< dtype > & operator=(value_type inValue) noexcept
Definition: NdArrayCore.hpp:598
NdArray< dtype > newbyteorder(Endian inEndianess) const
Definition: NdArrayCore.hpp:3247
column_iterator colend(size_type inCol)
Definition: NdArrayCore.hpp:1620
NdArray< dtype > & put(const Slice &inSlice, value_type inValue)
Definition: NdArrayCore.hpp:3809
void tofile(const std::string &inFilename, const std::string &inSep="") const
Definition: NdArrayCore.hpp:4542
const_reference operator[](int32 inIndex) const noexcept
Definition: NdArrayCore.hpp:664
NdArray< dtype > & ravel() noexcept
Definition: NdArrayCore.hpp:4046
dtype value_type
Definition: NdArrayCore.hpp:81
NdArray(pointer inPtr, size_type size, Bool takeOwnership) noexcept
Definition: NdArrayCore.hpp:488
void replace(value_type oldValue, value_type newValue)
Definition: NdArrayCore.hpp:4118
NdArray< dtype > & put(const Slice &inRowSlice, int32 inColIndex, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3964
Slice rSlice(int32 inStartIdx=0, uint32 inStepSize=1) const noexcept
Definition: NdArrayCore.hpp:905
const_reverse_iterator crend(size_type inRow) const
Definition: NdArrayCore.hpp:1590
const_reverse_iterator crbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1332
NdArray(const Shape &inShape)
Definition: NdArrayCore.hpp:141
NdArray< bool > all(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1783
Custom iterator for NdArray.
Definition: NdArrayIterators.hpp:324
A Shape Class for NdArrays.
Definition: Core/Shape.hpp:41
uint32 rows
Definition: Core/Shape.hpp:44
uint32 cols
Definition: Core/Shape.hpp:45
uint32 size() const noexcept
Definition: Core/Shape.hpp:102
A Class for slicing into NdArrays.
Definition: Slice.hpp:44
int32 step
Definition: Slice.hpp:49
int32 start
Definition: Slice.hpp:47
void makePositiveAndValidate(uint32 inArraySize)
Definition: Slice.hpp:137
uint32 numElements(uint32 inArraySize)
Definition: Slice.hpp:188
int32 stop
Definition: Slice.hpp:48
Provides simple filesystem functions.
Definition: Filesystem.hpp:40
constexpr auto j
Definition: Constants.hpp:45
const double nan
NaN.
Definition: Constants.hpp:44
bool isLittleEndian() noexcept
Definition: Endian.hpp:44
dtype byteSwap(dtype value) noexcept
Definition: Endian.hpp:63
dtype f(dtype inDofN, dtype inDofD)
Definition: f.hpp:56
bool any_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:76
void sort(RandomIt first, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:629
bool none_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:379
ForwardIt max_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:268
void stable_sort(RandomIt first, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:664
OutputIt transform(InputIt first, InputIt last, OutputIt destination, UnaryOperation unaryFunction)
Definition: StlAlgorithms.hpp:702
bool all_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:57
void for_each(InputIt first, InputIt last, UnaryFunction f)
Definition: StlAlgorithms.hpp:213
InputIt find(InputIt first, InputIt last, const T &value) noexcept
Definition: StlAlgorithms.hpp:195
std::pair< ForwardIt, ForwardIt > minmax_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:341
void replace(ForwardIt first, ForwardIt last, const T &oldValue, const T &newValue) noexcept
Definition: StlAlgorithms.hpp:435
bool is_sorted(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:231
OutputIt copy(InputIt first, InputIt last, OutputIt destination) noexcept
Definition: StlAlgorithms.hpp:95
void nth_element(RandomIt first, RandomIt nth, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:397
ForwardIt min_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:304
void fill(ForwardIt first, ForwardIt last, const T &value) noexcept
Definition: StlAlgorithms.hpp:174
std::string num2str(dtype inNumber)
Definition: num2str.hpp:46
dtype power(dtype inValue, uint8 inPower) noexcept
Definition: Utils/power.hpp:48
std::string value2str(dtype inValue)
Definition: value2str.hpp:48
Definition: Coordinate.hpp:45
NdArray< dtype > repeat(const NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition: repeat.hpp:50
std::pair< NdArray< uint32 >, NdArray< uint32 > > nonzero(const NdArray< dtype > &inArray)
Definition: nonzero.hpp:50
NdArray< dtype > & resizeFast(NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition: resizeFast.hpp:51
Axis
Enum To describe an axis.
Definition: Types.hpp:46
NdArray< dtype > & reshape(NdArray< dtype > &inArray, uint32 inSize)
Definition: reshape.hpp:52
std::int64_t int64
Definition: Types.hpp:35
auto abs(dtype inValue) noexcept
Definition: abs.hpp:51
std::uint64_t uint64
Definition: Types.hpp:39
NdArray< dtype > & resizeSlow(NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition: resizeSlow.hpp:53
Endian
Enum for endianess.
Definition: Types.hpp:50
std::int32_t int32
Definition: Types.hpp:36
std::uint8_t uint8
Definition: Types.hpp:42
NdArray< dtype > sum(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition: sum.hpp:47
NdArray< dtype > & put(NdArray< dtype > &inArray, const NdArray< uint32 > &inIndices, dtype inValue)
Definition: put.hpp:49
NdArray< dtype > transpose(const NdArray< dtype > &inArray)
Definition: transpose.hpp:47
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:47