NumCpp  2.4.0
A Templatized Header Only C++ Implementation of the Python NumPy Library
NdArrayCore.hpp
Go to the documentation of this file.
1 #pragma once
29 
39 #include "NumCpp/Core/Shape.hpp"
40 #include "NumCpp/Core/Slice.hpp"
41 #include "NumCpp/Core/Types.hpp"
43 #include "NumCpp/Utils/num2str.hpp"
44 #include "NumCpp/Utils/power.hpp"
45 #include "NumCpp/Utils/sqr.hpp"
47 
48 #include <array>
49 #include <cmath>
50 #include <deque>
51 #include <forward_list>
52 #include <fstream>
53 #include <initializer_list>
54 #include <iostream>
55 #include <iterator>
56 #include <list>
57 #include <memory>
58 #include <numeric>
59 #include <set>
60 #include <string>
61 #include <type_traits>
62 #include <utility>
63 #include <vector>
64 
65 namespace nc
66 {
67  //================================================================================
68  // Class Description:
70  template<typename dtype, class Allocator = std::allocator<dtype>>
71  class NdArray
72  {
73  private:
74  STATIC_ASSERT_VALID_DTYPE(dtype);
75  static_assert(is_same_v<dtype, typename Allocator::value_type>, "value_type and Allocator::value_type must match");
76 
77  using AllocType = typename std::allocator_traits<Allocator>::template rebind_alloc<dtype>;
78  using AllocTraits = std::allocator_traits<AllocType>;
79 
80  public:
81  using value_type = dtype;
82  using allocator_type = Allocator;
83  using pointer = typename AllocTraits::pointer;
84  using const_pointer = typename AllocTraits::const_pointer;
85  using reference = dtype&;
86  using const_reference = const dtype&;
87  using size_type = uint32;
88  using difference_type = typename AllocTraits::difference_type;
89 
92  using reverse_iterator = std::reverse_iterator<iterator>;
93  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
94 
97  using reverse_column_iterator = std::reverse_iterator<column_iterator>;
98  using const_reverse_column_iterator = std::reverse_iterator<const_column_iterator>;
99 
100  //============================================================================
101  // Method Description:
104  NdArray() = default;
105 
106  //============================================================================
107  // Method Description:
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:
463  shape_(numRows, numCols),
464  size_(shape_.size())
465  {
466  newArray();
467  if (inPtr != nullptr && size_ > 0)
468  {
469  stl_algorithms::copy(inPtr, inPtr + size_, begin());
470  }
471  }
472 
473  //============================================================================
474  // Method Description:
483  template<typename Bool,
484  std::enable_if_t<std::is_same<Bool, bool>::value, int> = 0>
485  NdArray(pointer inPtr, size_type size, Bool takeOwnership) noexcept :
486  shape_(1, size),
487  size_(size),
488  array_(inPtr),
489  ownsPtr_(takeOwnership)
490  {}
491 
492  //============================================================================
493  // Method Description:
503  template<typename Bool,
504  std::enable_if_t<std::is_same<Bool, bool>::value, int> = 0>
505  NdArray(pointer inPtr, uint32 numRows, uint32 numCols, Bool takeOwnership) noexcept :
506  shape_(numRows, numCols),
507  size_(numRows * numCols),
508  array_(inPtr),
509  ownsPtr_(takeOwnership)
510  {}
511 
512  //============================================================================
513  // Method Description:
519  NdArray(const NdArray<dtype>& inOtherArray) :
520  shape_(inOtherArray.shape_),
521  size_(inOtherArray.size_),
522  endianess_(inOtherArray.endianess_)
523  {
524  newArray();
525  if (size_ > 0)
526  {
527  stl_algorithms::copy(inOtherArray.cbegin(), inOtherArray.cend(), begin());
528  }
529  }
530 
531  //============================================================================
532  // Method Description:
538  NdArray(NdArray<dtype>&& inOtherArray) noexcept :
539  shape_(inOtherArray.shape_),
540  size_(inOtherArray.size_),
541  endianess_(inOtherArray.endianess_),
542  array_(inOtherArray.array_),
543  ownsPtr_(inOtherArray.ownsPtr_)
544  {
545  inOtherArray.shape_.rows = inOtherArray.shape_.cols = 0;
546  inOtherArray.size_ = 0;
547  inOtherArray.ownsPtr_ = false;
548  inOtherArray.array_ = nullptr;
549  }
550 
551  //============================================================================
552  // Method Description:
555  ~NdArray() noexcept
556  {
557  deleteArray();
558  }
559 
560  //============================================================================
561  // Method Description:
570  {
571  if (&rhs != this)
572  {
573  if (rhs.size_ > 0)
574  {
575  newArray(rhs.shape_);
576  endianess_ = rhs.endianess_;
577 
578  stl_algorithms::copy(rhs.cbegin(), rhs.cend(), begin());
579  }
580  }
581 
582  return *this;
583  }
584 
585  //============================================================================
586  // Method Description:
596  {
597  if (array_ != nullptr)
598  {
599  stl_algorithms::fill(begin(), end(), inValue);
600  }
601 
602  return *this;
603  }
604 
605  //============================================================================
606  // Method Description:
615  {
616  if (&rhs != this)
617  {
618  deleteArray();
619  shape_ = rhs.shape_;
620  size_ = rhs.size_;
621  endianess_ = rhs.endianess_;
622  array_ = rhs.array_;
623  ownsPtr_ = rhs.ownsPtr_;
624 
625  rhs.shape_.rows = rhs.shape_.cols = rhs.size_ = 0;
626  rhs.array_ = nullptr;
627  rhs.ownsPtr_ = false;
628  }
629 
630  return *this;
631  }
632 
633  //============================================================================
634  // Method Description:
642  reference operator[](int32 inIndex) noexcept
643  {
644  if (inIndex < 0)
645  {
646  inIndex += size_;
647  }
648 
649  return array_[inIndex];
650  }
651 
652  //============================================================================
653  // Method Description:
661  const_reference operator[](int32 inIndex) const noexcept
662  {
663  if (inIndex < 0)
664  {
665  inIndex += size_;
666  }
667 
668  return array_[inIndex];
669  }
670 
671  //============================================================================
672  // Method Description:
680  reference operator()(int32 inRowIndex, int32 inColIndex) noexcept
681  {
682  if (inRowIndex < 0)
683  {
684  inRowIndex += shape_.rows;
685  }
686 
687  if (inColIndex < 0)
688  {
689  inColIndex += shape_.cols;
690  }
691 
692  return array_[inRowIndex * shape_.cols + inColIndex];
693  }
694 
695  //============================================================================
696  // Method Description:
704  const_reference operator()(int32 inRowIndex, int32 inColIndex) const noexcept
705  {
706  if (inRowIndex < 0)
707  {
708  inRowIndex += shape_.rows;
709  }
710 
711  if (inColIndex < 0)
712  {
713  inColIndex += shape_.cols;
714  }
715 
716  return array_[inRowIndex * shape_.cols + inColIndex];
717  }
718 
719  //============================================================================
720  // Method Description:
729  NdArray<dtype> operator[](const Slice& inSlice) const
730  {
731  Slice inSliceCopy(inSlice);
732 
733  uint32 counter = 0;
734  NdArray<dtype> returnArray(1, inSliceCopy.numElements(size_));
735  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
736  {
737  returnArray[counter++] = at(i);
738  }
739 
740  return returnArray;
741  }
742 
743  //============================================================================
744  // Method Description:
753  {
754  if (inMask.shape() != shape_)
755  {
756  THROW_INVALID_ARGUMENT_ERROR("input inMask must have the same shape as the NdArray it will be masking.");
757  }
758 
759  auto indices = inMask.flatnonzero();
760  auto outArray = NdArray<dtype>(1, indices.size());
761  for (size_type i = 0; i < indices.size(); ++i)
762  {
763  outArray[i] = operator[](indices[i]);
764  }
765 
766  return outArray;
767  }
768 
769  //============================================================================
770  // Method Description:
779  {
780  if (inIndices.max().item() > size_ - 1)
781  {
782  THROW_INVALID_ARGUMENT_ERROR("input indices must be less than the array size.");
783  }
784 
785  auto outArray = NdArray<dtype>(1, static_cast<size_type>(inIndices.size()));
786  size_type i = 0;
787  for (auto& index : inIndices)
788  {
789  outArray[i++] = operator[](index);
790  }
791 
792  return outArray;
793  }
794 
795  //============================================================================
796  // Method Description:
805  NdArray<dtype> operator()(const Slice& inRowSlice, const Slice& inColSlice) const
806  {
807  Slice inRowSliceCopy(inRowSlice);
808  Slice inColSliceCopy(inColSlice);
809 
810  NdArray<dtype> returnArray(inRowSliceCopy.numElements(shape_.rows), inColSliceCopy.numElements(shape_.cols));
811 
812  uint32 rowCounter = 0;
813  uint32 colCounter = 0;
814  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
815  {
816  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
817  {
818  returnArray(rowCounter, colCounter++) = at(row, col);
819  }
820  colCounter = 0;
821  ++rowCounter;
822  }
823 
824  return returnArray;
825  }
826 
827  //============================================================================
828  // Method Description:
837  NdArray<dtype> operator()(const Slice& inRowSlice, int32 inColIndex) const
838  {
839  Slice inRowSliceCopy(inRowSlice);
840 
841  NdArray<dtype> returnArray(inRowSliceCopy.numElements(shape_.rows), 1);
842 
843  uint32 rowCounter = 0;
844  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
845  {
846  returnArray(rowCounter++, 0) = at(row, inColIndex);
847  }
848 
849  return returnArray;
850  }
851 
852  //============================================================================
853  // Method Description:
862  NdArray<dtype> operator()(int32 inRowIndex, const Slice& inColSlice) const
863  {
864  Slice inColSliceCopy(inColSlice);
865 
866  NdArray<dtype> returnArray(1, inColSliceCopy.numElements(shape_.cols));
867 
868  uint32 colCounter = 0;
869  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
870  {
871  returnArray(0, colCounter++) = at(inRowIndex, col);
872  }
873 
874  return returnArray;
875  }
876 
877  //============================================================================
878  // Method Description:
887  Slice cSlice(int32 inStartIdx = 0, uint32 inStepSize = 1) const noexcept
888  {
889  return Slice(inStartIdx, shape_.cols, inStepSize);
890  }
891 
892  //============================================================================
893  // Method Description:
902  Slice rSlice(int32 inStartIdx = 0, uint32 inStepSize = 1) const noexcept
903  {
904  return Slice(inStartIdx, shape_.rows, inStepSize);
905  }
906 
907  //============================================================================
908  // Method Description:
916  reference at(int32 inIndex)
917  {
918  // this doesn't allow for calling the first element as -size_...
919  // but why would you really want to do that anyway?
920  if (std::abs(inIndex) > static_cast<int64>(size_ - 1))
921  {
922  std::string errStr = "Input index " + utils::num2str(inIndex);
923  errStr += " is out of bounds for array of size " + utils::num2str(size_) + ".";
925  }
926 
927  return operator[](inIndex);
928  }
929 
930  //============================================================================
931  // Method Description:
939  const_reference at(int32 inIndex) const
940  {
941  // this doesn't allow for calling the first element as -size_...
942  // but why would you really want to do that anyway?
943  if (std::abs(inIndex) > static_cast<int64>(size_ - 1))
944  {
945  std::string errStr = "Input index " + utils::num2str(inIndex);
946  errStr += " is out of bounds for array of size " + utils::num2str(size_) + ".";
948  }
949 
950  return operator[](inIndex);
951  }
952 
953  //============================================================================
954  // Method Description:
962  reference at(int32 inRowIndex, int32 inColIndex)
963  {
964  // this doesn't allow for calling the first element as -size_...
965  // but why would you really want to do that anyway?
966  if (std::abs(inRowIndex) > static_cast<int32>(shape_.rows - 1))
967  {
968  std::string errStr = "Row index " + utils::num2str(inRowIndex);
969  errStr += " is out of bounds for array of size " + utils::num2str(shape_.rows) + ".";
971  }
972 
973  // this doesn't allow for calling the first element as -size_...
974  // but why would you really want to that anyway?
975  if (std::abs(inColIndex) > static_cast<int32>(shape_.cols - 1))
976  {
977  std::string errStr = "Column index " + utils::num2str(inColIndex);
978  errStr += " is out of bounds for array of size " + utils::num2str(shape_.cols) + ".";
980  }
981 
982  return operator()(inRowIndex, inColIndex);
983  }
984 
985  //============================================================================
986  // Method Description:
994  const_reference at(int32 inRowIndex, int32 inColIndex) const
995  {
996  // this doesn't allow for calling the first element as -size_...
997  // but why would you really want to do that anyway?
998  if (std::abs(inRowIndex) > static_cast<int32>(shape_.rows - 1))
999  {
1000  std::string errStr = "Row index " + utils::num2str(inRowIndex);
1001  errStr += " is out of bounds for array of size " + utils::num2str(shape_.rows) + ".";
1003  }
1004 
1005  // this doesn't allow for calling the first element as -size_...
1006  // but why would you really want to do that anyway?
1007  if (std::abs(inColIndex) > static_cast<int32>(shape_.cols - 1))
1008  {
1009  std::string errStr = "Column index " + utils::num2str(inColIndex);
1010  errStr += " is out of bounds for array of size " + utils::num2str(shape_.cols) + ".";
1012  }
1013 
1014  return operator()(inRowIndex, inColIndex);
1015  }
1016 
1017  //============================================================================
1018  // Method Description:
1026  NdArray<dtype> at(const Slice& inSlice) const
1027  {
1028  // the slice operator already provides bounds checking. just including
1029  // the at method for completeness
1030  return operator[](inSlice);
1031  }
1032 
1033  //============================================================================
1034  // Method Description:
1042  NdArray<dtype> at(const Slice& inRowSlice, const Slice& inColSlice) const
1043  {
1044  // the slice operator already provides bounds checking. just including
1045  // the at method for completeness
1046  return operator()(inRowSlice, inColSlice);
1047  }
1048 
1049  //============================================================================
1050  // Method Description:
1058  NdArray<dtype> at(const Slice& inRowSlice, int32 inColIndex) const
1059  {
1060  // the slice operator already provides bounds checking. just including
1061  // the at method for completeness
1062  return operator()(inRowSlice, inColIndex);
1063  }
1064 
1065  //============================================================================
1066  // Method Description:
1074  NdArray<dtype> at(int32 inRowIndex, const Slice& inColSlice) const
1075  {
1076  // the slice operator already provides bounds checking. just including
1077  // the at method for completeness
1078  return operator()(inRowIndex, inColSlice);
1079  }
1080 
1081  //============================================================================
1082  // Method Description:
1087  iterator begin() noexcept
1088  {
1089  return iterator(array_);
1090  }
1091 
1092  //============================================================================
1093  // Method Description:
1102  {
1103  if (inRow >= shape_.rows)
1104  {
1105  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1106  }
1107 
1108  return begin() += (inRow * shape_.cols);
1109  }
1110 
1111  //============================================================================
1112  // Method Description:
1117  const_iterator begin() const noexcept
1118  {
1119  return cbegin();
1120  }
1121 
1122  //============================================================================
1123  // Method Description:
1132  {
1133  return cbegin(inRow);
1134  }
1135 
1136  //============================================================================
1137  // Method Description:
1143  const_iterator cbegin() const noexcept
1144  {
1145  return const_iterator(array_);
1146  }
1147 
1148  //============================================================================
1149  // Method Description:
1158  {
1159  if (inRow >= shape_.rows)
1160  {
1161  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1162  }
1163 
1164  return cbegin() += (inRow * shape_.cols);
1165  }
1166 
1167  //============================================================================
1168  // Method Description:
1174  {
1175  return column_iterator(array_, shape_.rows, shape_.cols);
1176  }
1177 
1178  //============================================================================
1179  // Method Description:
1188  {
1189  if (inCol >= shape_.cols)
1190  {
1191  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1192  }
1193 
1194  return colbegin() += (inCol * shape_.rows);
1195  }
1196 
1197  //============================================================================
1198  // Method Description:
1204  {
1205  return ccolbegin();
1206  }
1207 
1208  //============================================================================
1209  // Method Description:
1218  {
1219  return ccolbegin(inCol);
1220  }
1221 
1222  //============================================================================
1223  // Method Description:
1230  {
1231  return const_column_iterator(array_, shape_.rows, shape_.cols);
1232  }
1233 
1234  //============================================================================
1235  // Method Description:
1244  {
1245  if (inCol >= shape_.cols)
1246  {
1247  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1248  }
1249 
1250  return ccolbegin() += (inCol * shape_.rows);
1251  }
1252 
1253  //============================================================================
1254  // Method Description:
1260  {
1261  return reverse_iterator(end());
1262  }
1263 
1264  //============================================================================
1265  // Method Description:
1274  {
1275  if (inRow >= shape_.rows)
1276  {
1277  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1278  }
1279 
1280  return rbegin() += (shape_.rows - inRow - 1) * shape_.cols;
1281  }
1282 
1283  //============================================================================
1284  // Method Description:
1290  {
1291  return crbegin();
1292  }
1293 
1294  //============================================================================
1295  // Method Description:
1304  {
1305  return crbegin(inRow);
1306  }
1307 
1308  //============================================================================
1309  // Method Description:
1316  {
1317  return const_reverse_iterator(cend());
1318  }
1319 
1320  //============================================================================
1321  // Method Description:
1330  {
1331  if (inRow >= shape_.rows)
1332  {
1333  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1334  }
1335 
1336  return crbegin() += (shape_.rows - inRow - 1) * shape_.cols;
1337  }
1338 
1339  //============================================================================
1340  // Method Description:
1346  {
1347  return reverse_column_iterator(colend());
1348  }
1349 
1350  //============================================================================
1351  // Method Description:
1360  {
1361  if (inCol >= shape_.cols)
1362  {
1363  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1364  }
1365 
1366  return rcolbegin() += (shape_.cols - inCol - 1) * shape_.rows;
1367  }
1368 
1369  //============================================================================
1370  // Method Description:
1376  {
1377  return crcolbegin();
1378  }
1379 
1380  //============================================================================
1381  // Method Description:
1390  {
1391  return crcolbegin(inCol);
1392  }
1393 
1394  //============================================================================
1395  // Method Description:
1402  {
1404  }
1405 
1406  //============================================================================
1407  // Method Description:
1416  {
1417  if (inCol >= shape_.cols)
1418  {
1419  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1420  }
1421 
1422  return crcolbegin() += (shape_.cols - inCol - 1) * shape_.rows;
1423  }
1424 
1425  //============================================================================
1426  // Method Description:
1431  iterator end() noexcept
1432  {
1433  return begin() += size_;
1434  }
1435 
1436  //============================================================================
1437  // Method Description:
1446  {
1447  if (inRow >= shape_.rows)
1448  {
1449  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1450  }
1451 
1452  return begin(inRow) += shape_.cols;
1453  }
1454 
1455  //============================================================================
1456  // Method Description:
1461  const_iterator end() const noexcept
1462  {
1463  return cend();
1464  }
1465 
1466  //============================================================================
1467  // Method Description:
1476  {
1477  return cend(inRow);
1478  }
1479 
1480  //============================================================================
1481  // Method Description:
1487  const_iterator cend() const noexcept
1488  {
1489  return cbegin() += size_;
1490  }
1491 
1492  //============================================================================
1493  // Method Description:
1502  {
1503  if (inRow >= shape_.rows)
1504  {
1505  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1506  }
1507 
1508  return cbegin(inRow) += shape_.cols;
1509  }
1510 
1511  //============================================================================
1512  // Method Description:
1518  {
1519  return rbegin() += size_;
1520  }
1521 
1522  //============================================================================
1523  // Method Description:
1532  {
1533  if (inRow >= shape_.rows)
1534  {
1535  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1536  }
1537 
1538  return rbegin(inRow) += shape_.cols;
1539  }
1540 
1541  //============================================================================
1542  // Method Description:
1547  const_reverse_iterator rend() const noexcept
1548  {
1549  return crend();
1550  }
1551 
1552  //============================================================================
1553  // Method Description:
1562  {
1563  return crend(inRow);
1564  }
1565 
1566  //============================================================================
1567  // Method Description:
1574  {
1575  return crbegin() += size_;
1576  }
1577 
1578  //============================================================================
1579  // Method Description:
1588  {
1589  if (inRow >= shape_.rows)
1590  {
1591  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1592  }
1593 
1594  return crbegin(inRow) += shape_.cols;
1595  }
1596 
1597  //============================================================================
1598  // Method Description:
1604  {
1605  return colbegin() += size_;
1606  }
1607 
1608  //============================================================================
1609  // Method Description:
1618  {
1619  if (inCol >= shape_.cols)
1620  {
1621  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1622  }
1623 
1624  return colbegin(inCol) += shape_.rows;
1625  }
1626 
1627  //============================================================================
1628  // Method Description:
1633  const_column_iterator colend() const noexcept
1634  {
1635  return ccolend();
1636  }
1637 
1638  //============================================================================
1639  // Method Description:
1648  {
1649  return ccolend(inCol);
1650  }
1651 
1652  //============================================================================
1653  // Method Description:
1659  const_column_iterator ccolend() const noexcept
1660  {
1661  return ccolbegin() += size_;
1662  }
1663 
1664  //============================================================================
1665  // Method Description:
1674  {
1675  if (inCol >= shape_.cols)
1676  {
1677  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1678  }
1679 
1680  return ccolbegin(inCol) += shape_.rows;
1681  }
1682 
1683  //============================================================================
1684  // Method Description:
1690  {
1691  return rcolbegin() += size_;
1692  }
1693 
1694  //============================================================================
1695  // Method Description:
1704  {
1705  if (inCol >= shape_.cols)
1706  {
1707  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1708  }
1709 
1710  return rcolbegin(inCol) += shape_.rows;
1711  }
1712 
1713  //============================================================================
1714  // Method Description:
1720  {
1721  return crcolend();
1722  }
1723 
1724  //============================================================================
1725  // Method Description:
1734  {
1735  return crcolend(inCol);
1736  }
1737 
1738  //============================================================================
1739  // Method Description:
1746  {
1747  return crcolbegin() += size_;
1748  }
1749 
1750  //============================================================================
1751  // Method Description:
1760  {
1761  if (inCol >= shape_.cols)
1762  {
1763  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1764  }
1765 
1766  return crcolbegin(inCol) += shape_.rows;
1767  }
1768 
1769  //============================================================================
1770  // Method Description:
1781  {
1783 
1784  const auto function = [](dtype i) -> bool
1785  {
1786  return i != dtype{ 0 };
1787  };
1788 
1789  switch (inAxis)
1790  {
1791  case Axis::NONE:
1792  {
1793  NdArray<bool> returnArray = { stl_algorithms::all_of(cbegin(), cend(), function) };
1794  return returnArray;
1795  }
1796  case Axis::COL:
1797  {
1798  NdArray<bool> returnArray(1, shape_.rows);
1799  for (uint32 row = 0; row < shape_.rows; ++row)
1800  {
1801  returnArray(0, row) = stl_algorithms::all_of(cbegin(row), cend(row), function);
1802  }
1803 
1804  return returnArray;
1805  }
1806  case Axis::ROW:
1807  {
1808  NdArray<dtype> arrayTransposed = transpose();
1809  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
1810  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1811  {
1812  returnArray(0, row) = stl_algorithms::all_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
1813  }
1814 
1815  return returnArray;
1816  }
1817  default:
1818  {
1819  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1820  return {}; // get rid of compiler warning
1821  }
1822  }
1823  }
1824 
1825  //============================================================================
1826  // Method Description:
1837  {
1839 
1840  const auto function = [](dtype i) -> bool
1841  {
1842  return i != dtype{ 0 };
1843  };
1844 
1845  switch (inAxis)
1846  {
1847  case Axis::NONE:
1848  {
1849  NdArray<bool> returnArray = { stl_algorithms::any_of(cbegin(), cend(), function) };
1850  return returnArray;
1851  }
1852  case Axis::COL:
1853  {
1854  NdArray<bool> returnArray(1, shape_.rows);
1855  for (uint32 row = 0; row < shape_.rows; ++row)
1856  {
1857  returnArray(0, row) = stl_algorithms::any_of(cbegin(row), cend(row), function);
1858  }
1859 
1860  return returnArray;
1861  }
1862  case Axis::ROW:
1863  {
1864  NdArray<dtype> arrayTransposed = transpose();
1865  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
1866  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1867  {
1868  returnArray(0, row) = stl_algorithms::any_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
1869  }
1870 
1871  return returnArray;
1872  }
1873  default:
1874  {
1875  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1876  return {}; // get rid of compiler warning
1877  }
1878  }
1879  }
1880 
1881  //============================================================================
1882  // Method Description:
1894  {
1896 
1897  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
1898  {
1899  return lhs < rhs;
1900  };
1901 
1902  switch (inAxis)
1903  {
1904  case Axis::NONE:
1905  {
1906  NdArray<uint32> returnArray = { static_cast<uint32>(stl_algorithms::max_element(cbegin(),
1907  cend(), comparitor) - cbegin()) };
1908  return returnArray;
1909  }
1910  case Axis::COL:
1911  {
1912  NdArray<uint32> returnArray(1, shape_.rows);
1913  for (uint32 row = 0; row < shape_.rows; ++row)
1914  {
1915  returnArray(0, row) = static_cast<uint32>(stl_algorithms::max_element(cbegin(row),
1916  cend(row), comparitor) - cbegin(row));
1917  }
1918 
1919  return returnArray;
1920  }
1921  case Axis::ROW:
1922  {
1923  NdArray<dtype> arrayTransposed = transpose();
1924  NdArray<uint32> returnArray(1, arrayTransposed.shape_.rows);
1925  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1926  {
1927  returnArray(0, row) = static_cast<uint32>(stl_algorithms::max_element(arrayTransposed.cbegin(row),
1928  arrayTransposed.cend(row), comparitor) - arrayTransposed.cbegin(row));
1929  }
1930 
1931  return returnArray;
1932  }
1933  default:
1934  {
1935  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1936  return {}; // get rid of compiler warning
1937  }
1938  }
1939  }
1940 
1941  //============================================================================
1942  // Method Description:
1954  {
1956 
1957  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
1958  {
1959  return lhs < rhs;
1960  };
1961 
1962  switch (inAxis)
1963  {
1964  case Axis::NONE:
1965  {
1966  NdArray<uint32> returnArray = { static_cast<uint32>(stl_algorithms::min_element(cbegin(),
1967  cend(), comparitor) - cbegin()) };
1968  return returnArray;
1969  }
1970  case Axis::COL:
1971  {
1972  NdArray<uint32> returnArray(1, shape_.rows);
1973  for (uint32 row = 0; row < shape_.rows; ++row)
1974  {
1975  returnArray(0, row) = static_cast<uint32>(stl_algorithms::min_element(cbegin(row),
1976  cend(row), comparitor) - cbegin(row));
1977  }
1978 
1979  return returnArray;
1980  }
1981  case Axis::ROW:
1982  {
1983  NdArray<dtype> arrayTransposed = transpose();
1984  NdArray<uint32> returnArray(1, arrayTransposed.shape_.rows);
1985  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1986  {
1987  returnArray(0, row) = static_cast<uint32>(stl_algorithms::min_element(arrayTransposed.cbegin(row),
1988  arrayTransposed.cend(row), comparitor) - arrayTransposed.cbegin(row));
1989  }
1990 
1991  return returnArray;
1992  }
1993  default:
1994  {
1995  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1996  return {}; // get rid of compiler warning
1997  }
1998  }
1999  }
2000 
2001  //============================================================================
2002  // Method Description:
2013  {
2015 
2016  switch (inAxis)
2017  {
2018  case Axis::NONE:
2019  {
2020  std::vector<uint32> idx(size_);
2021  std::iota(idx.begin(), idx.end(), 0);
2022 
2023  const auto function = [this](uint32 i1, uint32 i2) noexcept -> bool
2024  {
2025  return (*this)[i1] < (*this)[i2];
2026  };
2027 
2028  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2029  return NdArray<uint32>(idx);
2030  }
2031  case Axis::COL:
2032  {
2033  NdArray<uint32> returnArray(shape_);
2034  for (uint32 row = 0; row < shape_.rows; ++row)
2035  {
2036  std::vector<uint32> idx(shape_.cols);
2037  std::iota(idx.begin(), idx.end(), 0);
2038 
2039  const auto function = [this, row](uint32 i1, uint32 i2) noexcept -> bool
2040  {
2041  return operator()(row, i1) < operator()(row, i2);
2042  };
2043 
2044  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2045 
2046  for (uint32 col = 0; col < shape_.cols; ++col)
2047  {
2048  returnArray(row, col) = idx[col];
2049  }
2050  }
2051  return returnArray;
2052  }
2053  case Axis::ROW:
2054  {
2055  NdArray<dtype> arrayTransposed = transpose();
2056  NdArray<uint32> returnArray(shape_.cols, shape_.rows);
2057  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
2058  {
2059  std::vector<uint32> idx(arrayTransposed.shape_.cols);
2060  std::iota(idx.begin(), idx.end(), 0);
2061 
2062  const auto function = [&arrayTransposed, row](uint32 i1, uint32 i2) noexcept -> bool
2063  {
2064  return arrayTransposed(row, i1) < arrayTransposed(row, i2);
2065  };
2066 
2067  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2068 
2069  for (uint32 col = 0; col < arrayTransposed.shape_.cols; ++col)
2070  {
2071  returnArray(row, col) = idx[col];
2072  }
2073  }
2074  return returnArray.transpose();
2075  }
2076  default:
2077  {
2078  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2079  return {}; // get rid of compiler warning
2080  }
2081  }
2082  }
2083 
2084  //============================================================================
2085  // Method Description:
2094  template<typename dtypeOut, typename dtype_ = dtype,
2099  {
2100  NdArray<dtypeOut> outArray(shape_);
2101 
2102  if (is_same_v<dtypeOut, dtype>)
2103  {
2104  std::copy(cbegin(), cend(), outArray.begin());
2105  }
2106  else
2107  {
2108  const auto function = [](dtype value) -> dtypeOut
2109  {
2110  return static_cast<dtypeOut>(value);
2111  };
2112 
2113  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2114  }
2115 
2116  return outArray;
2117  }
2118 
2119  //============================================================================
2120  // Method Description:
2129  template<typename dtypeOut, typename dtype_ = dtype,
2134  {
2135  NdArray<dtypeOut> outArray(shape_);
2136 
2137  const auto function = [](const_reference value) -> dtypeOut
2138  {
2139  return std::complex<typename dtypeOut::value_type>(value);
2140  };
2141 
2142  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2143 
2144  return outArray;
2145  }
2146 
2147  //============================================================================
2148  // Method Description:
2157  template<typename dtypeOut, typename dtype_ = dtype,
2162  {
2163  NdArray<dtypeOut> outArray(shape_);
2164 
2165  if (std::is_same<dtypeOut, dtype>::value)
2166  {
2167  std::copy(cbegin(), cend(), outArray.begin());
2168  }
2169  else
2170  {
2171  const auto function = [](const_reference value) noexcept -> dtypeOut
2172  {
2173  return complex_cast<typename dtypeOut::value_type>(value);
2174  };
2175 
2176  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2177  }
2178 
2179  return outArray;
2180  }
2181 
2182  //============================================================================
2183  // Method Description:
2192  template<typename dtypeOut, typename dtype_ = dtype,
2197  {
2198  NdArray<dtypeOut> outArray(shape_);
2199 
2200  const auto function = [](const_reference value) -> dtypeOut
2201  {
2202  return static_cast<dtypeOut>(value.real());
2203  };
2204 
2205  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2206 
2207  return outArray;
2208  }
2209 
2210  //============================================================================
2211  // Method Description:
2217  value_type back() const noexcept
2218  {
2219  return *(cend() - 1);
2220  }
2221 
2222  //============================================================================
2223  // Method Description:
2229  reference back() noexcept
2230  {
2231  return *(end() - 1);
2232  }
2233 
2234  //============================================================================
2235  // Method Description:
2242  {
2243  return *(cend(row) - 1);
2244  }
2245 
2246  //============================================================================
2247  // Method Description:
2254  {
2255  return *(end(row) - 1);
2256  }
2257 
2258  //============================================================================
2259  // Method Description:
2268  {
2269  STATIC_ASSERT_INTEGER(dtype);
2270 
2272  [](dtype& value) noexcept -> void
2273  {
2274  value = endian::byteSwap(value);
2275  }
2276  );
2277 
2278  switch (endianess_)
2279  {
2280  case Endian::NATIVE:
2281  {
2283  break;
2284  }
2285  case Endian::LITTLE:
2286  {
2287  endianess_ = Endian::BIG;
2288  break;
2289  }
2290  case Endian::BIG:
2291  {
2292  endianess_ = Endian::LITTLE;
2293  break;
2294  }
2295  }
2296 
2297  return *this;
2298  }
2299 
2300  //============================================================================
2301  // Method Description:
2312  {
2314 
2315  NdArray<dtype> outArray(shape_);
2316  stl_algorithms::transform(cbegin(), cend(), outArray.begin(),
2317  [inMin, inMax](dtype value) noexcept -> dtype
2318  {
2319 #ifdef __cpp_lib_clamp
2320  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
2321  {
2322  return lhs < rhs;
2323  };
2324 
2325  return std::clamp(value, inMin, inMax, comparitor);
2326 #else
2327  if (value < inMin)
2328  {
2329  return inMin;
2330  }
2331  else if (value > inMax)
2332  {
2333  return inMax;
2334  }
2335 
2336  return value;
2337 #endif
2338  });
2339 
2340  return outArray;
2341  }
2342 
2343  //============================================================================
2344  // Method Description:
2352  {
2353  return operator()(rSlice(), inColumn);
2354  }
2355 
2356  //============================================================================
2357  // Method Description:
2366  {
2368 
2369  switch (inAxis)
2370  {
2371  case Axis::NONE:
2372  {
2373  NdArray<bool> returnArray = { stl_algorithms::find(cbegin(), cend(), inValue) != cend() };
2374  return returnArray;
2375  }
2376  case Axis::COL:
2377  {
2378  NdArray<bool> returnArray(1, shape_.rows);
2379  for (uint32 row = 0; row < shape_.rows; ++row)
2380  {
2381  returnArray(0, row) = stl_algorithms::find(cbegin(row), cend(row), inValue) != cend(row);
2382  }
2383 
2384  return returnArray;
2385  }
2386  case Axis::ROW:
2387  {
2388  NdArray<dtype> transArray = transpose();
2389  NdArray<bool> returnArray(1, transArray.shape_.rows);
2390  for (uint32 row = 0; row < transArray.shape_.rows; ++row)
2391  {
2392  returnArray(0, row) = stl_algorithms::find(transArray.cbegin(row), transArray.cend(row), inValue) != transArray.cend(row);
2393  }
2394 
2395  return returnArray;
2396  }
2397  default:
2398  {
2399  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2400  return {}; // get rid of compiler warning
2401  }
2402  }
2403  }
2404 
2405  //============================================================================
2406  // Method Description:
2415  {
2416  return NdArray<dtype>(*this);
2417  }
2418 
2419  //============================================================================
2420  // Method Description:
2431  {
2433 
2434  switch (inAxis)
2435  {
2436  case Axis::NONE:
2437  {
2438  NdArray<dtype> returnArray(1, size_);
2439  returnArray[0] = front();
2440  for (uint32 i = 1; i < size_; ++i)
2441  {
2442  returnArray[i] = returnArray[i - 1] * array_[i];
2443  }
2444 
2445  return returnArray;
2446  }
2447  case Axis::COL:
2448  {
2449  NdArray<dtype> returnArray(shape_);
2450  for (uint32 row = 0; row < shape_.rows; ++row)
2451  {
2452  returnArray(row, 0) = operator()(row, 0);
2453  for (uint32 col = 1; col < shape_.cols; ++col)
2454  {
2455  returnArray(row, col) = returnArray(row, col - 1) * operator()(row, col);
2456  }
2457  }
2458 
2459  return returnArray;
2460  }
2461  case Axis::ROW:
2462  {
2463  NdArray<dtype> returnArray(shape_);
2464  for (uint32 col = 0; col < shape_.cols; ++col)
2465  {
2466  returnArray(0, col) = operator()(0, col);
2467  for (uint32 row = 1; row < shape_.rows; ++row)
2468  {
2469  returnArray(row, col) = returnArray(row - 1, col) * operator()(row, col);
2470  }
2471  }
2472 
2473  return returnArray;
2474  }
2475  default:
2476  {
2477  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2478  return {}; // get rid of compiler warning
2479  }
2480  }
2481  }
2482 
2483  //============================================================================
2484  // Method Description:
2495  {
2497 
2498  switch (inAxis)
2499  {
2500  case Axis::NONE:
2501  {
2502  NdArray<dtype> returnArray(1, size_);
2503  returnArray[0] = front();
2504  for (uint32 i = 1; i < size_; ++i)
2505  {
2506  returnArray[i] = returnArray[i - 1] + array_[i];
2507  }
2508 
2509  return returnArray;
2510  }
2511  case Axis::COL:
2512  {
2513  NdArray<dtype> returnArray(shape_);
2514  for (uint32 row = 0; row < shape_.rows; ++row)
2515  {
2516  returnArray(row, 0) = operator()(row, 0);
2517  for (uint32 col = 1; col < shape_.cols; ++col)
2518  {
2519  returnArray(row, col) = returnArray(row, col - 1) + operator()(row, col);
2520  }
2521  }
2522 
2523  return returnArray;
2524  }
2525  case Axis::ROW:
2526  {
2527  NdArray<dtype> returnArray(shape_);
2528  for (uint32 col = 0; col < shape_.cols; ++col)
2529  {
2530  returnArray(0, col) = operator()(0, col);
2531  for (uint32 row = 1; row < shape_.rows; ++row)
2532  {
2533  returnArray(row, col) = returnArray(row - 1, col) + operator()(row, col);
2534  }
2535  }
2536 
2537  return returnArray;
2538  }
2539  default:
2540  {
2541  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2542  return {}; // get rid of compiler warning
2543  }
2544  }
2545  }
2546 
2547  //============================================================================
2548  // Method Description:
2552  pointer data() noexcept
2553  {
2554  return array_;
2555  }
2556 
2557  //============================================================================
2558  // Method Description:
2562  const_pointer data() const noexcept
2563  {
2564  return array_;
2565  }
2566 
2567  //============================================================================
2568  // Method Description:
2575  {
2576  ownsPtr_ = false;
2577  return data();
2578  }
2579 
2580  //============================================================================
2581  // Method Description:
2591  NdArray<dtype> diagonal(int32 inOffset = 0, Axis inAxis = Axis::ROW) const
2592  {
2593  switch (inAxis)
2594  {
2595  case Axis::ROW:
2596  {
2597  std::vector<dtype> diagnolValues;
2598  int32 col = inOffset;
2599  for (uint32 row = 0; row < shape_.rows; ++row)
2600  {
2601  if (col < 0)
2602  {
2603  ++col;
2604  continue;
2605  }
2606  if (col >= static_cast<int32>(shape_.cols))
2607  {
2608  break;
2609  }
2610 
2611  diagnolValues.push_back(operator()(row, static_cast<uint32>(col)));
2612  ++col;
2613  }
2614 
2615  return NdArray<dtype>(diagnolValues);
2616  }
2617  case Axis::COL:
2618  {
2619  std::vector<dtype> diagnolValues;
2620  uint32 col = 0;
2621  for (int32 row = inOffset; row < static_cast<int32>(shape_.rows); ++row)
2622  {
2623  if (row < 0)
2624  {
2625  ++col;
2626  continue;
2627  }
2628  if (col >= shape_.cols)
2629  {
2630  break;
2631  }
2632 
2633  diagnolValues.push_back(operator()(static_cast<uint32>(row), col));
2634  ++col;
2635  }
2636 
2637  return NdArray<dtype>(diagnolValues);
2638  }
2639  default:
2640  {
2641  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2642  return {}; // get rid of compiler warning
2643  }
2644  }
2645  }
2646 
2647  //============================================================================
2648  // Method Description:
2661  NdArray<dtype> dot(const NdArray<dtype>& inOtherArray) const
2662  {
2664 
2665  if (shape_ == inOtherArray.shape_ && (shape_.rows == 1 || shape_.cols == 1))
2666  {
2667  dtype dotProduct = std::inner_product(cbegin(), cend(), inOtherArray.cbegin(), dtype{ 0 });
2668  NdArray<dtype> returnArray = { dotProduct };
2669  return returnArray;
2670  }
2671  if (shape_.cols == inOtherArray.shape_.rows)
2672  {
2673  // 2D array, use matrix multiplication
2674  NdArray<dtype> returnArray(shape_.rows, inOtherArray.shape_.cols);
2675  auto otherArrayT = inOtherArray.transpose();
2676 
2677  for (uint32 i = 0; i < shape_.rows; ++i)
2678  {
2679  for (uint32 j = 0; j < otherArrayT.shape_.rows; ++j)
2680  {
2681  returnArray(i, j) = std::inner_product(otherArrayT.cbegin(j), otherArrayT.cend(j), cbegin(i), dtype{ 0 });
2682  }
2683  }
2684 
2685  return returnArray;
2686  }
2687 
2688  std::string errStr = "shapes of [" + utils::num2str(shape_.rows) + ", " + utils::num2str(shape_.cols) + "]";
2689  errStr += " and [" + utils::num2str(inOtherArray.shape_.rows) + ", " + utils::num2str(inOtherArray.shape_.cols) + "]";
2690  errStr += " are not consistent.";
2692 
2693  return NdArray<dtype>(); // get rid of compiler warning
2694  }
2695 
2696  //============================================================================
2697  // Method Description:
2705  void dump(const std::string& inFilename) const
2706  {
2707  filesystem::File f(inFilename);
2708  if (!f.hasExt())
2709  {
2710  f.withExt(".bin");
2711  }
2712 
2713  std::ofstream ofile(f.fullName().c_str(), std::ios::binary);
2714  if (!ofile.good())
2715  {
2716  THROW_RUNTIME_ERROR("Unable to open the input file:\n\t" + inFilename);
2717  }
2718 
2719  if (array_ != nullptr)
2720  {
2721  ofile.write(reinterpret_cast<const char*>(array_), size_ * sizeof(dtype));
2722  }
2723  ofile.close();
2724  }
2725 
2726  //============================================================================
2727  // Method Description:
2733  Endian endianess() const noexcept
2734  {
2735  STATIC_ASSERT_ARITHMETIC(dtype);
2736 
2737  return endianess_;
2738  }
2739 
2740  //============================================================================
2741  // Method Description:
2751  NdArray<dtype>& fill(value_type inFillValue) noexcept
2752  {
2753  stl_algorithms::fill(begin(), end(), inFillValue);
2754  return *this;
2755  }
2756 
2757  //============================================================================
2758  // Method Description:
2766  {
2768 
2769  std::vector<uint32> indices;
2770  uint32 idx = 0;
2771  for (auto value : *this)
2772  {
2773  if (value != dtype{ 0 })
2774  {
2775  indices.push_back(idx);
2776  }
2777  ++idx;
2778  }
2779 
2780  return NdArray<uint32>(indices);
2781  }
2782 
2783  //============================================================================
2784  // Method Description:
2793  {
2794  NdArray<dtype> outArray(1, size_);
2795  stl_algorithms::copy(cbegin(), cend(), outArray.begin());
2796  return outArray;
2797  }
2798 
2799  //============================================================================
2800  // Method Description:
2806  value_type front() const noexcept
2807  {
2808  return *cbegin();
2809  }
2810 
2811  //============================================================================
2812  // Method Description:
2818  reference front() noexcept
2819  {
2820  return *begin();
2821  }
2822 
2823  //============================================================================
2824  // Method Description:
2831  {
2832  return *cbegin(row);
2833  }
2834 
2835  //============================================================================
2836  // Method Description:
2843  {
2844  return *begin(row);
2845  }
2846 
2847  //============================================================================
2848  // Method Description:
2857  {
2858  return operator[](inIndices);
2859  }
2860 
2861  //============================================================================
2862  // Method Description:
2873  {
2874  return operator[](inMask);
2875  }
2876 
2877  //============================================================================
2878  // Method Description:
2885  bool isempty() const noexcept
2886  {
2887  return size_ == 0;
2888  }
2889 
2890  //============================================================================
2891  // Method Description:
2898  bool isflat() const noexcept
2899  {
2900  return shape_.rows == 1 || shape_.cols == 1;
2901  }
2902 
2903  //============================================================================
2904  // Method Description:
2911  {
2913 
2914  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
2915  {
2916  return lhs < rhs;
2917  };
2918 
2919  switch (inAxis)
2920  {
2921  case Axis::NONE:
2922  {
2923  return { stl_algorithms::is_sorted(cbegin(), cend(), comparitor) };
2924  }
2925  case Axis::ROW:
2926  {
2927  NdArray<bool> returnArray(shape_.cols, 1);
2928  auto transposedArray = transpose();
2929  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
2930  {
2931  returnArray(0, row) = stl_algorithms::is_sorted(transposedArray.cbegin(row),
2932  transposedArray.cend(row), comparitor);
2933  }
2934 
2935  return returnArray;
2936  }
2937  case Axis::COL:
2938  {
2939  NdArray<bool> returnArray(1, shape_.rows);
2940  for (uint32 row = 0; row < shape_.rows; ++row)
2941  {
2942  returnArray(0, row) = stl_algorithms::is_sorted(cbegin(row), cend(row), comparitor);
2943  }
2944 
2945  return returnArray;
2946  }
2947  default:
2948  {
2949  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2950  return {}; // get rid of compiler warning
2951  }
2952  }
2953  }
2954 
2955  //============================================================================
2956  // Method Description:
2961  bool issquare() const noexcept
2962  {
2963  return shape_.issquare();
2964  }
2965 
2966  //============================================================================
2967  // Method Description:
2976  {
2977  if (size_ != 1)
2978  {
2979  THROW_INVALID_ARGUMENT_ERROR("Can only convert an array of size 1 to a C++ scaler");
2980  }
2981 
2982  return front();
2983  }
2984 
2985  //============================================================================
2986  // Method Description:
2997  {
2999 
3000  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3001  {
3002  return lhs < rhs;
3003  };
3004 
3005  switch (inAxis)
3006  {
3007  case Axis::NONE:
3008  {
3009  NdArray<dtype> returnArray = { *stl_algorithms::max_element(cbegin(), cend(), comparitor) };
3010  return returnArray;
3011  }
3012  case Axis::COL:
3013  {
3014  NdArray<dtype> returnArray(1, shape_.rows);
3015  for (uint32 row = 0; row < shape_.rows; ++row)
3016  {
3017  returnArray(0, row) = *stl_algorithms::max_element(cbegin(row), cend(row), comparitor);
3018  }
3019 
3020  return returnArray;
3021  }
3022  case Axis::ROW:
3023  {
3024  NdArray<dtype> transposedArray = transpose();
3025  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3026  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3027  {
3028  returnArray(0, row) = *stl_algorithms::max_element(transposedArray.cbegin(row),
3029  transposedArray.cend(row), comparitor);
3030  }
3031 
3032  return returnArray;
3033  }
3034  default:
3035  {
3036  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3037  return {}; // get rid of compiler warning
3038  }
3039  }
3040  }
3041 
3042  //============================================================================
3043  // Method Description:
3054  {
3056 
3057  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3058  {
3059  return lhs < rhs;
3060  };
3061 
3062  switch (inAxis)
3063  {
3064  case Axis::NONE:
3065  {
3066  NdArray<dtype> returnArray = { *stl_algorithms::min_element(cbegin(), cend(), comparitor) };
3067  return returnArray;
3068  }
3069  case Axis::COL:
3070  {
3071  NdArray<dtype> returnArray(1, shape_.rows);
3072  for (uint32 row = 0; row < shape_.rows; ++row)
3073  {
3074  returnArray(0, row) = *stl_algorithms::min_element(cbegin(row), cend(row), comparitor);
3075  }
3076 
3077  return returnArray;
3078  }
3079  case Axis::ROW:
3080  {
3081  NdArray<dtype> transposedArray = transpose();
3082  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3083  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3084  {
3085  returnArray(0, row) = *stl_algorithms::min_element(transposedArray.cbegin(row),
3086  transposedArray.cend(row), comparitor);
3087  }
3088 
3089  return returnArray;
3090  }
3091  default:
3092  {
3093  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3094  return {}; // get rid of compiler warning
3095  }
3096  }
3097  }
3098 
3099  //============================================================================
3100  // Method Description:
3113  {
3115 
3116  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3117  {
3118  return lhs < rhs;
3119  };
3120 
3121  if (size_ == 0)
3122  {
3123  THROW_RUNTIME_ERROR("Median is undefined for an array of size = 0.");
3124  }
3125 
3126  switch (inAxis)
3127  {
3128  case Axis::NONE:
3129  {
3130  NdArray<dtype> copyArray(*this);
3131 
3132  const uint32 middleIdx = size_ / 2; // integer division
3133  stl_algorithms::nth_element(copyArray.begin(), copyArray.begin() + middleIdx, copyArray.end(), comparitor);
3134 
3135  dtype medianValue = copyArray.array_[middleIdx];
3136  if (size_ % 2 == 0)
3137  {
3138  const uint32 lhsIndex = middleIdx - 1;
3139  stl_algorithms::nth_element(copyArray.begin(), copyArray.begin() + lhsIndex, copyArray.end(), comparitor);
3140  medianValue = (medianValue + copyArray.array_[lhsIndex]) / dtype{2}; // potentially integer division, ok
3141  }
3142 
3143  return { medianValue };
3144  }
3145  case Axis::COL:
3146  {
3147  NdArray<dtype> copyArray(*this);
3148  NdArray<dtype> returnArray(1, shape_.rows);
3149 
3150  const bool isEven = shape_.cols % 2 == 0;
3151  for (uint32 row = 0; row < shape_.rows; ++row)
3152  {
3153  const uint32 middleIdx = shape_.cols / 2; // integer division
3154  stl_algorithms::nth_element(copyArray.begin(row), copyArray.begin(row) + middleIdx,
3155  copyArray.end(row), comparitor);
3156 
3157  dtype medianValue = copyArray(row, middleIdx);
3158  if (isEven)
3159  {
3160  const uint32 lhsIndex = middleIdx - 1;
3161  stl_algorithms::nth_element(copyArray.begin(row), copyArray.begin(row) + lhsIndex,
3162  copyArray.end(row), comparitor);
3163  medianValue = (medianValue + copyArray(row, lhsIndex)) / dtype{2}; // potentially integer division, ok
3164  }
3165 
3166  returnArray(0, row) = medianValue;
3167  }
3168 
3169  return returnArray;
3170  }
3171  case Axis::ROW:
3172  {
3173  NdArray<dtype> transposedArray = transpose();
3174  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3175 
3176  const bool isEven = shape_.rows % 2 == 0;
3177  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3178  {
3179  const uint32 middleIdx = transposedArray.shape_.cols / 2; // integer division
3180  stl_algorithms::nth_element(transposedArray.begin(row), transposedArray.begin(row) + middleIdx,
3181  transposedArray.end(row), comparitor);
3182 
3183  dtype medianValue = transposedArray(row, middleIdx);
3184  if (isEven)
3185  {
3186  const uint32 lhsIndex = middleIdx - 1;
3187  stl_algorithms::nth_element(transposedArray.begin(row), transposedArray.begin(row) + lhsIndex,
3188  transposedArray.end(row), comparitor);
3189  medianValue = (medianValue + transposedArray(row, lhsIndex)) / dtype{2}; // potentially integer division, ok
3190  }
3191 
3192  returnArray(0, row) = medianValue;
3193  }
3194 
3195  return returnArray;
3196  }
3197  default:
3198  {
3199  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3200  return {}; // get rid of compiler warning
3201  }
3202  }
3203  }
3204 
3205  //============================================================================
3206  // Method Description:
3210  NdArray<dtype>& nans() noexcept
3211  {
3212  STATIC_ASSERT_FLOAT(dtype);
3213 
3215  return *this;
3216  }
3217 
3218  //============================================================================
3219  // Method Description:
3227  uint64 nbytes() const noexcept
3228  {
3229  return static_cast<uint64>(sizeof(dtype) * size_);
3230  }
3231 
3232  //============================================================================
3233  // Method Description:
3244  NdArray<dtype> newbyteorder(Endian inEndianess) const
3245  {
3246  STATIC_ASSERT_INTEGER(dtype);
3247 
3248  const bool nativeIsLittle = endian::isLittleEndian();
3249 
3250  switch (endianess_)
3251  {
3252  case Endian::NATIVE:
3253  {
3254  switch (inEndianess)
3255  {
3256  case Endian::NATIVE:
3257  {
3258  return NdArray(*this);
3259  }
3260  case Endian::BIG:
3261  {
3262  if (nativeIsLittle)
3263  {
3264  NdArray<dtype> outArray(shape_);
3265 
3266  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3267 
3268  outArray.endianess_ = Endian::BIG;
3269  return outArray;
3270  }
3271  else
3272  {
3273  auto outArray = NdArray(*this);
3274  outArray.endianess_ = Endian::BIG;
3275  return outArray;
3276  }
3277  }
3278  case Endian::LITTLE:
3279  {
3280  if (nativeIsLittle)
3281  {
3282  auto outArray = NdArray(*this);
3283  outArray.endianess_ = Endian::LITTLE;
3284  return outArray;
3285  }
3286  else
3287  {
3288  NdArray<dtype> outArray(shape_);
3289 
3290  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3291 
3292  outArray.endianess_ = Endian::LITTLE;
3293  return outArray;
3294  }
3295  }
3296  default:
3297  {
3298  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3299  return {}; // get rid of compiler warning
3300  }
3301  }
3302  break;
3303  }
3304  case Endian::BIG:
3305  {
3306  switch (inEndianess)
3307  {
3308  case Endian::NATIVE:
3309  {
3310  if (nativeIsLittle)
3311  {
3312  NdArray<dtype> outArray(shape_);
3313 
3314  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3315 
3316  outArray.endianess_ = Endian::NATIVE;
3317  return outArray;
3318  }
3319  else
3320  {
3321  auto outArray = NdArray(*this);
3322  outArray.endianess_ = Endian::NATIVE;
3323  return outArray;
3324  }
3325  }
3326  case Endian::BIG:
3327  {
3328  return NdArray(*this);
3329  }
3330  case Endian::LITTLE:
3331  {
3332  NdArray<dtype> outArray(shape_);
3333 
3334  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3335 
3336  outArray.endianess_ = Endian::LITTLE;
3337  return outArray;
3338  }
3339  default:
3340  {
3341  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3342  return {}; // get rid of compiler warning
3343  }
3344  }
3345  break;
3346  }
3347  case Endian::LITTLE:
3348  {
3349  switch (inEndianess)
3350  {
3351  case Endian::NATIVE:
3352  {
3353  if (nativeIsLittle)
3354  {
3355  auto outArray = NdArray(*this);
3356  outArray.endianess_ = Endian::NATIVE;
3357  return outArray;
3358  }
3359  else
3360  {
3361  NdArray<dtype> outArray(shape_);
3362 
3363  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3364 
3365  outArray.endianess_ = Endian::NATIVE;
3366  return outArray;
3367  }
3368  }
3369  case Endian::BIG:
3370  {
3371  NdArray<dtype> outArray(shape_);
3372 
3373  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3374 
3375  outArray.endianess_ = Endian::BIG;
3376  return outArray;
3377  }
3378  case Endian::LITTLE:
3379  {
3380  return NdArray(*this);
3381  }
3382  default:
3383  {
3384  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3385  return {}; // get rid of compiler warning
3386  }
3387  }
3388  break;
3389  }
3390  default:
3391  {
3392  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3393  return {}; // get rid of compiler warning
3394  }
3395  }
3396  }
3397 
3398  //============================================================================
3399  // Method Description:
3410  {
3412 
3413  const auto function = [](dtype i) -> bool
3414  {
3415  return i != dtype{ 0 };
3416  };
3417 
3418  switch (inAxis)
3419  {
3420  case Axis::NONE:
3421  {
3422  NdArray<bool> returnArray = { stl_algorithms::none_of(cbegin(), cend(), function) };
3423  return returnArray;
3424  }
3425  case Axis::COL:
3426  {
3427  NdArray<bool> returnArray(1, shape_.rows);
3428  for (uint32 row = 0; row < shape_.rows; ++row)
3429  {
3430  returnArray(0, row) = stl_algorithms::none_of(cbegin(row), cend(row), function);
3431  }
3432 
3433  return returnArray;
3434  }
3435  case Axis::ROW:
3436  {
3437  NdArray<dtype> arrayTransposed = transpose();
3438  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
3439  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
3440  {
3441  returnArray(0, row) = stl_algorithms::none_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
3442  }
3443 
3444  return returnArray;
3445  }
3446  default:
3447  {
3448  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3449  return {}; // get rid of compiler warning
3450  }
3451  }
3452  }
3453 
3454  //============================================================================
3455  // Method Description:
3465  std::pair<NdArray<uint32>, NdArray<uint32>> nonzero() const;
3466 
3467  //============================================================================
3468  // Method Description:
3475  uint32 numCols() const noexcept
3476  {
3477  return shape_.cols;
3478  }
3479 
3480  //============================================================================
3481  // Method Description:
3488  uint32 numRows() const noexcept
3489  {
3490  return shape_.rows;
3491  }
3492 
3493  //============================================================================
3494  // Method Description:
3498  NdArray<dtype>& ones() noexcept
3499  {
3501 
3502  fill(dtype{ 1 });
3503  return *this;
3504  }
3505 
3506  //============================================================================
3507  // Method Description:
3512  bool ownsInternalData() noexcept
3513  {
3514  return ownsPtr_;
3515  }
3516 
3517  //============================================================================
3518  // Method Description:
3534  {
3536 
3537  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3538  {
3539  return lhs < rhs;
3540  };
3541 
3542  switch (inAxis)
3543  {
3544  case Axis::NONE:
3545  {
3546  if (inKth >= size_)
3547  {
3548  std::string errStr = "kth(=" + utils::num2str(inKth);
3549  errStr += ") out of bounds (" + utils::num2str(size_) + ")";
3551  }
3552 
3553  stl_algorithms::nth_element(begin(), begin() + inKth, end(), comparitor);
3554  break;
3555  }
3556  case Axis::COL:
3557  {
3558  if (inKth >= shape_.cols)
3559  {
3560  std::string errStr = "kth(=" + utils::num2str(inKth);
3561  errStr += ") out of bounds (" + utils::num2str(shape_.cols) + ")";
3563  }
3564 
3565  for (uint32 row = 0; row < shape_.rows; ++row)
3566  {
3567  stl_algorithms::nth_element(begin(row), begin(row) + inKth, end(row), comparitor);
3568  }
3569  break;
3570  }
3571  case Axis::ROW:
3572  {
3573  if (inKth >= shape_.rows)
3574  {
3575  std::string errStr = "kth(=" + utils::num2str(inKth);
3576  errStr += ") out of bounds (" + utils::num2str(shape_.rows) + ")";
3578  }
3579 
3580  NdArray<dtype> transposedArray = transpose();
3581  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3582  {
3583  stl_algorithms::nth_element(transposedArray.begin(row), transposedArray.begin(row) + inKth,
3584  transposedArray.end(row), comparitor);
3585  }
3586  *this = transposedArray.transpose();
3587  break;
3588  }
3589  }
3590 
3591  return *this;
3592  }
3593 
3594  //============================================================================
3595  // Method Description:
3599  void print() const
3600  {
3602 
3603  std::cout << *this;
3604  }
3605 
3606  //============================================================================
3607  // Method Description:
3618  {
3620 
3621  switch (inAxis)
3622  {
3623  case Axis::NONE:
3624  {
3625  dtype product = std::accumulate(cbegin(), cend(),
3626  dtype{ 1 }, std::multiplies<dtype>());
3627  NdArray<dtype> returnArray = { product };
3628  return returnArray;
3629  }
3630  case Axis::COL:
3631  {
3632  NdArray<dtype> returnArray(1, shape_.rows);
3633  for (uint32 row = 0; row < shape_.rows; ++row)
3634  {
3635  returnArray(0, row) = std::accumulate(cbegin(row), cend(row),
3636  dtype{ 1 }, std::multiplies<dtype>());
3637  }
3638 
3639  return returnArray;
3640  }
3641  case Axis::ROW:
3642  {
3643  NdArray<dtype> transposedArray = transpose();
3644  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3645  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3646  {
3647  returnArray(0, row) = std::accumulate(transposedArray.cbegin(row), transposedArray.cend(row),
3648  dtype{ 1 }, std::multiplies<dtype>());
3649  }
3650 
3651  return returnArray;
3652  }
3653  default:
3654  {
3655  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3656  return {}; // get rid of compiler warning
3657  }
3658  }
3659  }
3660 
3661  //============================================================================
3662  // Method Description:
3673  {
3675 
3676  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3677  {
3678  return lhs < rhs;
3679  };
3680 
3681  switch (inAxis)
3682  {
3683  case Axis::NONE:
3684  {
3685  const auto result = stl_algorithms::minmax_element(cbegin(), cend(), comparitor);
3686  NdArray<dtype> returnArray = { *result.second - *result.first };
3687  return returnArray;
3688  }
3689  case Axis::COL:
3690  {
3691  NdArray<dtype> returnArray(1, shape_.rows);
3692  for (uint32 row = 0; row < shape_.rows; ++row)
3693  {
3694  const auto result = stl_algorithms::minmax_element(cbegin(row), cend(row), comparitor);
3695  returnArray(0, row) = *result.second - *result.first;
3696  }
3697 
3698  return returnArray;
3699  }
3700  case Axis::ROW:
3701  {
3702  NdArray<dtype> transposedArray = transpose();
3703  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3704  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3705  {
3706  const auto result = stl_algorithms::minmax_element(transposedArray.cbegin(row), transposedArray.cend(row), comparitor);
3707  returnArray(0, row) = *result.second - *result.first;
3708  }
3709 
3710  return returnArray;
3711  }
3712  default:
3713  {
3714  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3715  return {}; // get rid of compiler warning
3716  }
3717  }
3718  }
3719 
3720  //============================================================================
3721  // Method Description:
3729  NdArray<dtype>& put(int32 inIndex, value_type inValue)
3730  {
3731  at(inIndex) = inValue;
3732 
3733  return *this;
3734  }
3735 
3736  //============================================================================
3737  // Method Description:
3746  NdArray<dtype>& put(int32 inRow, int32 inCol, value_type inValue)
3747  {
3748  at(inRow, inCol) = inValue;
3749 
3750  return *this;
3751  }
3752 
3753  //============================================================================
3754  // Method Description:
3762  NdArray<dtype>& put(const NdArray<uint32>& inIndices, value_type inValue)
3763  {
3764  for (auto index : inIndices)
3765  {
3766  put(index, inValue);
3767  }
3768 
3769  return *this;
3770  }
3771 
3772  //============================================================================
3773  // Method Description:
3781  NdArray<dtype>& put(const NdArray<uint32>& inIndices, const NdArray<dtype>& inValues)
3782  {
3783  if (inIndices.size() != inValues.size())
3784  {
3785  THROW_INVALID_ARGUMENT_ERROR("Input indices do not match values dimensions.");
3786  }
3787 
3788  uint32 counter = 0;
3789  for (auto index : inIndices)
3790  {
3791  put(index, inValues[counter++]);
3792  }
3793 
3794  return *this;
3795  }
3796 
3797  //============================================================================
3798  // Method Description:
3806  NdArray<dtype>& put(const Slice& inSlice, value_type inValue)
3807  {
3808  Slice inSliceCopy(inSlice);
3809  inSliceCopy.makePositiveAndValidate(size_);
3810 
3811  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
3812  {
3813  put(i, inValue);
3814  }
3815 
3816  return *this;
3817  }
3818 
3819  //============================================================================
3820  // Method Description:
3828  NdArray<dtype>& put(const Slice& inSlice, const NdArray<dtype>& inValues)
3829  {
3830  Slice inSliceCopy(inSlice);
3831  inSliceCopy.makePositiveAndValidate(size_);
3832 
3833  std::vector<uint32> indices;
3834  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
3835  {
3836  indices.push_back(i);
3837  }
3838 
3839  return put(NdArray<uint32>(indices), inValues);
3840  }
3841 
3842  //============================================================================
3843  // Method Description:
3852  NdArray<dtype>& put(const Slice& inRowSlice, const Slice& inColSlice, value_type inValue)
3853  {
3854  Slice inRowSliceCopy(inRowSlice);
3855  Slice inColSliceCopy(inColSlice);
3856 
3857  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3858  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3859 
3860  std::vector<uint32> indices;
3861  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3862  {
3863  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3864  {
3865  put(row, col, inValue);
3866  }
3867  }
3868 
3869  return *this;
3870  }
3871 
3872  //============================================================================
3873  // Method Description:
3882  NdArray<dtype>& put(const Slice& inRowSlice, int32 inColIndex, value_type inValue)
3883  {
3884  Slice inRowSliceCopy(inRowSlice);
3885  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3886 
3887  std::vector<uint32> indices;
3888  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3889  {
3890  put(row, inColIndex, inValue);
3891  }
3892 
3893  return *this;
3894  }
3895 
3896  //============================================================================
3897  // Method Description:
3906  NdArray<dtype>& put(int32 inRowIndex, const Slice& inColSlice, value_type inValue)
3907  {
3908  Slice inColSliceCopy(inColSlice);
3909  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3910 
3911  std::vector<uint32> indices;
3912  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3913  {
3914  put(inRowIndex, col, inValue);
3915  }
3916 
3917  return *this;
3918  }
3919 
3920  //============================================================================
3921  // Method Description:
3930  NdArray<dtype>& put(const Slice& inRowSlice, const Slice& inColSlice, const NdArray<dtype>& inValues)
3931  {
3932  Slice inRowSliceCopy(inRowSlice);
3933  Slice inColSliceCopy(inColSlice);
3934 
3935  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3936  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3937 
3938  std::vector<uint32> indices;
3939  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3940  {
3941  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3942  {
3943  const uint32 index = row * shape_.cols + col;
3944  indices.push_back(index);
3945  }
3946  }
3947 
3948  return put(NdArray<uint32>(indices), inValues);
3949  }
3950 
3951  //============================================================================
3952  // Method Description:
3961  NdArray<dtype>& put(const Slice& inRowSlice, int32 inColIndex, const NdArray<dtype>& inValues)
3962  {
3963  Slice inRowSliceCopy(inRowSlice);
3964  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3965 
3966  std::vector<uint32> indices;
3967  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3968  {
3969  const uint32 index = row * shape_.cols + inColIndex;
3970  indices.push_back(index);
3971  }
3972 
3973  return put(NdArray<uint32>(indices), inValues);
3974  }
3975 
3976  //============================================================================
3977  // Method Description:
3986  NdArray<dtype>& put(int32 inRowIndex, const Slice& inColSlice, const NdArray<dtype>& inValues)
3987  {
3988  Slice inColSliceCopy(inColSlice);
3989  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3990 
3991  std::vector<uint32> indices;
3992  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3993  {
3994  const uint32 index = inRowIndex * shape_.cols + col;
3995  indices.push_back(index);
3996  }
3997 
3998  return put(NdArray<uint32>(indices), inValues);
3999  }
4000 
4001  //============================================================================
4002  // Method Description:
4009  {
4010  if (inMask.shape() != shape_)
4011  {
4012  THROW_INVALID_ARGUMENT_ERROR("input inMask must be the same shape as the array it is masking.");
4013  }
4014 
4015  return put(inMask.flatnonzero(), inValue);
4016  }
4017 
4018  //============================================================================
4019  // Method Description:
4025  NdArray<dtype>& putMask(const NdArray<bool>& inMask, const NdArray<dtype>& inValues)
4026  {
4027  if (inMask.shape() != shape_)
4028  {
4029  THROW_INVALID_ARGUMENT_ERROR("input inMask must be the same shape as the array it is masking.");
4030  }
4031 
4032  return put(inMask.flatnonzero(), inValues);
4033  }
4034 
4035  //============================================================================
4036  // Method Description:
4043  NdArray<dtype>& ravel() noexcept
4044  {
4045  reshape(size_);
4046  return *this;
4047  }
4048 
4049  //============================================================================
4050  // Method Description:
4060  NdArray<dtype> repeat(uint32 inNumRows, uint32 inNumCols) const
4061  {
4062  NdArray<dtype> returnArray(shape_.rows * inNumRows, shape_.cols * inNumCols);
4063 
4064  for (uint32 row = 0; row < inNumRows; ++row)
4065  {
4066  for (uint32 col = 0; col < inNumCols; ++col)
4067  {
4068  std::vector<uint32> indices(shape_.size());
4069 
4070  const uint32 rowStart = row * shape_.rows;
4071  const uint32 colStart = col * shape_.cols;
4072 
4073  const uint32 rowEnd = (row + 1) * shape_.rows;
4074  const uint32 colEnd = (col + 1) * shape_.cols;
4075 
4076  uint32 counter = 0;
4077  for (uint32 rowIdx = rowStart; rowIdx < rowEnd; ++rowIdx)
4078  {
4079  for (uint32 colIdx = colStart; colIdx < colEnd; ++colIdx)
4080  {
4081  indices[counter++] = rowIdx * returnArray.shape_.cols + colIdx;
4082  }
4083  }
4084 
4085  returnArray.put(NdArray<uint32>(indices), *this);
4086  }
4087  }
4088 
4089  return returnArray;
4090  }
4091 
4092  //============================================================================
4093  // Method Description:
4103  NdArray<dtype> repeat(const Shape& inRepeatShape) const
4104  {
4105  return repeat(inRepeatShape.rows, inRepeatShape.cols);
4106  }
4107 
4108  //============================================================================
4109  // Method Description:
4115  void replace(value_type oldValue, value_type newValue)
4116  {
4118 
4119  stl_algorithms::replace(begin(), end(), oldValue, newValue);
4120  }
4121 
4122  //============================================================================
4123  // Method Description:
4134  {
4135  if (inSize != size_)
4136  {
4137  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into shape ";
4138  errStr += "[" + utils::num2str(1) + ", " + utils::num2str(inSize) + "]";
4139  THROW_RUNTIME_ERROR(errStr);
4140  }
4141 
4142  shape_.rows = 1;
4143  shape_.cols = inSize;
4144 
4145  return *this;
4146  }
4147 
4148  //============================================================================
4149  // Method Description:
4160  NdArray<dtype>& reshape(int32 inNumRows, int32 inNumCols)
4161  {
4162  if (inNumRows < 0)
4163  {
4164  if (size_ % inNumCols == 0)
4165  {
4166  return reshape(size_ / inNumCols, inNumCols);
4167  }
4168 
4169  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into a shape ";
4170  errStr += "with " + utils::num2str(inNumCols) + " columns";
4172 
4173  }
4174 
4175  if (inNumCols < 0)
4176  {
4177  if (size_ % inNumRows == 0)
4178  {
4179  return reshape(inNumRows, size_ / inNumRows);
4180  }
4181 
4182  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into a shape ";
4183  errStr += "with " + utils::num2str(inNumRows) + " rows";
4185 
4186  }
4187 
4188  if (static_cast<uint32>(inNumRows * inNumCols) != size_)
4189  {
4190  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into shape ";
4191  errStr += "[" + utils::num2str(inNumRows) + ", " + utils::num2str(inNumCols) + "]";
4193  }
4194 
4195  shape_.rows = static_cast<uint32>(inNumRows);
4196  shape_.cols = static_cast<uint32>(inNumCols);
4197 
4198  return *this;
4199  }
4200 
4201  //============================================================================
4202  // Method Description:
4213  NdArray<dtype>& reshape(const Shape& inShape)
4214  {
4215  return reshape(inShape.rows, inShape.cols);
4216  }
4217 
4218  //============================================================================
4219  // Method Description:
4228  NdArray<dtype>& resizeFast(uint32 inNumRows, uint32 inNumCols)
4229  {
4230  newArray(Shape(inNumRows, inNumCols));
4231  return *this;
4232  }
4233 
4234  //============================================================================
4235  // Method Description:
4244  NdArray<dtype>& resizeFast(const Shape& inShape)
4245  {
4246  return resizeFast(inShape.rows, inShape.cols);
4247  }
4248 
4249  //============================================================================
4250  // Method Description:
4261  NdArray<dtype>& resizeSlow(uint32 inNumRows, uint32 inNumCols)
4262  {
4263  std::vector<dtype> oldData(size_);
4264  stl_algorithms::copy(begin(), end(), oldData.begin());
4265 
4266  const Shape inShape(inNumRows, inNumCols);
4267  const Shape oldShape = shape_;
4268 
4269  newArray(inShape);
4270 
4271  for (uint32 row = 0; row < inShape.rows; ++row)
4272  {
4273  for (uint32 col = 0; col < inShape.cols; ++col)
4274  {
4275  if (row >= oldShape.rows || col >= oldShape.cols)
4276  {
4277  operator()(row, col) = dtype{ 0 }; // zero fill
4278  }
4279  else
4280  {
4281  operator()(row, col) = oldData[row * oldShape.cols + col];
4282  }
4283  }
4284  }
4285 
4286  return *this;
4287  }
4288 
4289  //============================================================================
4290  // Method Description:
4301  NdArray<dtype>& resizeSlow(const Shape& inShape)
4302  {
4303  return resizeSlow(inShape.rows, inShape.cols);
4304  }
4305 
4306  //============================================================================
4307  // Method Description:
4318  NdArray<dtype> round(uint8 inNumDecimals = 0) const
4319  {
4320  STATIC_ASSERT_FLOAT(dtype);
4321 
4322  NdArray<dtype> returnArray(shape_);
4323  const double multFactor = utils::power(10.0, inNumDecimals);
4324  const auto function = [multFactor](dtype value) noexcept -> dtype
4325  {
4326  return static_cast<dtype>(std::nearbyint(static_cast<double>(value) * multFactor) / multFactor);
4327  };
4328 
4329  stl_algorithms::transform(cbegin(), cend(), returnArray.begin(), function);
4330 
4331  return returnArray;
4332  }
4333 
4334  //============================================================================
4335  // Method Description:
4343  {
4344  return NdArray<dtype>(cbegin(inRow), cend(inRow));
4345  }
4346 
4347  //============================================================================
4348  // Method Description:
4356  Shape shape() const noexcept
4357  {
4358  return shape_;
4359  }
4360 
4361  //============================================================================
4362  // Method Description:
4370  size_type size() const noexcept
4371  {
4372  return size_;
4373  }
4374 
4375  //============================================================================
4376  // Method Description:
4387  {
4389 
4390  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
4391  {
4392  return lhs < rhs;
4393  };
4394 
4395  switch (inAxis)
4396  {
4397  case Axis::NONE:
4398  {
4399  stl_algorithms::sort(begin(), end(), comparitor);
4400  break;
4401  }
4402  case Axis::COL:
4403  {
4404  for (uint32 row = 0; row < shape_.rows; ++row)
4405  {
4406  stl_algorithms::sort(begin(row), end(row), comparitor);
4407  }
4408  break;
4409  }
4410  case Axis::ROW:
4411  {
4412  NdArray<dtype> transposedArray = transpose();
4413  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
4414  {
4415  stl_algorithms::sort(transposedArray.begin(row), transposedArray.end(row), comparitor);
4416  }
4417 
4418  *this = transposedArray.transpose();
4419  break;
4420  }
4421  }
4422 
4423  return *this;
4424  }
4425 
4426  //============================================================================
4427  // Method Description:
4433  std::string str() const
4434  {
4436 
4437  std::string out;
4438  out += "[";
4439  for (uint32 row = 0; row < shape_.rows; ++row)
4440  {
4441  out += "[";
4442  for (uint32 col = 0; col < shape_.cols; ++col)
4443  {
4444  out += utils::value2str(operator()(row, col)) + ", ";
4445  }
4446 
4447  if (row == shape_.rows - 1)
4448  {
4449  out += "]";
4450  }
4451  else
4452  {
4453  out += "]\n";
4454  }
4455  }
4456  out += "]\n";
4457  return out;
4458  }
4459 
4460  //============================================================================
4461  // Method Description:
4472  {
4474 
4475  switch (inAxis)
4476  {
4477  case Axis::NONE:
4478  {
4479  NdArray<dtype> returnArray = { std::accumulate(cbegin(), cend(), dtype{ 0 }) };
4480  return returnArray;
4481  }
4482  case Axis::COL:
4483  {
4484  NdArray<dtype> returnArray(1, shape_.rows);
4485  for (uint32 row = 0; row < shape_.rows; ++row)
4486  {
4487  returnArray(0, row) = std::accumulate(cbegin(row), cend(row), dtype{ 0 });
4488  }
4489 
4490  return returnArray;
4491  }
4492  case Axis::ROW:
4493  {
4494  NdArray<dtype> transposedArray = transpose();
4495  const Shape transShape = transposedArray.shape();
4496  NdArray<dtype> returnArray(1, transShape.rows);
4497  for (uint32 row = 0; row < transShape.rows; ++row)
4498  {
4499  returnArray(0, row) = std::accumulate(transposedArray.cbegin(row), transposedArray.cend(row), dtype{ 0 });
4500  }
4501 
4502  return returnArray;
4503  }
4504  default:
4505  {
4506  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
4507  return {}; // get rid of compiler warning
4508  }
4509  }
4510  }
4511 
4512  //============================================================================
4513  // Method Description:
4522  {
4523  return transpose();
4524  }
4525 
4526  //============================================================================
4527  // Method Description:
4539  void tofile(const std::string& inFilename, const std::string& inSep = "") const
4540  {
4542 
4543  if (inSep.empty())
4544  {
4545  dump(inFilename);
4546  }
4547  else
4548  {
4549  filesystem::File f(inFilename);
4550  if (!f.hasExt())
4551  {
4552  f.withExt("txt");
4553  }
4554 
4555  std::ofstream ofile(f.fullName().c_str());
4556  if (!ofile.good())
4557  {
4558  THROW_RUNTIME_ERROR("Input file could not be opened:\n\t" + inFilename);
4559  }
4560 
4561  uint32 counter = 0;
4562  for (auto value : *this)
4563  {
4564  ofile << value;
4565  if (counter++ != size_ - 1)
4566  {
4567  ofile << inSep;
4568  }
4569  }
4570  ofile.close();
4571  }
4572  }
4573 
4574  //============================================================================
4575  // Method Description:
4581  std::vector<dtype> toStlVector() const
4582  {
4583  return std::vector<dtype>(cbegin(), cend());
4584  }
4585 
4586  //============================================================================
4587  // Method Description:
4598  value_type trace(uint32 inOffset = 0, Axis inAxis = Axis::ROW) const noexcept
4599  {
4601 
4602  uint32 rowStart = 0;
4603  uint32 colStart = 0;
4604  switch (inAxis)
4605  {
4606  case Axis::ROW:
4607  {
4608  rowStart += inOffset;
4609  break;
4610  }
4611  case Axis::COL:
4612  {
4613  colStart += inOffset;
4614  break;
4615  }
4616  default:
4617  {
4618  // if the user input NONE, override back to ROW
4619  inAxis = Axis::ROW;
4620  break;
4621  }
4622  }
4623 
4624  if (rowStart >= shape_.rows || colStart >= shape_.cols)
4625  {
4626  return dtype{ 0 };
4627  }
4628 
4629  uint32 col = colStart;
4630  dtype sum = 0;
4631  for (uint32 row = rowStart; row < shape_.rows; ++row)
4632  {
4633  if (col >= shape_.cols)
4634  {
4635  break;
4636  }
4637  sum += operator()(row, col++);
4638  }
4639 
4640  return sum;
4641  }
4642 
4643  //============================================================================
4644  // Method Description:
4653  {
4654  NdArray<dtype> transArray(shape_.cols, shape_.rows);
4655  for (uint32 row = 0; row < shape_.rows; ++row)
4656  {
4657  for (uint32 col = 0; col < shape_.cols; ++col)
4658  {
4659  transArray(col, row) = operator()(row, col);
4660  }
4661  }
4662  return transArray;
4663  }
4664 
4665  //============================================================================
4666  // Method Description:
4670  NdArray<dtype>& zeros() noexcept
4671  {
4673 
4674  fill(dtype{ 0 });
4675  return *this;
4676  }
4677 
4678  private:
4679  //====================================Attributes==============================
4680  allocator_type allocator_{};
4681  Shape shape_{ 0, 0 };
4682  size_type size_{ 0 };
4683  Endian endianess_{ Endian::NATIVE };
4684  pointer array_{ nullptr };
4685  bool ownsPtr_{ false };
4686 
4687  //============================================================================
4688  // Method Description:
4691  void deleteArray() noexcept
4692  {
4693  if (ownsPtr_ && array_ != nullptr)
4694  {
4695  allocator_.deallocate(array_, size_);
4696  }
4697 
4698  array_ = nullptr;
4699  shape_.rows = shape_.cols = 0;
4700  size_ = 0;
4701  ownsPtr_ = false;
4702  endianess_ = Endian::NATIVE;
4703  }
4704 
4705  //============================================================================
4706  // Method Description:
4709  void newArray()
4710  {
4711  if (size_ > 0)
4712  {
4713  array_ = allocator_.allocate(size_);
4714  ownsPtr_ = true;
4715  }
4716  }
4717 
4718  //============================================================================
4719  // Method Description:
4725  void newArray(const Shape& inShape)
4726  {
4727  deleteArray();
4728 
4729  shape_ = inShape;
4730  size_ = inShape.size();
4731  newArray();
4732  }
4733  };
4734 
4735  // NOTE: this needs to be defined outside of the class to get rid of a compiler
4736  // error in Visual Studio
4737  template<typename dtype, class _Alloc>
4738  std::pair<NdArray<uint32>, NdArray<uint32>> NdArray<dtype, _Alloc>::nonzero() const
4739  {
4741 
4742  std::vector<uint32> rowIndices;
4743  std::vector<uint32> colIndices;
4744 
4745  for (uint32 row = 0; row < shape_.rows; ++row)
4746  {
4747  for (uint32 col = 0; col < shape_.cols; ++col)
4748  {
4749  if (operator()(row, col) != dtype{ 0 })
4750  {
4751  rowIndices.push_back(row);
4752  colIndices.push_back(col);
4753  }
4754  }
4755  }
4756 
4757  return std::make_pair(NdArray<uint32>(rowIndices), NdArray<uint32>(colIndices));
4758  }
4759 } // namespace nc
nc::NdArray::rcolend
const_reverse_column_iterator rcolend() const noexcept
Definition: NdArrayCore.hpp:1719
STATIC_ASSERT_INTEGER
#define STATIC_ASSERT_INTEGER(dtype)
Definition: StaticAsserts.hpp:40
nc::NdArray< dtype >::const_reverse_column_iterator
std::reverse_iterator< const_column_iterator > const_reverse_column_iterator
Definition: NdArrayCore.hpp:98
StaticAsserts.hpp
nc::NdArray::crbegin
const_reverse_iterator crbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1329
nc::enable_if_t
typename std::enable_if< B, T >::type enable_if_t
Definition: TypeTraits.hpp:40
nc::NdArray::item
value_type item() const
Definition: NdArrayCore.hpp:2975
nc::NdArray::colbegin
column_iterator colbegin(size_type inCol)
Definition: NdArrayCore.hpp:1187
nc::NdArray::contains
NdArray< bool > contains(value_type inValue, Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2365
nc::Slice::stop
int32 stop
Definition: Slice.hpp:48
nc::NdArray::put
NdArray< dtype > & put(int32 inRowIndex, const Slice &inColSlice, value_type inValue)
Definition: NdArrayCore.hpp:3906
nc::NdArray::cend
const_iterator cend(size_type inRow) const
Definition: NdArrayCore.hpp:1501
nc::NdArray::any
NdArray< bool > any(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1836
nc::NdArray::toStlVector
std::vector< dtype > toStlVector() const
Definition: NdArrayCore.hpp:4581
nc::NdArray::shape
Shape shape() const noexcept
Definition: NdArrayCore.hpp:4356
nc::Axis::NONE
@ NONE
nc::int32
std::int32_t int32
Definition: Types.hpp:36
nc::NdArray::operator=
NdArray< dtype > & operator=(NdArray< dtype > &&rhs) noexcept
Definition: NdArrayCore.hpp:614
nc::NdArrayColumnIterator
Custom column iterator for NdArray.
Definition: NdArrayIterators.hpp:827
nc::NdArray::cbegin
const_iterator cbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1157
nc::NdArray< dtype >::reverse_column_iterator
std::reverse_iterator< column_iterator > reverse_column_iterator
Definition: NdArrayCore.hpp:97
nc::NdArray::NdArray
NdArray(const NdArray< dtype > &inOtherArray)
Definition: NdArrayCore.hpp:519
nc::Slice::makePositiveAndValidate
void makePositiveAndValidate(uint32 inArraySize)
Definition: Slice.hpp:137
Error.hpp
STATIC_ASSERT_ARITHMETIC
#define STATIC_ASSERT_ARITHMETIC(dtype)
Definition: StaticAsserts.hpp:37
nc::Axis::ROW
@ ROW
nc::NdArray::dot
NdArray< dtype > dot(const NdArray< dtype > &inOtherArray) const
Definition: NdArrayCore.hpp:2661
nc::NdArray::sort
NdArray< dtype > & sort(Axis inAxis=Axis::NONE)
Definition: NdArrayCore.hpp:4386
nc::Endian::BIG
@ BIG
nc::NdArray::NdArray
NdArray()=default
StdComplexOperators.hpp
nc::NdArray::operator[]
reference operator[](int32 inIndex) noexcept
Definition: NdArrayCore.hpp:642
nc::NdArray::put
NdArray< dtype > & put(const Slice &inRowSlice, const Slice &inColSlice, value_type inValue)
Definition: NdArrayCore.hpp:3852
nc::NdArray::round
NdArray< dtype > round(uint8 inNumDecimals=0) const
Definition: NdArrayCore.hpp:4318
nc::NdArray::copy
NdArray< dtype > copy() const
Definition: NdArrayCore.hpp:2414
Endian.hpp
nc::NdArray::at
NdArray< dtype > at(int32 inRowIndex, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:1074
nc::NdArray::back
reference back(size_type row)
Definition: NdArrayCore.hpp:2253
nc::NdArray::nans
NdArray< dtype > & nans() noexcept
Definition: NdArrayCore.hpp:3210
nc::NdArray::begin
const_iterator begin() const noexcept
Definition: NdArrayCore.hpp:1117
nc::NdArray::at
reference at(int32 inIndex)
Definition: NdArrayCore.hpp:916
nc::NdArray::operator()
NdArray< dtype > operator()(const Slice &inRowSlice, int32 inColIndex) const
Definition: NdArrayCore.hpp:837
nc::NdArray::trace
value_type trace(uint32 inOffset=0, Axis inAxis=Axis::ROW) const noexcept
Definition: NdArrayCore.hpp:4598
nc::NdArray::at
NdArray< dtype > at(const Slice &inRowSlice, int32 inColIndex) const
Definition: NdArrayCore.hpp:1058
nc::NdArray::NdArray
NdArray(std::vector< std::array< dtype, Dim1Size >> &in2dArray, bool copy=true)
Definition: NdArrayCore.hpp:326
nc::NdArray::NdArray
NdArray(std::array< dtype, ArraySize > &inArray, bool copy=true)
Definition: NdArrayCore.hpp:209
nc::NdArray::operator[]
NdArray< dtype > operator[](const NdArray< bool > &inMask) const
Definition: NdArrayCore.hpp:752
nc::NdArray::reshape
NdArray< dtype > & reshape(const Shape &inShape)
Definition: NdArrayCore.hpp:4213
nc::resizeSlow
NdArray< dtype > & resizeSlow(NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition: resizeSlow.hpp:53
Constants.hpp
nc::NdArray::crcolbegin
const_reverse_column_iterator crcolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1415
nc::NdArray::resizeSlow
NdArray< dtype > & resizeSlow(const Shape &inShape)
Definition: NdArrayCore.hpp:4301
nc::NdArray::NdArray
NdArray(const std::initializer_list< dtype > &inList)
Definition: NdArrayCore.hpp:155
nc::NdArray< dtype >::const_reference
const dtype & const_reference
Definition: NdArrayCore.hpp:86
nc::uint8
std::uint8_t uint8
Definition: Types.hpp:42
nc::NdArray::reshape
NdArray< dtype > & reshape(size_type inSize)
Definition: NdArrayCore.hpp:4133
nc::uint64
std::uint64_t uint64
Definition: Types.hpp:39
nc::NdArray::put
NdArray< dtype > & put(int32 inRowIndex, const Slice &inColSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3986
nc::NdArray::tofile
void tofile(const std::string &inFilename, const std::string &inSep="") const
Definition: NdArrayCore.hpp:4539
nc::utils::num2str
std::string num2str(dtype inNumber)
Definition: num2str.hpp:46
nc::NdArray::issquare
bool issquare() const noexcept
Definition: NdArrayCore.hpp:2961
nc::NdArray::prod
NdArray< dtype > prod(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3617
nc::NdArray::diagonal
NdArray< dtype > diagonal(int32 inOffset=0, Axis inAxis=Axis::ROW) const
Definition: NdArrayCore.hpp:2591
nc::NdArray::operator=
NdArray< dtype > & operator=(const NdArray< dtype > &rhs)
Definition: NdArrayCore.hpp:569
STATIC_ASSERT_ARITHMETIC_OR_COMPLEX
#define STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype)
Definition: StaticAsserts.hpp:50
nc::NdArray::putMask
NdArray< dtype > & putMask(const NdArray< bool > &inMask, value_type inValue)
Definition: NdArrayCore.hpp:4008
nc::NdArray::rend
const_reverse_iterator rend() const noexcept
Definition: NdArrayCore.hpp:1547
nc::NdArray::const_column_iterator
NdArrayConstColumnIterator< dtype, size_type, const_pointer, difference_type > const_column_iterator
Definition: NdArrayCore.hpp:96
nc::NdArray::at
const_reference at(int32 inRowIndex, int32 inColIndex) const
Definition: NdArrayCore.hpp:994
nc::NdArray::transpose
NdArray< dtype > transpose() const
Definition: NdArrayCore.hpp:4652
nc::NdArray::nbytes
uint64 nbytes() const noexcept
Definition: NdArrayCore.hpp:3227
nc::NdArray::getByMask
NdArray< dtype > getByMask(const NdArray< bool > &inMask) const
Definition: NdArrayCore.hpp:2872
nc::NdArray< dtype >::size_type
uint32 size_type
Definition: NdArrayCore.hpp:87
nc::NdArray::ccolend
const_column_iterator ccolend() const noexcept
Definition: NdArrayCore.hpp:1659
nc::NdArray::crend
const_reverse_iterator crend(size_type inRow) const
Definition: NdArrayCore.hpp:1587
nc::dump
void dump(const NdArray< dtype > &inArray, const std::string &inFilename)
Definition: dump.hpp:47
nc::NdArray::at
const_reference at(int32 inIndex) const
Definition: NdArrayCore.hpp:939
nc::NdArray::max
NdArray< dtype > max(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2996
nc::NdArray::NdArray
NdArray(const std::initializer_list< std::initializer_list< dtype > > &inList)
Definition: NdArrayCore.hpp:173
nc::NdArray< dtype >::const_pointer
typename AllocTraits::const_pointer const_pointer
Definition: NdArrayCore.hpp:84
nc::NdArray
Holds 1D and 2D arrays, the main work horse of the NumCpp library.
Definition: NdArrayCore.hpp:71
nc::NdArray::put
NdArray< dtype > & put(const NdArray< uint32 > &inIndices, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3781
nc::NdArray::end
iterator end(size_type inRow)
Definition: NdArrayCore.hpp:1445
nc::NdArray::front
value_type front() const noexcept
Definition: NdArrayCore.hpp:2806
nc::NdArray::back
value_type back(size_type row) const
Definition: NdArrayCore.hpp:2241
nc::NdArray::rcolend
reverse_column_iterator rcolend(size_type inCol)
Definition: NdArrayCore.hpp:1703
nc::NdArray::put
NdArray< dtype > & put(const Slice &inRowSlice, const Slice &inColSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3930
nc::NdArray::back
value_type back() const noexcept
Definition: NdArrayCore.hpp:2217
nc::NdArray::ownsInternalData
bool ownsInternalData() noexcept
Definition: NdArrayCore.hpp:3512
nc::NdArray::front
reference front() noexcept
Definition: NdArrayCore.hpp:2818
nc::NdArray< dtype >::const_reverse_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: NdArrayCore.hpp:93
nc::NdArray::at
NdArray< dtype > at(const Slice &inSlice) const
Definition: NdArrayCore.hpp:1026
nc::stl_algorithms::transform
OutputIt transform(InputIt first, InputIt last, OutputIt destination, UnaryOperation unaryFunction)
Definition: StlAlgorithms.hpp:702
nc::stl_algorithms::for_each
void for_each(InputIt first, InputIt last, UnaryFunction f)
Definition: StlAlgorithms.hpp:213
nc::NdArray::clip
NdArray< dtype > clip(value_type inMin, value_type inMax) const
Definition: NdArrayCore.hpp:2311
nc::constants::j
constexpr auto j
Definition: Constants.hpp:45
nc::uint32
std::uint32_t uint32
Definition: Types.hpp:40
nc::NdArray::rSlice
Slice rSlice(int32 inStartIdx=0, uint32 inStepSize=1) const noexcept
Definition: NdArrayCore.hpp:902
nc::NdArray::NdArray
NdArray(std::vector< dtype > &inVector, bool copy=true)
Definition: NdArrayCore.hpp:266
nc::stl_algorithms::is_sorted
bool is_sorted(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:231
nc::NdArray< dtype >::allocator_type
std::allocator< dtype > allocator_type
Definition: NdArrayCore.hpp:82
nc::NdArray::crend
const_reverse_iterator crend() const noexcept
Definition: NdArrayCore.hpp:1573
nc::NdArray::colend
const_column_iterator colend(size_type inCol) const
Definition: NdArrayCore.hpp:1647
nc::NdArray::cSlice
Slice cSlice(int32 inStartIdx=0, uint32 inStepSize=1) const noexcept
Definition: NdArrayCore.hpp:887
nc::NdArray::numCols
uint32 numCols() const noexcept
Definition: NdArrayCore.hpp:3475
nc::NdArray::iterator
NdArrayIterator< dtype, pointer, difference_type > iterator
Definition: NdArrayCore.hpp:90
nc::NdArrayConstColumnIterator
Custom column const_iterator for NdArray.
Definition: NdArrayIterators.hpp:496
nc::NdArray::str
std::string str() const
Definition: NdArrayCore.hpp:4433
nc::NdArray::colend
column_iterator colend() noexcept
Definition: NdArrayCore.hpp:1603
nc::NdArray::newbyteorder
NdArray< dtype > newbyteorder(Endian inEndianess) const
Definition: NdArrayCore.hpp:3244
num2str.hpp
nc::endian::isLittleEndian
bool isLittleEndian() noexcept
Definition: Endian.hpp:44
nc::NdArray::dataRelease
pointer dataRelease() noexcept
Definition: NdArrayCore.hpp:2574
nc::Shape
A Shape Class for NdArrays.
Definition: Core/Shape.hpp:40
nc::stl_algorithms::max_element
ForwardIt max_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:268
nc::NdArray::put
NdArray< dtype > & put(int32 inIndex, value_type inValue)
Definition: NdArrayCore.hpp:3729
nc::NdArray::reshape
NdArray< dtype > & reshape(int32 inNumRows, int32 inNumCols)
Definition: NdArrayCore.hpp:4160
nc::stl_algorithms::all_of
bool all_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:57
nc::NdArray::ccolbegin
const_column_iterator ccolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1243
nc::Slice::start
int32 start
Definition: Slice.hpp:47
nc::stl_algorithms::fill
void fill(ForwardIt first, ForwardIt last, const T &value) noexcept
Definition: StlAlgorithms.hpp:174
STATIC_ASSERT_FLOAT
#define STATIC_ASSERT_FLOAT(dtype)
Definition: StaticAsserts.hpp:43
nc::NdArray::column
NdArray< dtype > column(uint32 inColumn)
Definition: NdArrayCore.hpp:2351
nc::stl_algorithms::copy
OutputIt copy(InputIt first, InputIt last, OutputIt destination) noexcept
Definition: StlAlgorithms.hpp:95
nc::NdArray::isflat
bool isflat() const noexcept
Definition: NdArrayCore.hpp:2898
nc::NdArray::end
const_iterator end() const noexcept
Definition: NdArrayCore.hpp:1461
nc::NdArray::rend
const_reverse_iterator rend(size_type inRow) const
Definition: NdArrayCore.hpp:1561
nc::NdArray::NdArray
NdArray(const Shape &inShape)
Definition: NdArrayCore.hpp:141
nc::NdArray::colbegin
column_iterator colbegin() noexcept
Definition: NdArrayCore.hpp:1173
nc::NdArray::colend
column_iterator colend(size_type inCol)
Definition: NdArrayCore.hpp:1617
nc::NdArray::end
iterator end() noexcept
Definition: NdArrayCore.hpp:1431
nc::put
NdArray< dtype > & put(NdArray< dtype > &inArray, const NdArray< uint32 > &inIndices, dtype inValue)
Definition: put.hpp:49
nc::Endian
Endian
Enum for endianess.
Definition: Types.hpp:50
nc::NdArray::rbegin
const_reverse_iterator rbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1303
nc::NdArray::NdArray
NdArray(const_pointer inPtr, uint32 numRows, uint32 numCols)
Definition: NdArrayCore.hpp:462
nc::NdArray::size
size_type size() const noexcept
Definition: NdArrayCore.hpp:4370
nc::Shape::cols
uint32 cols
Definition: Core/Shape.hpp:45
nc::NdArray::rcolend
reverse_column_iterator rcolend() noexcept
Definition: NdArrayCore.hpp:1689
nc::NdArray::repeat
NdArray< dtype > repeat(const Shape &inRepeatShape) const
Definition: NdArrayCore.hpp:4103
nc::reshape
NdArray< dtype > & reshape(NdArray< dtype > &inArray, uint32 inSize)
Definition: reshape.hpp:52
nc::NdArray::dump
void dump(const std::string &inFilename) const
Definition: NdArrayCore.hpp:2705
nc::NdArray::sum
NdArray< dtype > sum(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:4471
nc::NdArray::swapaxes
NdArray< dtype > swapaxes() const
Definition: NdArrayCore.hpp:4521
nc::Shape::size
uint32 size() const noexcept
Definition: Core/Shape.hpp:102
nc::sum
NdArray< dtype > sum(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition: sum.hpp:47
nc::NdArray::rbegin
const_reverse_iterator rbegin() const noexcept
Definition: NdArrayCore.hpp:1289
nc::NdArray< dtype >::reference
dtype & reference
Definition: NdArrayCore.hpp:85
nc::NdArray::operator=
NdArray< dtype > & operator=(value_type inValue) noexcept
Definition: NdArrayCore.hpp:595
nc::NdArray::put
NdArray< dtype > & put(const Slice &inRowSlice, int32 inColIndex, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3961
nc::NdArray::rcolbegin
reverse_column_iterator rcolbegin() noexcept
Definition: NdArrayCore.hpp:1345
nc::NdArray::cend
const_iterator cend() const noexcept
Definition: NdArrayCore.hpp:1487
nc::NdArray::NdArray
NdArray(NdArray< dtype > &&inOtherArray) noexcept
Definition: NdArrayCore.hpp:538
nc::NdArray::rcolend
const_reverse_column_iterator rcolend(size_type inCol) const
Definition: NdArrayCore.hpp:1733
nc::Slice::numElements
uint32 numElements(uint32 inArraySize)
Definition: Slice.hpp:188
nc::Axis
Axis
Enum To describe an axis.
Definition: Types.hpp:46
nc::stl_algorithms::find
InputIt find(InputIt first, InputIt last, const T &value) noexcept
Definition: StlAlgorithms.hpp:195
THROW_RUNTIME_ERROR
#define THROW_RUNTIME_ERROR(msg)
Definition: Error.hpp:37
nc::NdArray::put
NdArray< dtype > & put(const Slice &inRowSlice, int32 inColIndex, value_type inValue)
Definition: NdArrayCore.hpp:3882
nc::stl_algorithms::nth_element
void nth_element(RandomIt first, RandomIt nth, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:397
nc::NdArray< dtype >::reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
Definition: NdArrayCore.hpp:92
nc::constants::nan
const double nan
NaN.
Definition: Constants.hpp:44
power.hpp
nc::NdArray::rend
reverse_iterator rend(size_type inRow)
Definition: NdArrayCore.hpp:1531
nc::Slice::step
int32 step
Definition: Slice.hpp:49
nc::NdArray::put
NdArray< dtype > & put(const Slice &inSlice, value_type inValue)
Definition: NdArrayCore.hpp:3806
nc::NdArray::zeros
NdArray< dtype > & zeros() noexcept
Definition: NdArrayCore.hpp:4670
Shape.hpp
nc::NdArray::flatten
NdArray< dtype > flatten() const
Definition: NdArrayCore.hpp:2792
nc::NdArray::put
NdArray< dtype > & put(const Slice &inSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3828
Filesystem.hpp
nc::NdArray::cumsum
NdArray< dtype > cumsum(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2494
nc::NdArray::ones
NdArray< dtype > & ones() noexcept
Definition: NdArrayCore.hpp:3498
nc::NdArray::NdArray
NdArray(const std::deque< dtype > &inDeque)
Definition: NdArrayCore.hpp:353
nc::NdArray< dtype >::value_type
dtype value_type
Definition: NdArrayCore.hpp:81
nc::NdArray::endianess
Endian endianess() const noexcept
Definition: NdArrayCore.hpp:2733
nc::NdArray::NdArray
NdArray(size_type inSquareSize)
Definition: NdArrayCore.hpp:113
nc
Definition: Coordinate.hpp:44
nc::NdArray::ccolbegin
const_column_iterator ccolbegin() const noexcept
Definition: NdArrayCore.hpp:1229
nc::stl_algorithms::any_of
bool any_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:76
nc::NdArray::data
pointer data() noexcept
Definition: NdArrayCore.hpp:2552
nc::NdArray::ccolend
const_column_iterator ccolend(size_type inCol) const
Definition: NdArrayCore.hpp:1673
nc::NdArray::crcolbegin
const_reverse_column_iterator crcolbegin() const noexcept
Definition: NdArrayCore.hpp:1401
nc::NdArray::rend
reverse_iterator rend() noexcept
Definition: NdArrayCore.hpp:1517
nc::endian::byteSwap
dtype byteSwap(dtype value) noexcept
Definition: Endian.hpp:63
nc::NdArray::at
reference at(int32 inRowIndex, int32 inColIndex)
Definition: NdArrayCore.hpp:962
nc::Shape::rows
uint32 rows
Definition: Core/Shape.hpp:44
nc::NdArray::operator()
NdArray< dtype > operator()(int32 inRowIndex, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:862
nc::NdArray::argmin
NdArray< uint32 > argmin(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1953
sqr.hpp
nc::int64
std::int64_t int64
Definition: Types.hpp:35
DtypeInfo.hpp
nc::stl_algorithms::replace
void replace(ForwardIt first, ForwardIt last, const T &oldValue, const T &newValue) noexcept
Definition: StlAlgorithms.hpp:435
nc::NdArrayConstIterator
Custom const_iterator for NdArray.
Definition: NdArrayIterators.hpp:42
nc::NdArray::operator[]
NdArray< dtype > operator[](const Slice &inSlice) const
Definition: NdArrayCore.hpp:729
nc::NdArray::row
NdArray< dtype > row(uint32 inRow)
Definition: NdArrayCore.hpp:4342
nc::NdArray::column_iterator
NdArrayColumnIterator< dtype, size_type, pointer, difference_type > column_iterator
Definition: NdArrayCore.hpp:95
nc::NdArray::NdArray
NdArray(pointer inPtr, uint32 numRows, uint32 numCols, Bool takeOwnership) noexcept
Definition: NdArrayCore.hpp:505
nc::NdArray::argsort
NdArray< uint32 > argsort(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2012
nc::NdArray::getByIndices
NdArray< dtype > getByIndices(const NdArray< uint32 > &inIndices) const
Definition: NdArrayCore.hpp:2856
THROW_INVALID_ARGUMENT_ERROR
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:36
nc::NdArrayIterator
Custom iterator for NdArray.
Definition: NdArrayIterators.hpp:317
nc::NdArray::rbegin
reverse_iterator rbegin() noexcept
Definition: NdArrayCore.hpp:1259
nc::NdArray::put
NdArray< dtype > & put(int32 inRow, int32 inCol, value_type inValue)
Definition: NdArrayCore.hpp:3746
nc::utils::power
dtype power(dtype inValue, uint8 inPower) noexcept
Definition: Utils/power.hpp:48
nc::repeat
NdArray< dtype > repeat(const NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition: repeat.hpp:50
nc::NdArray::cbegin
const_iterator cbegin() const noexcept
Definition: NdArrayCore.hpp:1143
nc::NdArray::cumprod
NdArray< dtype > cumprod(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2430
nc::stl_algorithms::sort
void sort(RandomIt first, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:629
StlAlgorithms.hpp
nc::NdArray::NdArray
NdArray(const std::deque< std::deque< dtype >> &in2dDeque)
Definition: NdArrayCore.hpp:370
nc::resizeFast
NdArray< dtype > & resizeFast(NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition: resizeFast.hpp:51
nc::NdArray::end
const_iterator end(size_type inRow) const
Definition: NdArrayCore.hpp:1475
nc::NdArray::back
reference back() noexcept
Definition: NdArrayCore.hpp:2229
nc::NdArray::astype
NdArray< dtypeOut > astype() const
Definition: NdArrayCore.hpp:2098
nc::NdArray::const_iterator
NdArrayConstIterator< dtype, const_pointer, difference_type > const_iterator
Definition: NdArrayCore.hpp:91
nc::NdArray::colbegin
const_column_iterator colbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1217
nc::NdArray::NdArray
NdArray(const std::vector< std::vector< dtype >> &in2dVector)
Definition: NdArrayCore.hpp:291
nc::stl_algorithms::min_element
ForwardIt min_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:304
nc::NdArray::resizeFast
NdArray< dtype > & resizeFast(uint32 inNumRows, uint32 inNumCols)
Definition: NdArrayCore.hpp:4228
nc::NdArray::colbegin
const_column_iterator colbegin() const noexcept
Definition: NdArrayCore.hpp:1203
nc::NdArray::operator()
const_reference operator()(int32 inRowIndex, int32 inColIndex) const noexcept
Definition: NdArrayCore.hpp:704
nc::NdArray::crcolend
const_reverse_column_iterator crcolend(size_type inCol) const
Definition: NdArrayCore.hpp:1759
nc::NdArray::argmax
NdArray< uint32 > argmax(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1893
nc::NdArray::flatnonzero
NdArray< uint32 > flatnonzero() const
Definition: NdArrayCore.hpp:2765
nc::NdArray::replace
void replace(value_type oldValue, value_type newValue)
Definition: NdArrayCore.hpp:4115
value2str.hpp
nc::NdArray::operator()
reference operator()(int32 inRowIndex, int32 inColIndex) noexcept
Definition: NdArrayCore.hpp:680
nc::stl_algorithms::stable_sort
void stable_sort(RandomIt first, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:664
nc::NdArray::putMask
NdArray< dtype > & putMask(const NdArray< bool > &inMask, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:4025
nc::NdArray::rcolbegin
const_reverse_column_iterator rcolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1389
nc::NdArray::none
NdArray< bool > none(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3409
nc::stl_algorithms::minmax_element
std::pair< ForwardIt, ForwardIt > minmax_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:341
nc::NdArray::isempty
bool isempty() const noexcept
Definition: NdArrayCore.hpp:2885
nc::NdArray::front
value_type front(size_type row) const
Definition: NdArrayCore.hpp:2830
nc::NdArray::crbegin
const_reverse_iterator crbegin() const noexcept
Definition: NdArrayCore.hpp:1315
Types.hpp
nc::NdArray::rcolbegin
const_reverse_column_iterator rcolbegin() const noexcept
Definition: NdArrayCore.hpp:1375
nc::NdArray::NdArray
NdArray(pointer inPtr, size_type size, Bool takeOwnership) noexcept
Definition: NdArrayCore.hpp:485
nc::NdArray::numRows
uint32 numRows() const noexcept
Definition: NdArrayCore.hpp:3488
nc::NdArray::front
reference front(size_type row)
Definition: NdArrayCore.hpp:2842
nc::NdArray::begin
iterator begin() noexcept
Definition: NdArrayCore.hpp:1087
nc::nonzero
std::pair< NdArray< uint32 >, NdArray< uint32 > > nonzero(const NdArray< dtype > &inArray)
Definition: nonzero.hpp:50
nc::NdArray::at
NdArray< dtype > at(const Slice &inRowSlice, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:1042
nc::Axis::COL
@ COL
nc::random::f
dtype f(dtype inDofN, dtype inDofD)
Definition: f.hpp:56
nc::utils::value2str
std::string value2str(dtype inValue)
Definition: value2str.hpp:48
nc::NdArray::rbegin
reverse_iterator rbegin(size_type inRow)
Definition: NdArrayCore.hpp:1273
nc::NdArray::rcolbegin
reverse_column_iterator rcolbegin(size_type inCol)
Definition: NdArrayCore.hpp:1359
nc::Slice
A Class for slicing into NdArrays.
Definition: Slice.hpp:43
nc::NdArray::resizeFast
NdArray< dtype > & resizeFast(const Shape &inShape)
Definition: NdArrayCore.hpp:4244
nc::NdArray::ptp
NdArray< dtype > ptp(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3672
nc::NdArray::NdArray
NdArray(const std::list< dtype > &inList)
Definition: NdArrayCore.hpp:403
nc::NdArray::operator[]
const_reference operator[](int32 inIndex) const noexcept
Definition: NdArrayCore.hpp:661
nc::NdArray::data
const_pointer data() const noexcept
Definition: NdArrayCore.hpp:2562
nc::NdArray::operator[]
NdArray< dtype > operator[](const NdArray< size_type > &inIndices) const
Definition: NdArrayCore.hpp:778
nc::NdArray::NdArray
NdArray(std::array< std::array< dtype, Dim1Size >, Dim0Size > &in2dArray, bool copy=true)
Definition: NdArrayCore.hpp:237
nc::NdArray::NdArray
NdArray(const_pointer inPtr, size_type size)
Definition: NdArrayCore.hpp:442
nc::stl_algorithms::none_of
bool none_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:379
nc::NdArray< dtype >::pointer
typename AllocTraits::pointer pointer
Definition: NdArrayCore.hpp:83
nc::NdArray::colend
const_column_iterator colend() const noexcept
Definition: NdArrayCore.hpp:1633
nc::NdArray::partition
NdArray< dtype > & partition(uint32 inKth, Axis inAxis=Axis::NONE)
Definition: NdArrayCore.hpp:3533
nc::NdArray::issorted
NdArray< bool > issorted(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2910
NdArrayIterators.hpp
nc::NdArray::crcolend
const_reverse_column_iterator crcolend() const noexcept
Definition: NdArrayCore.hpp:1745
nc::NdArray::fill
NdArray< dtype > & fill(value_type inFillValue) noexcept
Definition: NdArrayCore.hpp:2751
nc::NdArray::NdArray
NdArray(Iterator inFirst, Iterator inLast)
Definition: NdArrayCore.hpp:423
nc::Endian::LITTLE
@ LITTLE
nc::Endian::NATIVE
@ NATIVE
nc::NdArray::all
NdArray< bool > all(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1780
nc::NdArray::~NdArray
~NdArray() noexcept
Definition: NdArrayCore.hpp:555
nc::NdArray::begin
const_iterator begin(size_type inRow) const
Definition: NdArrayCore.hpp:1131
nc::NdArray::median
NdArray< dtype > median(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3112
TypeTraits.hpp
nc::NdArray::ravel
NdArray< dtype > & ravel() noexcept
Definition: NdArrayCore.hpp:4043
nc::NdArray::repeat
NdArray< dtype > repeat(uint32 inNumRows, uint32 inNumCols) const
Definition: NdArrayCore.hpp:4060
nc::NdArray< dtype >::difference_type
typename AllocTraits::difference_type difference_type
Definition: NdArrayCore.hpp:88
nc::NdArray::NdArray
NdArray(size_type inNumRows, size_type inNumCols)
Definition: NdArrayCore.hpp:127
nc::NdArray::byteswap
NdArray< dtype > & byteswap() noexcept
Definition: NdArrayCore.hpp:2267
nc::transpose
NdArray< dtype > transpose(const NdArray< dtype > &inArray)
Definition: transpose.hpp:47
nc::NdArray::print
void print() const
Definition: NdArrayCore.hpp:3599
Slice.hpp
nc::filesystem::File
Provides simple filesystem functions.
Definition: Filesystem.hpp:39
nc::NdArray::put
NdArray< dtype > & put(const NdArray< uint32 > &inIndices, value_type inValue)
Definition: NdArrayCore.hpp:3762
nc::NdArray::begin
iterator begin(size_type inRow)
Definition: NdArrayCore.hpp:1101
nc::abs
auto abs(dtype inValue) noexcept
Definition: abs.hpp:51
nc::NdArray::resizeSlow
NdArray< dtype > & resizeSlow(uint32 inNumRows, uint32 inNumCols)
Definition: NdArrayCore.hpp:4261
nc::NdArray::operator()
NdArray< dtype > operator()(const Slice &inRowSlice, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:805
nc::NdArray::min
NdArray< dtype > min(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3053