NumCpp  2.6.2
A Templatized Header Only C++ Implementation of the Python NumPy Library
NdArrayCore.hpp
Go to the documentation of this file.
1 
28 #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<is_same_v<typename std::iterator_traits<Iterator>::value_type, dtype>, int> = 0>
423  NdArray(Iterator inFirst, Iterator inLast) :
424  shape_(1, static_cast<uint32>(std::distance(inFirst, inLast))),
425  size_(shape_.size())
426  {
427  newArray();
428  if (size_ > 0)
429  {
430  stl_algorithms::copy(inFirst, inLast, begin());
431  }
432  }
433 
434  //============================================================================
435  // Method Description:
443  shape_(1, size),
444  size_(size)
445  {
446  newArray();
447  if (inPtr != nullptr && size_ > 0)
448  {
449  stl_algorithms::copy(inPtr, inPtr + size_, begin());
450  }
451  }
452 
453  //============================================================================
454  // Method Description:
462  template<typename UIntType1, typename UIntType2,
463  std::enable_if_t<!is_same_v<UIntType1, bool>, int> = 0,
464  std::enable_if_t<!is_same_v<UIntType2, bool>, int> = 0>
465  NdArray(const_pointer inPtr, UIntType1 numRows, UIntType2 numCols) :
466  shape_(numRows, numCols),
467  size_(shape_.size())
468  {
469  newArray();
470  if (inPtr != nullptr && size_ > 0)
471  {
472  stl_algorithms::copy(inPtr, inPtr + size_, begin());
473  }
474  }
475 
476  //============================================================================
477  // Method Description:
486  template<typename Bool,
487  std::enable_if_t<is_same_v<Bool, bool>, int> = 0>
488  NdArray(pointer inPtr, size_type size, Bool takeOwnership) noexcept :
489  shape_(1, size),
490  size_(size),
491  array_(inPtr),
492  ownsPtr_(takeOwnership)
493  {}
494 
495  //============================================================================
496  // Method Description:
506  template<typename Bool,
507  std::enable_if_t<is_same_v<Bool, bool>, int> = 0>
508  NdArray(pointer inPtr, uint32 numRows, uint32 numCols, Bool takeOwnership) noexcept :
509  shape_(numRows, numCols),
510  size_(numRows * numCols),
511  array_(inPtr),
512  ownsPtr_(takeOwnership)
513  {}
514 
515  //============================================================================
516  // Method Description:
522  NdArray(const NdArray<dtype>& inOtherArray) :
523  shape_(inOtherArray.shape_),
524  size_(inOtherArray.size_),
525  endianess_(inOtherArray.endianess_)
526  {
527  newArray();
528  if (size_ > 0)
529  {
530  stl_algorithms::copy(inOtherArray.cbegin(), inOtherArray.cend(), begin());
531  }
532  }
533 
534  //============================================================================
535  // Method Description:
541  NdArray(NdArray<dtype>&& inOtherArray) noexcept :
542  shape_(inOtherArray.shape_),
543  size_(inOtherArray.size_),
544  endianess_(inOtherArray.endianess_),
545  array_(inOtherArray.array_),
546  ownsPtr_(inOtherArray.ownsPtr_)
547  {
548  inOtherArray.shape_.rows = inOtherArray.shape_.cols = 0;
549  inOtherArray.size_ = 0;
550  inOtherArray.ownsPtr_ = false;
551  inOtherArray.array_ = nullptr;
552  }
553 
554  //============================================================================
555  // Method Description:
558  ~NdArray() noexcept
559  {
560  deleteArray();
561  }
562 
563  //============================================================================
564  // Method Description:
573  {
574  if (&rhs != this)
575  {
576  if (rhs.size_ > 0)
577  {
578  newArray(rhs.shape_);
579  endianess_ = rhs.endianess_;
580 
581  stl_algorithms::copy(rhs.cbegin(), rhs.cend(), begin());
582  }
583  }
584 
585  return *this;
586  }
587 
588  //============================================================================
589  // Method Description:
599  {
600  if (array_ != nullptr)
601  {
602  stl_algorithms::fill(begin(), end(), inValue);
603  }
604 
605  return *this;
606  }
607 
608  //============================================================================
609  // Method Description:
618  {
619  if (&rhs != this)
620  {
621  deleteArray();
622  shape_ = rhs.shape_;
623  size_ = rhs.size_;
624  endianess_ = rhs.endianess_;
625  array_ = rhs.array_;
626  ownsPtr_ = rhs.ownsPtr_;
627 
628  rhs.shape_.rows = rhs.shape_.cols = rhs.size_ = 0;
629  rhs.array_ = nullptr;
630  rhs.ownsPtr_ = false;
631  }
632 
633  return *this;
634  }
635 
636  //============================================================================
637  // Method Description:
645  reference operator[](int32 inIndex) noexcept
646  {
647  if (inIndex < 0)
648  {
649  inIndex += size_;
650  }
651 
652  return array_[inIndex];
653  }
654 
655  //============================================================================
656  // Method Description:
664  const_reference operator[](int32 inIndex) const noexcept
665  {
666  if (inIndex < 0)
667  {
668  inIndex += size_;
669  }
670 
671  return array_[inIndex];
672  }
673 
674  //============================================================================
675  // Method Description:
683  reference operator()(int32 inRowIndex, int32 inColIndex) noexcept
684  {
685  if (inRowIndex < 0)
686  {
687  inRowIndex += shape_.rows;
688  }
689 
690  if (inColIndex < 0)
691  {
692  inColIndex += shape_.cols;
693  }
694 
695  return array_[inRowIndex * shape_.cols + inColIndex];
696  }
697 
698  //============================================================================
699  // Method Description:
707  const_reference operator()(int32 inRowIndex, int32 inColIndex) const noexcept
708  {
709  if (inRowIndex < 0)
710  {
711  inRowIndex += shape_.rows;
712  }
713 
714  if (inColIndex < 0)
715  {
716  inColIndex += shape_.cols;
717  }
718 
719  return array_[inRowIndex * shape_.cols + inColIndex];
720  }
721 
722  //============================================================================
723  // Method Description:
732  NdArray<dtype> operator[](const Slice& inSlice) const
733  {
734  Slice inSliceCopy(inSlice);
735 
736  uint32 counter = 0;
737  NdArray<dtype> returnArray(1, inSliceCopy.numElements(size_));
738  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
739  {
740  returnArray[counter++] = at(i);
741  }
742 
743  return returnArray;
744  }
745 
746  //============================================================================
747  // Method Description:
756  {
757  if (inMask.shape() != shape_)
758  {
759  THROW_INVALID_ARGUMENT_ERROR("input inMask must have the same shape as the NdArray it will be masking.");
760  }
761 
762  auto indices = inMask.flatnonzero();
763  auto outArray = NdArray<dtype>(1, indices.size());
764  for (size_type i = 0; i < indices.size(); ++i)
765  {
766  outArray[i] = operator[](indices[i]);
767  }
768 
769  return outArray;
770  }
771 
772  //============================================================================
773  // Method Description:
782  template<typename Indices,
784  NdArray<dtype> operator[](const Indices& inIndices) const
785  {
786  if (inIndices.max().item() > size_ - 1)
787  {
788  THROW_INVALID_ARGUMENT_ERROR("input indices must be less than the array size.");
789  }
790 
791  auto outArray = NdArray<dtype>(1, static_cast<size_type>(inIndices.size()));
792  size_type i = 0;
793  for (auto& index : inIndices)
794  {
795  outArray[i++] = operator[](index);
796  }
797 
798  return outArray;
799  }
800 
801  //============================================================================
802  // Method Description:
811  NdArray<dtype> operator()(Slice inRowSlice, Slice inColSlice) const
812  {
813  NdArray<dtype> returnArray(inRowSlice.numElements(shape_.rows), inColSlice.numElements(shape_.cols));
814 
815  uint32 rowCounter = 0;
816  uint32 colCounter = 0;
817  for (int32 row = inRowSlice.start; row < inRowSlice.stop; row += inRowSlice.step)
818  {
819  for (int32 col = inColSlice.start; col < inColSlice.stop; col += inColSlice.step)
820  {
821  returnArray(rowCounter, colCounter++) = at(row, col);
822  }
823  colCounter = 0;
824  ++rowCounter;
825  }
826 
827  return returnArray;
828  }
829 
830  //============================================================================
831  // Method Description:
840  NdArray<dtype> operator()(Slice inRowSlice, int32 inColIndex) const
841  {
842  NdArray<dtype> returnArray(inRowSlice.numElements(shape_.rows), 1);
843 
844  uint32 rowCounter = 0;
845  for (int32 row = inRowSlice.start; row < inRowSlice.stop; row += inRowSlice.step)
846  {
847  returnArray(rowCounter++, 0) = at(row, inColIndex);
848  }
849 
850  return returnArray;
851  }
852 
853  //============================================================================
854  // Method Description:
863  NdArray<dtype> operator()(int32 inRowIndex, Slice inColSlice) const
864  {
865  NdArray<dtype> returnArray(1, inColSlice.numElements(shape_.cols));
866 
867  uint32 colCounter = 0;
868  for (int32 col = inColSlice.start; col < inColSlice.stop; col += inColSlice.step)
869  {
870  returnArray(0, colCounter++) = at(inRowIndex, col);
871  }
872 
873  return returnArray;
874  }
875 
876  //============================================================================
877  // Method Description:
886  template<typename Indices,
887  enable_if_t<is_same_v<Indices, NdArray<int32>> || is_same_v<Indices, NdArray<uint32>>, int> = 0>
888  NdArray<dtype> operator()(const Indices& rowIndices, int32 colIndex) const
889  {
890  const NdArray<int32> colIndices = { colIndex };
891  return operator()(rowIndices, colIndices);
892  }
893 
894  //============================================================================
895  // Method Description:
904  template<typename Indices,
905  enable_if_t<is_same_v<Indices, NdArray<int32>> || is_same_v<Indices, NdArray<uint32>>, int> = 0>
906  NdArray<dtype> operator()(const Indices& rowIndices, Slice colSlice) const
907  {
908  return operator()(rowIndices, toIndices(colSlice, Axis::COL));
909  }
910 
911  //============================================================================
912  // Method Description:
921  template<typename Indices,
922  enable_if_t<is_same_v<Indices, NdArray<int32>> || is_same_v<Indices, NdArray<uint32>>, int> = 0>
923  NdArray<dtype> operator()(int32 rowIndex, const Indices& colIndices) const
924  {
925  const NdArray<int32> rowIndices = { rowIndex };
926  return operator()(rowIndices, colIndices);
927  }
928 
929  //============================================================================
930  // Method Description:
939  template<typename Indices,
940  enable_if_t<is_same_v<Indices, NdArray<int32>> || is_same_v<Indices, NdArray<uint32>>, int> = 0>
941  NdArray<dtype> operator()(Slice rowSlice, const Indices& colIndices) const
942  {
943  return operator()(toIndices(rowSlice, Axis::ROW), colIndices);
944  }
945 
946  //============================================================================
947  // Method Description:
956  template<typename RowIndices, typename ColIndices,
957  enable_if_t<is_same_v<RowIndices, NdArray<int32>> || is_same_v<RowIndices, NdArray<uint32>>, int> = 0,
958  enable_if_t<is_same_v<ColIndices, NdArray<int32>> || is_same_v<ColIndices, NdArray<uint32>>, int> = 0>
959  NdArray<dtype> operator()(RowIndices rowIndices, ColIndices colIndices) const
960  {
961  rowIndices.sort();
962  colIndices.sort();
963 
964  std::vector<int32> rowIndicesUnique(rowIndices.size());
965  std::vector<int32> colIndicesUnique(colIndices.size());
966 
967  const auto lastRow = stl_algorithms::unique_copy(rowIndices.begin(), rowIndices.end(), rowIndicesUnique.begin());
968  const auto lastCol = stl_algorithms::unique_copy(colIndices.begin(), colIndices.end(), colIndicesUnique.begin());
969 
970  NdArray<dtype> returnArray(static_cast<uint32>(lastRow - rowIndicesUnique.begin()),
971  static_cast<uint32>(lastCol - colIndicesUnique.begin()));
972 
973  uint32 rowCounter = 0;
974  for (auto rowIter = rowIndicesUnique.begin(); rowIter != lastRow; ++rowIter)
975  {
976  uint32 colCounter = 0;
977  for (auto colIter = colIndicesUnique.begin(); colIter != lastCol; ++colIter)
978  {
979  returnArray(rowCounter, colCounter++) = at(*rowIter, *colIter);
980  }
981 
982  ++rowCounter;
983  }
984 
985  return returnArray;
986  }
987 
988  //============================================================================
989  // Method Description:
998  Slice cSlice(int32 inStartIdx = 0, uint32 inStepSize = 1) const noexcept
999  {
1000  return Slice(inStartIdx, shape_.cols, inStepSize);
1001  }
1002 
1003  //============================================================================
1004  // Method Description:
1013  Slice rSlice(int32 inStartIdx = 0, uint32 inStepSize = 1) const noexcept
1014  {
1015  return Slice(inStartIdx, shape_.rows, inStepSize);
1016  }
1017 
1018  //============================================================================
1019  // Method Description:
1027  reference at(int32 inIndex)
1028  {
1029  // this doesn't allow for calling the first element as -size_...
1030  // but why would you really want to do that anyway?
1031  if (std::abs(inIndex) > static_cast<int64>(size_ - 1))
1032  {
1033  std::string errStr = "Input index " + utils::num2str(inIndex);
1034  errStr += " is out of bounds for array of size " + utils::num2str(size_) + ".";
1036  }
1037 
1038  return operator[](inIndex);
1039  }
1040 
1041  //============================================================================
1042  // Method Description:
1050  const_reference at(int32 inIndex) const
1051  {
1052  // this doesn't allow for calling the first element as -size_...
1053  // but why would you really want to do that anyway?
1054  if (std::abs(inIndex) > static_cast<int64>(size_ - 1))
1055  {
1056  std::string errStr = "Input index " + utils::num2str(inIndex);
1057  errStr += " is out of bounds for array of size " + utils::num2str(size_) + ".";
1059  }
1060 
1061  return operator[](inIndex);
1062  }
1063 
1064  //============================================================================
1065  // Method Description:
1073  reference at(int32 inRowIndex, int32 inColIndex)
1074  {
1075  // this doesn't allow for calling the first element as -size_...
1076  // but why would you really want to do that anyway?
1077  if (std::abs(inRowIndex) > static_cast<int32>(shape_.rows - 1))
1078  {
1079  std::string errStr = "Row index " + utils::num2str(inRowIndex);
1080  errStr += " is out of bounds for array of size " + utils::num2str(shape_.rows) + ".";
1082  }
1083 
1084  // this doesn't allow for calling the first element as -size_...
1085  // but why would you really want to that anyway?
1086  if (std::abs(inColIndex) > static_cast<int32>(shape_.cols - 1))
1087  {
1088  std::string errStr = "Column index " + utils::num2str(inColIndex);
1089  errStr += " is out of bounds for array of size " + utils::num2str(shape_.cols) + ".";
1091  }
1092 
1093  return operator()(inRowIndex, inColIndex);
1094  }
1095 
1096  //============================================================================
1097  // Method Description:
1105  const_reference at(int32 inRowIndex, int32 inColIndex) const
1106  {
1107  // this doesn't allow for calling the first element as -size_...
1108  // but why would you really want to do that anyway?
1109  if (std::abs(inRowIndex) > static_cast<int32>(shape_.rows - 1))
1110  {
1111  std::string errStr = "Row index " + utils::num2str(inRowIndex);
1112  errStr += " is out of bounds for array of size " + utils::num2str(shape_.rows) + ".";
1114  }
1115 
1116  // this doesn't allow for calling the first element as -size_...
1117  // but why would you really want to do that anyway?
1118  if (std::abs(inColIndex) > static_cast<int32>(shape_.cols - 1))
1119  {
1120  std::string errStr = "Column index " + utils::num2str(inColIndex);
1121  errStr += " is out of bounds for array of size " + utils::num2str(shape_.cols) + ".";
1123  }
1124 
1125  return operator()(inRowIndex, inColIndex);
1126  }
1127 
1128  //============================================================================
1129  // Method Description:
1137  NdArray<dtype> at(const Slice& inSlice) const
1138  {
1139  // the slice operator already provides bounds checking. just including
1140  // the at method for completeness
1141  return operator[](inSlice);
1142  }
1143 
1144  //============================================================================
1145  // Method Description:
1153  NdArray<dtype> at(const Slice& inRowSlice, const Slice& inColSlice) const
1154  {
1155  // the slice operator already provides bounds checking. just including
1156  // the at method for completeness
1157  return operator()(inRowSlice, inColSlice);
1158  }
1159 
1160  //============================================================================
1161  // Method Description:
1169  NdArray<dtype> at(const Slice& inRowSlice, int32 inColIndex) const
1170  {
1171  // the slice operator already provides bounds checking. just including
1172  // the at method for completeness
1173  return operator()(inRowSlice, inColIndex);
1174  }
1175 
1176  //============================================================================
1177  // Method Description:
1185  NdArray<dtype> at(int32 inRowIndex, const Slice& inColSlice) const
1186  {
1187  // the slice operator already provides bounds checking. just including
1188  // the at method for completeness
1189  return operator()(inRowIndex, inColSlice);
1190  }
1191 
1192  //============================================================================
1193  // Method Description:
1201  NdArray<dtype> at(const NdArray<int32>& rowIndices, const NdArray<int32>& colIndices) const
1202  {
1203  // the slice operator already provides bounds checking. just including
1204  // the at method for completeness
1205  return operator()(rowIndices, colIndices);
1206  }
1207 
1208  //============================================================================
1209  // Method Description:
1214  iterator begin() noexcept
1215  {
1216  return iterator(array_);
1217  }
1218 
1219  //============================================================================
1220  // Method Description:
1229  {
1230  if (inRow >= shape_.rows)
1231  {
1232  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1233  }
1234 
1235  return begin() += (inRow * shape_.cols);
1236  }
1237 
1238  //============================================================================
1239  // Method Description:
1244  const_iterator begin() const noexcept
1245  {
1246  return cbegin();
1247  }
1248 
1249  //============================================================================
1250  // Method Description:
1259  {
1260  return cbegin(inRow);
1261  }
1262 
1263  //============================================================================
1264  // Method Description:
1270  const_iterator cbegin() const noexcept
1271  {
1272  return const_iterator(array_);
1273  }
1274 
1275  //============================================================================
1276  // Method Description:
1285  {
1286  if (inRow >= shape_.rows)
1287  {
1288  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1289  }
1290 
1291  return cbegin() += (inRow * shape_.cols);
1292  }
1293 
1294  //============================================================================
1295  // Method Description:
1301  {
1302  return column_iterator(array_, shape_.rows, shape_.cols);
1303  }
1304 
1305  //============================================================================
1306  // Method Description:
1315  {
1316  if (inCol >= shape_.cols)
1317  {
1318  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1319  }
1320 
1321  return colbegin() += (inCol * shape_.rows);
1322  }
1323 
1324  //============================================================================
1325  // Method Description:
1331  {
1332  return ccolbegin();
1333  }
1334 
1335  //============================================================================
1336  // Method Description:
1345  {
1346  return ccolbegin(inCol);
1347  }
1348 
1349  //============================================================================
1350  // Method Description:
1357  {
1358  return const_column_iterator(array_, shape_.rows, shape_.cols);
1359  }
1360 
1361  //============================================================================
1362  // Method Description:
1371  {
1372  if (inCol >= shape_.cols)
1373  {
1374  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1375  }
1376 
1377  return ccolbegin() += (inCol * shape_.rows);
1378  }
1379 
1380  //============================================================================
1381  // Method Description:
1387  {
1388  return reverse_iterator(end());
1389  }
1390 
1391  //============================================================================
1392  // Method Description:
1401  {
1402  if (inRow >= shape_.rows)
1403  {
1404  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1405  }
1406 
1407  return rbegin() += (shape_.rows - inRow - 1) * shape_.cols;
1408  }
1409 
1410  //============================================================================
1411  // Method Description:
1417  {
1418  return crbegin();
1419  }
1420 
1421  //============================================================================
1422  // Method Description:
1431  {
1432  return crbegin(inRow);
1433  }
1434 
1435  //============================================================================
1436  // Method Description:
1443  {
1444  return const_reverse_iterator(cend());
1445  }
1446 
1447  //============================================================================
1448  // Method Description:
1457  {
1458  if (inRow >= shape_.rows)
1459  {
1460  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1461  }
1462 
1463  return crbegin() += (shape_.rows - inRow - 1) * shape_.cols;
1464  }
1465 
1466  //============================================================================
1467  // Method Description:
1473  {
1474  return reverse_column_iterator(colend());
1475  }
1476 
1477  //============================================================================
1478  // Method Description:
1487  {
1488  if (inCol >= shape_.cols)
1489  {
1490  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1491  }
1492 
1493  return rcolbegin() += (shape_.cols - inCol - 1) * shape_.rows;
1494  }
1495 
1496  //============================================================================
1497  // Method Description:
1503  {
1504  return crcolbegin();
1505  }
1506 
1507  //============================================================================
1508  // Method Description:
1517  {
1518  return crcolbegin(inCol);
1519  }
1520 
1521  //============================================================================
1522  // Method Description:
1529  {
1531  }
1532 
1533  //============================================================================
1534  // Method Description:
1543  {
1544  if (inCol >= shape_.cols)
1545  {
1546  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1547  }
1548 
1549  return crcolbegin() += (shape_.cols - inCol - 1) * shape_.rows;
1550  }
1551 
1552  //============================================================================
1553  // Method Description:
1558  iterator end() noexcept
1559  {
1560  return begin() += size_;
1561  }
1562 
1563  //============================================================================
1564  // Method Description:
1573  {
1574  if (inRow >= shape_.rows)
1575  {
1576  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1577  }
1578 
1579  return begin(inRow) += shape_.cols;
1580  }
1581 
1582  //============================================================================
1583  // Method Description:
1588  const_iterator end() const noexcept
1589  {
1590  return cend();
1591  }
1592 
1593  //============================================================================
1594  // Method Description:
1603  {
1604  return cend(inRow);
1605  }
1606 
1607  //============================================================================
1608  // Method Description:
1614  const_iterator cend() const noexcept
1615  {
1616  return cbegin() += size_;
1617  }
1618 
1619  //============================================================================
1620  // Method Description:
1629  {
1630  if (inRow >= shape_.rows)
1631  {
1632  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1633  }
1634 
1635  return cbegin(inRow) += shape_.cols;
1636  }
1637 
1638  //============================================================================
1639  // Method Description:
1645  {
1646  return rbegin() += size_;
1647  }
1648 
1649  //============================================================================
1650  // Method Description:
1659  {
1660  if (inRow >= shape_.rows)
1661  {
1662  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1663  }
1664 
1665  return rbegin(inRow) += shape_.cols;
1666  }
1667 
1668  //============================================================================
1669  // Method Description:
1674  const_reverse_iterator rend() const noexcept
1675  {
1676  return crend();
1677  }
1678 
1679  //============================================================================
1680  // Method Description:
1689  {
1690  return crend(inRow);
1691  }
1692 
1693  //============================================================================
1694  // Method Description:
1701  {
1702  return crbegin() += size_;
1703  }
1704 
1705  //============================================================================
1706  // Method Description:
1715  {
1716  if (inRow >= shape_.rows)
1717  {
1718  THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1719  }
1720 
1721  return crbegin(inRow) += shape_.cols;
1722  }
1723 
1724  //============================================================================
1725  // Method Description:
1731  {
1732  return colbegin() += size_;
1733  }
1734 
1735  //============================================================================
1736  // Method Description:
1745  {
1746  if (inCol >= shape_.cols)
1747  {
1748  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1749  }
1750 
1751  return colbegin(inCol) += shape_.rows;
1752  }
1753 
1754  //============================================================================
1755  // Method Description:
1760  const_column_iterator colend() const noexcept
1761  {
1762  return ccolend();
1763  }
1764 
1765  //============================================================================
1766  // Method Description:
1775  {
1776  return ccolend(inCol);
1777  }
1778 
1779  //============================================================================
1780  // Method Description:
1786  const_column_iterator ccolend() const noexcept
1787  {
1788  return ccolbegin() += size_;
1789  }
1790 
1791  //============================================================================
1792  // Method Description:
1801  {
1802  if (inCol >= shape_.cols)
1803  {
1804  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1805  }
1806 
1807  return ccolbegin(inCol) += shape_.rows;
1808  }
1809 
1810  //============================================================================
1811  // Method Description:
1817  {
1818  return rcolbegin() += size_;
1819  }
1820 
1821  //============================================================================
1822  // Method Description:
1831  {
1832  if (inCol >= shape_.cols)
1833  {
1834  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1835  }
1836 
1837  return rcolbegin(inCol) += shape_.rows;
1838  }
1839 
1840  //============================================================================
1841  // Method Description:
1847  {
1848  return crcolend();
1849  }
1850 
1851  //============================================================================
1852  // Method Description:
1861  {
1862  return crcolend(inCol);
1863  }
1864 
1865  //============================================================================
1866  // Method Description:
1873  {
1874  return crcolbegin() += size_;
1875  }
1876 
1877  //============================================================================
1878  // Method Description:
1887  {
1888  if (inCol >= shape_.cols)
1889  {
1890  THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1891  }
1892 
1893  return crcolbegin(inCol) += shape_.rows;
1894  }
1895 
1896  //============================================================================
1897  // Method Description:
1908  {
1910 
1911  const auto function = [](dtype i) -> bool
1912  {
1913  return i != dtype{ 0 };
1914  };
1915 
1916  switch (inAxis)
1917  {
1918  case Axis::NONE:
1919  {
1920  NdArray<bool> returnArray = { stl_algorithms::all_of(cbegin(), cend(), function) };
1921  return returnArray;
1922  }
1923  case Axis::COL:
1924  {
1925  NdArray<bool> returnArray(1, shape_.rows);
1926  for (uint32 row = 0; row < shape_.rows; ++row)
1927  {
1928  returnArray(0, row) = stl_algorithms::all_of(cbegin(row), cend(row), function);
1929  }
1930 
1931  return returnArray;
1932  }
1933  case Axis::ROW:
1934  {
1935  NdArray<dtype> arrayTransposed = transpose();
1936  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
1937  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1938  {
1939  returnArray(0, row) = stl_algorithms::all_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
1940  }
1941 
1942  return returnArray;
1943  }
1944  default:
1945  {
1946  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1947  return {}; // get rid of compiler warning
1948  }
1949  }
1950  }
1951 
1952  //============================================================================
1953  // Method Description:
1964  {
1966 
1967  const auto function = [](dtype i) -> bool
1968  {
1969  return i != dtype{ 0 };
1970  };
1971 
1972  switch (inAxis)
1973  {
1974  case Axis::NONE:
1975  {
1976  NdArray<bool> returnArray = { stl_algorithms::any_of(cbegin(), cend(), function) };
1977  return returnArray;
1978  }
1979  case Axis::COL:
1980  {
1981  NdArray<bool> returnArray(1, shape_.rows);
1982  for (uint32 row = 0; row < shape_.rows; ++row)
1983  {
1984  returnArray(0, row) = stl_algorithms::any_of(cbegin(row), cend(row), function);
1985  }
1986 
1987  return returnArray;
1988  }
1989  case Axis::ROW:
1990  {
1991  NdArray<dtype> arrayTransposed = transpose();
1992  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
1993  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
1994  {
1995  returnArray(0, row) = stl_algorithms::any_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
1996  }
1997 
1998  return returnArray;
1999  }
2000  default:
2001  {
2002  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2003  return {}; // get rid of compiler warning
2004  }
2005  }
2006  }
2007 
2008  //============================================================================
2009  // Method Description:
2021  {
2023 
2024  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
2025  {
2026  return lhs < rhs;
2027  };
2028 
2029  switch (inAxis)
2030  {
2031  case Axis::NONE:
2032  {
2033  NdArray<uint32> returnArray = { static_cast<uint32>(stl_algorithms::max_element(cbegin(),
2034  cend(), comparitor) - cbegin()) };
2035  return returnArray;
2036  }
2037  case Axis::COL:
2038  {
2039  NdArray<uint32> returnArray(1, shape_.rows);
2040  for (uint32 row = 0; row < shape_.rows; ++row)
2041  {
2042  returnArray(0, row) = static_cast<uint32>(stl_algorithms::max_element(cbegin(row),
2043  cend(row), comparitor) - cbegin(row));
2044  }
2045 
2046  return returnArray;
2047  }
2048  case Axis::ROW:
2049  {
2050  NdArray<dtype> arrayTransposed = transpose();
2051  NdArray<uint32> returnArray(1, arrayTransposed.shape_.rows);
2052  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
2053  {
2054  returnArray(0, row) = static_cast<uint32>(stl_algorithms::max_element(arrayTransposed.cbegin(row),
2055  arrayTransposed.cend(row), comparitor) - arrayTransposed.cbegin(row));
2056  }
2057 
2058  return returnArray;
2059  }
2060  default:
2061  {
2062  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2063  return {}; // get rid of compiler warning
2064  }
2065  }
2066  }
2067 
2068  //============================================================================
2069  // Method Description:
2081  {
2083 
2084  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
2085  {
2086  return lhs < rhs;
2087  };
2088 
2089  switch (inAxis)
2090  {
2091  case Axis::NONE:
2092  {
2093  NdArray<uint32> returnArray = { static_cast<uint32>(stl_algorithms::min_element(cbegin(),
2094  cend(), comparitor) - cbegin()) };
2095  return returnArray;
2096  }
2097  case Axis::COL:
2098  {
2099  NdArray<uint32> returnArray(1, shape_.rows);
2100  for (uint32 row = 0; row < shape_.rows; ++row)
2101  {
2102  returnArray(0, row) = static_cast<uint32>(stl_algorithms::min_element(cbegin(row),
2103  cend(row), comparitor) - cbegin(row));
2104  }
2105 
2106  return returnArray;
2107  }
2108  case Axis::ROW:
2109  {
2110  NdArray<dtype> arrayTransposed = transpose();
2111  NdArray<uint32> returnArray(1, arrayTransposed.shape_.rows);
2112  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
2113  {
2114  returnArray(0, row) = static_cast<uint32>(stl_algorithms::min_element(arrayTransposed.cbegin(row),
2115  arrayTransposed.cend(row), comparitor) - arrayTransposed.cbegin(row));
2116  }
2117 
2118  return returnArray;
2119  }
2120  default:
2121  {
2122  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2123  return {}; // get rid of compiler warning
2124  }
2125  }
2126  }
2127 
2128  //============================================================================
2129  // Method Description:
2140  {
2142 
2143  switch (inAxis)
2144  {
2145  case Axis::NONE:
2146  {
2147  std::vector<uint32> idx(size_);
2148  std::iota(idx.begin(), idx.end(), 0);
2149 
2150  const auto function = [this](uint32 i1, uint32 i2) noexcept -> bool
2151  {
2152  return (*this)[i1] < (*this)[i2];
2153  };
2154 
2155  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2156  return NdArray<uint32>(idx);
2157  }
2158  case Axis::COL:
2159  {
2160  NdArray<uint32> returnArray(shape_);
2161  for (uint32 row = 0; row < shape_.rows; ++row)
2162  {
2163  std::vector<uint32> idx(shape_.cols);
2164  std::iota(idx.begin(), idx.end(), 0);
2165 
2166  const auto function = [this, row](uint32 i1, uint32 i2) noexcept -> bool
2167  {
2168  return operator()(row, i1) < operator()(row, i2);
2169  };
2170 
2171  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2172 
2173  for (uint32 col = 0; col < shape_.cols; ++col)
2174  {
2175  returnArray(row, col) = idx[col];
2176  }
2177  }
2178  return returnArray;
2179  }
2180  case Axis::ROW:
2181  {
2182  NdArray<dtype> arrayTransposed = transpose();
2183  NdArray<uint32> returnArray(shape_.cols, shape_.rows);
2184  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
2185  {
2186  std::vector<uint32> idx(arrayTransposed.shape_.cols);
2187  std::iota(idx.begin(), idx.end(), 0);
2188 
2189  const auto function = [&arrayTransposed, row](uint32 i1, uint32 i2) noexcept -> bool
2190  {
2191  return arrayTransposed(row, i1) < arrayTransposed(row, i2);
2192  };
2193 
2194  stl_algorithms::stable_sort(idx.begin(), idx.end(), function);
2195 
2196  for (uint32 col = 0; col < arrayTransposed.shape_.cols; ++col)
2197  {
2198  returnArray(row, col) = idx[col];
2199  }
2200  }
2201  return returnArray.transpose();
2202  }
2203  default:
2204  {
2205  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2206  return {}; // get rid of compiler warning
2207  }
2208  }
2209  }
2210 
2211  //============================================================================
2212  // Method Description:
2221  template<typename dtypeOut, typename dtype_ = dtype,
2226  {
2227  NdArray<dtypeOut> outArray(shape_);
2228 
2229  if (is_same_v<dtypeOut, dtype>)
2230  {
2231  std::copy(cbegin(), cend(), outArray.begin());
2232  }
2233  else
2234  {
2235  const auto function = [](dtype value) -> dtypeOut
2236  {
2237  return static_cast<dtypeOut>(value);
2238  };
2239 
2240  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2241  }
2242 
2243  return outArray;
2244  }
2245 
2246  //============================================================================
2247  // Method Description:
2256  template<typename dtypeOut, typename dtype_ = dtype,
2261  {
2262  NdArray<dtypeOut> outArray(shape_);
2263 
2264  const auto function = [](const_reference value) -> dtypeOut
2265  {
2266  return std::complex<typename dtypeOut::value_type>(value);
2267  };
2268 
2269  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2270 
2271  return outArray;
2272  }
2273 
2274  //============================================================================
2275  // Method Description:
2284  template<typename dtypeOut, typename dtype_ = dtype,
2289  {
2290  NdArray<dtypeOut> outArray(shape_);
2291 
2292  if (is_same_v<dtypeOut, dtype>)
2293  {
2294  std::copy(cbegin(), cend(), outArray.begin());
2295  }
2296  else
2297  {
2298  const auto function = [](const_reference value) noexcept -> dtypeOut
2299  {
2300  return complex_cast<typename dtypeOut::value_type>(value);
2301  };
2302 
2303  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2304  }
2305 
2306  return outArray;
2307  }
2308 
2309  //============================================================================
2310  // Method Description:
2319  template<typename dtypeOut, typename dtype_ = dtype,
2324  {
2325  NdArray<dtypeOut> outArray(shape_);
2326 
2327  const auto function = [](const_reference value) -> dtypeOut
2328  {
2329  return static_cast<dtypeOut>(value.real());
2330  };
2331 
2332  stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2333 
2334  return outArray;
2335  }
2336 
2337  //============================================================================
2338  // Method Description:
2344  const_reference back() const noexcept
2345  {
2346  return *(cend() - 1);
2347  }
2348 
2349  //============================================================================
2350  // Method Description:
2356  reference back() noexcept
2357  {
2358  return *(end() - 1);
2359  }
2360 
2361  //============================================================================
2362  // Method Description:
2369  {
2370  return *(cend(row) - 1);
2371  }
2372 
2373  //============================================================================
2374  // Method Description:
2381  {
2382  return *(end(row) - 1);
2383  }
2384 
2385  //============================================================================
2386  // Method Description:
2395  {
2396  STATIC_ASSERT_INTEGER(dtype);
2397 
2399  [](dtype& value) noexcept -> void
2400  {
2401  value = endian::byteSwap(value);
2402  }
2403  );
2404 
2405  switch (endianess_)
2406  {
2407  case Endian::NATIVE:
2408  {
2410  break;
2411  }
2412  case Endian::LITTLE:
2413  {
2414  endianess_ = Endian::BIG;
2415  break;
2416  }
2417  case Endian::BIG:
2418  {
2419  endianess_ = Endian::LITTLE;
2420  break;
2421  }
2422  }
2423 
2424  return *this;
2425  }
2426 
2427  //============================================================================
2428  // Method Description:
2439  {
2441 
2442  NdArray<dtype> outArray(shape_);
2443  stl_algorithms::transform(cbegin(), cend(), outArray.begin(),
2444  [inMin, inMax](dtype value) noexcept -> dtype
2445  {
2446 #ifdef __cpp_lib_clamp
2447  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
2448  {
2449  return lhs < rhs;
2450  };
2451 
2452  return std::clamp(value, inMin, inMax, comparitor);
2453 #else
2454  if (value < inMin)
2455  {
2456  return inMin;
2457  }
2458  else if (value > inMax)
2459  {
2460  return inMax;
2461  }
2462 
2463  return value;
2464 #endif
2465  });
2466 
2467  return outArray;
2468  }
2469 
2470  //============================================================================
2471  // Method Description:
2479  {
2480  return operator()(rSlice(), inColumn);
2481  }
2482 
2483  //============================================================================
2484  // Method Description:
2493  {
2495 
2496  switch (inAxis)
2497  {
2498  case Axis::NONE:
2499  {
2500  NdArray<bool> returnArray = { stl_algorithms::find(cbegin(), cend(), inValue) != cend() };
2501  return returnArray;
2502  }
2503  case Axis::COL:
2504  {
2505  NdArray<bool> returnArray(1, shape_.rows);
2506  for (uint32 row = 0; row < shape_.rows; ++row)
2507  {
2508  returnArray(0, row) = stl_algorithms::find(cbegin(row), cend(row), inValue) != cend(row);
2509  }
2510 
2511  return returnArray;
2512  }
2513  case Axis::ROW:
2514  {
2515  NdArray<dtype> transArray = transpose();
2516  NdArray<bool> returnArray(1, transArray.shape_.rows);
2517  for (uint32 row = 0; row < transArray.shape_.rows; ++row)
2518  {
2519  returnArray(0, row) = stl_algorithms::find(transArray.cbegin(row), transArray.cend(row), inValue) != transArray.cend(row);
2520  }
2521 
2522  return returnArray;
2523  }
2524  default:
2525  {
2526  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2527  return {}; // get rid of compiler warning
2528  }
2529  }
2530  }
2531 
2532  //============================================================================
2533  // Method Description:
2542  {
2543  return NdArray<dtype>(*this);
2544  }
2545 
2546  //============================================================================
2547  // Method Description:
2558  {
2560 
2561  switch (inAxis)
2562  {
2563  case Axis::NONE:
2564  {
2565  NdArray<dtype> returnArray(1, size_);
2566  returnArray[0] = front();
2567  for (uint32 i = 1; i < size_; ++i)
2568  {
2569  returnArray[i] = returnArray[i - 1] * array_[i];
2570  }
2571 
2572  return returnArray;
2573  }
2574  case Axis::COL:
2575  {
2576  NdArray<dtype> returnArray(shape_);
2577  for (uint32 row = 0; row < shape_.rows; ++row)
2578  {
2579  returnArray(row, 0) = operator()(row, 0);
2580  for (uint32 col = 1; col < shape_.cols; ++col)
2581  {
2582  returnArray(row, col) = returnArray(row, col - 1) * operator()(row, col);
2583  }
2584  }
2585 
2586  return returnArray;
2587  }
2588  case Axis::ROW:
2589  {
2590  NdArray<dtype> returnArray(shape_);
2591  for (uint32 col = 0; col < shape_.cols; ++col)
2592  {
2593  returnArray(0, col) = operator()(0, col);
2594  for (uint32 row = 1; row < shape_.rows; ++row)
2595  {
2596  returnArray(row, col) = returnArray(row - 1, col) * operator()(row, col);
2597  }
2598  }
2599 
2600  return returnArray;
2601  }
2602  default:
2603  {
2604  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2605  return {}; // get rid of compiler warning
2606  }
2607  }
2608  }
2609 
2610  //============================================================================
2611  // Method Description:
2622  {
2624 
2625  switch (inAxis)
2626  {
2627  case Axis::NONE:
2628  {
2629  NdArray<dtype> returnArray(1, size_);
2630  returnArray[0] = front();
2631  for (uint32 i = 1; i < size_; ++i)
2632  {
2633  returnArray[i] = returnArray[i - 1] + array_[i];
2634  }
2635 
2636  return returnArray;
2637  }
2638  case Axis::COL:
2639  {
2640  NdArray<dtype> returnArray(shape_);
2641  for (uint32 row = 0; row < shape_.rows; ++row)
2642  {
2643  returnArray(row, 0) = operator()(row, 0);
2644  for (uint32 col = 1; col < shape_.cols; ++col)
2645  {
2646  returnArray(row, col) = returnArray(row, col - 1) + operator()(row, col);
2647  }
2648  }
2649 
2650  return returnArray;
2651  }
2652  case Axis::ROW:
2653  {
2654  NdArray<dtype> returnArray(shape_);
2655  for (uint32 col = 0; col < shape_.cols; ++col)
2656  {
2657  returnArray(0, col) = operator()(0, col);
2658  for (uint32 row = 1; row < shape_.rows; ++row)
2659  {
2660  returnArray(row, col) = returnArray(row - 1, col) + operator()(row, col);
2661  }
2662  }
2663 
2664  return returnArray;
2665  }
2666  default:
2667  {
2668  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2669  return {}; // get rid of compiler warning
2670  }
2671  }
2672  }
2673 
2674  //============================================================================
2675  // Method Description:
2679  pointer data() noexcept
2680  {
2681  return array_;
2682  }
2683 
2684  //============================================================================
2685  // Method Description:
2689  const_pointer data() const noexcept
2690  {
2691  return array_;
2692  }
2693 
2694  //============================================================================
2695  // Method Description:
2702  {
2703  ownsPtr_ = false;
2704  return data();
2705  }
2706 
2707  //============================================================================
2708  // Method Description:
2718  NdArray<dtype> diagonal(int32 inOffset = 0, Axis inAxis = Axis::ROW) const
2719  {
2720  switch (inAxis)
2721  {
2722  case Axis::ROW:
2723  {
2724  std::vector<dtype> diagnolValues;
2725  int32 col = inOffset;
2726  for (uint32 row = 0; row < shape_.rows; ++row)
2727  {
2728  if (col < 0)
2729  {
2730  ++col;
2731  continue;
2732  }
2733  if (col >= static_cast<int32>(shape_.cols))
2734  {
2735  break;
2736  }
2737 
2738  diagnolValues.push_back(operator()(row, static_cast<uint32>(col)));
2739  ++col;
2740  }
2741 
2742  return NdArray<dtype>(diagnolValues);
2743  }
2744  case Axis::COL:
2745  {
2746  std::vector<dtype> diagnolValues;
2747  uint32 col = 0;
2748  for (int32 row = inOffset; row < static_cast<int32>(shape_.rows); ++row)
2749  {
2750  if (row < 0)
2751  {
2752  ++col;
2753  continue;
2754  }
2755  if (col >= shape_.cols)
2756  {
2757  break;
2758  }
2759 
2760  diagnolValues.push_back(operator()(static_cast<uint32>(row), col));
2761  ++col;
2762  }
2763 
2764  return NdArray<dtype>(diagnolValues);
2765  }
2766  default:
2767  {
2768  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2769  return {}; // get rid of compiler warning
2770  }
2771  }
2772  }
2773 
2774  //============================================================================
2775  // Method Description:
2788  NdArray<dtype> dot(const NdArray<dtype>& inOtherArray) const
2789  {
2791 
2792  if (shape_ == inOtherArray.shape_ && (shape_.rows == 1 || shape_.cols == 1))
2793  {
2794  dtype dotProduct = std::inner_product(cbegin(), cend(), inOtherArray.cbegin(), dtype{ 0 });
2795  NdArray<dtype> returnArray = { dotProduct };
2796  return returnArray;
2797  }
2798  if (shape_.cols == inOtherArray.shape_.rows)
2799  {
2800  // 2D array, use matrix multiplication
2801  NdArray<dtype> returnArray(shape_.rows, inOtherArray.shape_.cols);
2802  auto otherArrayT = inOtherArray.transpose();
2803 
2804  for (uint32 i = 0; i < shape_.rows; ++i)
2805  {
2806  for (uint32 j = 0; j < otherArrayT.shape_.rows; ++j)
2807  {
2808  returnArray(i, j) = std::inner_product(otherArrayT.cbegin(j), otherArrayT.cend(j), cbegin(i), dtype{ 0 });
2809  }
2810  }
2811 
2812  return returnArray;
2813  }
2814 
2815  std::string errStr = "shapes of [" + utils::num2str(shape_.rows) + ", " + utils::num2str(shape_.cols) + "]";
2816  errStr += " and [" + utils::num2str(inOtherArray.shape_.rows) + ", " + utils::num2str(inOtherArray.shape_.cols) + "]";
2817  errStr += " are not consistent.";
2819 
2820  return NdArray<dtype>(); // get rid of compiler warning
2821  }
2822 
2823  //============================================================================
2824  // Method Description:
2832  void dump(const std::string& inFilename) const
2833  {
2834  filesystem::File f(inFilename);
2835  if (!f.hasExt())
2836  {
2837  f.withExt(".bin");
2838  }
2839 
2840  std::ofstream ofile(f.fullName().c_str(), std::ios::binary);
2841  if (!ofile.good())
2842  {
2843  THROW_RUNTIME_ERROR("Unable to open the input file:\n\t" + inFilename);
2844  }
2845 
2846  if (array_ != nullptr)
2847  {
2848  ofile.write(reinterpret_cast<const char*>(array_), size_ * sizeof(dtype));
2849  }
2850  ofile.close();
2851  }
2852 
2853  //============================================================================
2854  // Method Description:
2860  Endian endianess() const noexcept
2861  {
2862  STATIC_ASSERT_ARITHMETIC(dtype);
2863 
2864  return endianess_;
2865  }
2866 
2867  //============================================================================
2868  // Method Description:
2878  NdArray<dtype>& fill(value_type inFillValue) noexcept
2879  {
2880  stl_algorithms::fill(begin(), end(), inFillValue);
2881  return *this;
2882  }
2883 
2884  //============================================================================
2885  // Method Description:
2893  {
2895 
2896  std::vector<uint32> indices;
2897  uint32 idx = 0;
2898  for (auto value : *this)
2899  {
2900  if (value != dtype{ 0 })
2901  {
2902  indices.push_back(idx);
2903  }
2904  ++idx;
2905  }
2906 
2907  return NdArray<uint32>(indices);
2908  }
2909 
2910  //============================================================================
2911  // Method Description:
2920  {
2921  NdArray<dtype> outArray(1, size_);
2922  stl_algorithms::copy(cbegin(), cend(), outArray.begin());
2923  return outArray;
2924  }
2925 
2926  //============================================================================
2927  // Method Description:
2933  const_reference front() const noexcept
2934  {
2935  return *cbegin();
2936  }
2937 
2938  //============================================================================
2939  // Method Description:
2945  reference front() noexcept
2946  {
2947  return *begin();
2948  }
2949 
2950  //============================================================================
2951  // Method Description:
2958  {
2959  return *cbegin(row);
2960  }
2961 
2962  //============================================================================
2963  // Method Description:
2970  {
2971  return *begin(row);
2972  }
2973 
2974  //============================================================================
2975  // Method Description:
2984  {
2985  return operator[](inIndices);
2986  }
2987 
2988  //============================================================================
2989  // Method Description:
3000  {
3001  return operator[](inMask);
3002  }
3003 
3004  //============================================================================
3005  // Method Description:
3012  bool isempty() const noexcept
3013  {
3014  return size_ == 0;
3015  }
3016 
3017  //============================================================================
3018  // Method Description:
3025  bool isflat() const noexcept
3026  {
3027  return shape_.rows == 1 || shape_.cols == 1;
3028  }
3029 
3030  //============================================================================
3031  // Method Description:
3038  {
3040 
3041  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3042  {
3043  return lhs < rhs;
3044  };
3045 
3046  switch (inAxis)
3047  {
3048  case Axis::NONE:
3049  {
3050  return { stl_algorithms::is_sorted(cbegin(), cend(), comparitor) };
3051  }
3052  case Axis::ROW:
3053  {
3054  NdArray<bool> returnArray(shape_.cols, 1);
3055  auto transposedArray = transpose();
3056  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3057  {
3058  returnArray(0, row) = stl_algorithms::is_sorted(transposedArray.cbegin(row),
3059  transposedArray.cend(row), comparitor);
3060  }
3061 
3062  return returnArray;
3063  }
3064  case Axis::COL:
3065  {
3066  NdArray<bool> returnArray(1, shape_.rows);
3067  for (uint32 row = 0; row < shape_.rows; ++row)
3068  {
3069  returnArray(0, row) = stl_algorithms::is_sorted(cbegin(row), cend(row), comparitor);
3070  }
3071 
3072  return returnArray;
3073  }
3074  default:
3075  {
3076  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3077  return {}; // get rid of compiler warning
3078  }
3079  }
3080  }
3081 
3082  //============================================================================
3083  // Method Description:
3088  bool issquare() const noexcept
3089  {
3090  return shape_.issquare();
3091  }
3092 
3093  //============================================================================
3094  // Method Description:
3103  {
3104  if (size_ != 1)
3105  {
3106  THROW_INVALID_ARGUMENT_ERROR("Can only convert an array of size 1 to a C++ scaler");
3107  }
3108 
3109  return front();
3110  }
3111 
3112  //============================================================================
3113  // Method Description:
3124  {
3126 
3127  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3128  {
3129  return lhs < rhs;
3130  };
3131 
3132  switch (inAxis)
3133  {
3134  case Axis::NONE:
3135  {
3136  NdArray<dtype> returnArray = { *stl_algorithms::max_element(cbegin(), cend(), comparitor) };
3137  return returnArray;
3138  }
3139  case Axis::COL:
3140  {
3141  NdArray<dtype> returnArray(1, shape_.rows);
3142  for (uint32 row = 0; row < shape_.rows; ++row)
3143  {
3144  returnArray(0, row) = *stl_algorithms::max_element(cbegin(row), cend(row), comparitor);
3145  }
3146 
3147  return returnArray;
3148  }
3149  case Axis::ROW:
3150  {
3151  NdArray<dtype> transposedArray = transpose();
3152  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3153  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3154  {
3155  returnArray(0, row) = *stl_algorithms::max_element(transposedArray.cbegin(row),
3156  transposedArray.cend(row), comparitor);
3157  }
3158 
3159  return returnArray;
3160  }
3161  default:
3162  {
3163  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3164  return {}; // get rid of compiler warning
3165  }
3166  }
3167  }
3168 
3169  //============================================================================
3170  // Method Description:
3181  {
3183 
3184  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3185  {
3186  return lhs < rhs;
3187  };
3188 
3189  switch (inAxis)
3190  {
3191  case Axis::NONE:
3192  {
3193  NdArray<dtype> returnArray = { *stl_algorithms::min_element(cbegin(), cend(), comparitor) };
3194  return returnArray;
3195  }
3196  case Axis::COL:
3197  {
3198  NdArray<dtype> returnArray(1, shape_.rows);
3199  for (uint32 row = 0; row < shape_.rows; ++row)
3200  {
3201  returnArray(0, row) = *stl_algorithms::min_element(cbegin(row), cend(row), comparitor);
3202  }
3203 
3204  return returnArray;
3205  }
3206  case Axis::ROW:
3207  {
3208  NdArray<dtype> transposedArray = transpose();
3209  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3210  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3211  {
3212  returnArray(0, row) = *stl_algorithms::min_element(transposedArray.cbegin(row),
3213  transposedArray.cend(row), comparitor);
3214  }
3215 
3216  return returnArray;
3217  }
3218  default:
3219  {
3220  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3221  return {}; // get rid of compiler warning
3222  }
3223  }
3224  }
3225 
3226  //============================================================================
3227  // Method Description:
3240  {
3242 
3243  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3244  {
3245  return lhs < rhs;
3246  };
3247 
3248  if (size_ == 0)
3249  {
3250  THROW_RUNTIME_ERROR("Median is undefined for an array of size = 0.");
3251  }
3252 
3253  switch (inAxis)
3254  {
3255  case Axis::NONE:
3256  {
3257  NdArray<dtype> copyArray(*this);
3258 
3259  const uint32 middleIdx = size_ / 2; // integer division
3260  stl_algorithms::nth_element(copyArray.begin(), copyArray.begin() + middleIdx, copyArray.end(), comparitor);
3261 
3262  dtype medianValue = copyArray.array_[middleIdx];
3263  if (size_ % 2 == 0)
3264  {
3265  const uint32 lhsIndex = middleIdx - 1;
3266  stl_algorithms::nth_element(copyArray.begin(), copyArray.begin() + lhsIndex, copyArray.end(), comparitor);
3267  medianValue = (medianValue + copyArray.array_[lhsIndex]) / dtype{2}; // potentially integer division, ok
3268  }
3269 
3270  return { medianValue };
3271  }
3272  case Axis::COL:
3273  {
3274  NdArray<dtype> copyArray(*this);
3275  NdArray<dtype> returnArray(1, shape_.rows);
3276 
3277  const bool isEven = shape_.cols % 2 == 0;
3278  for (uint32 row = 0; row < shape_.rows; ++row)
3279  {
3280  const uint32 middleIdx = shape_.cols / 2; // integer division
3281  stl_algorithms::nth_element(copyArray.begin(row), copyArray.begin(row) + middleIdx,
3282  copyArray.end(row), comparitor);
3283 
3284  dtype medianValue = copyArray(row, middleIdx);
3285  if (isEven)
3286  {
3287  const uint32 lhsIndex = middleIdx - 1;
3288  stl_algorithms::nth_element(copyArray.begin(row), copyArray.begin(row) + lhsIndex,
3289  copyArray.end(row), comparitor);
3290  medianValue = (medianValue + copyArray(row, lhsIndex)) / dtype{2}; // potentially integer division, ok
3291  }
3292 
3293  returnArray(0, row) = medianValue;
3294  }
3295 
3296  return returnArray;
3297  }
3298  case Axis::ROW:
3299  {
3300  NdArray<dtype> transposedArray = transpose();
3301  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3302 
3303  const bool isEven = shape_.rows % 2 == 0;
3304  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3305  {
3306  const uint32 middleIdx = transposedArray.shape_.cols / 2; // integer division
3307  stl_algorithms::nth_element(transposedArray.begin(row), transposedArray.begin(row) + middleIdx,
3308  transposedArray.end(row), comparitor);
3309 
3310  dtype medianValue = transposedArray(row, middleIdx);
3311  if (isEven)
3312  {
3313  const uint32 lhsIndex = middleIdx - 1;
3314  stl_algorithms::nth_element(transposedArray.begin(row), transposedArray.begin(row) + lhsIndex,
3315  transposedArray.end(row), comparitor);
3316  medianValue = (medianValue + transposedArray(row, lhsIndex)) / dtype{2}; // potentially integer division, ok
3317  }
3318 
3319  returnArray(0, row) = medianValue;
3320  }
3321 
3322  return returnArray;
3323  }
3324  default:
3325  {
3326  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3327  return {}; // get rid of compiler warning
3328  }
3329  }
3330  }
3331 
3332  //============================================================================
3333  // Method Description:
3337  NdArray<dtype>& nans() noexcept
3338  {
3339  STATIC_ASSERT_FLOAT(dtype);
3340 
3342  return *this;
3343  }
3344 
3345  //============================================================================
3346  // Method Description:
3354  uint64 nbytes() const noexcept
3355  {
3356  return static_cast<uint64>(sizeof(dtype) * size_);
3357  }
3358 
3359  //============================================================================
3360  // Method Description:
3371  NdArray<dtype> newbyteorder(Endian inEndianess) const
3372  {
3373  STATIC_ASSERT_INTEGER(dtype);
3374 
3375  const bool nativeIsLittle = endian::isLittleEndian();
3376 
3377  switch (endianess_)
3378  {
3379  case Endian::NATIVE:
3380  {
3381  switch (inEndianess)
3382  {
3383  case Endian::NATIVE:
3384  {
3385  return NdArray(*this);
3386  }
3387  case Endian::BIG:
3388  {
3389  if (nativeIsLittle)
3390  {
3391  NdArray<dtype> outArray(shape_);
3392 
3393  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3394 
3395  outArray.endianess_ = Endian::BIG;
3396  return outArray;
3397  }
3398  else
3399  {
3400  auto outArray = NdArray(*this);
3401  outArray.endianess_ = Endian::BIG;
3402  return outArray;
3403  }
3404  }
3405  case Endian::LITTLE:
3406  {
3407  if (nativeIsLittle)
3408  {
3409  auto outArray = NdArray(*this);
3410  outArray.endianess_ = Endian::LITTLE;
3411  return outArray;
3412  }
3413  else
3414  {
3415  NdArray<dtype> outArray(shape_);
3416 
3417  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3418 
3419  outArray.endianess_ = Endian::LITTLE;
3420  return outArray;
3421  }
3422  }
3423  default:
3424  {
3425  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3426  return {}; // get rid of compiler warning
3427  }
3428  }
3429  break;
3430  }
3431  case Endian::BIG:
3432  {
3433  switch (inEndianess)
3434  {
3435  case Endian::NATIVE:
3436  {
3437  if (nativeIsLittle)
3438  {
3439  NdArray<dtype> outArray(shape_);
3440 
3441  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3442 
3443  outArray.endianess_ = Endian::NATIVE;
3444  return outArray;
3445  }
3446  else
3447  {
3448  auto outArray = NdArray(*this);
3449  outArray.endianess_ = Endian::NATIVE;
3450  return outArray;
3451  }
3452  }
3453  case Endian::BIG:
3454  {
3455  return NdArray(*this);
3456  }
3457  case Endian::LITTLE:
3458  {
3459  NdArray<dtype> outArray(shape_);
3460 
3461  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3462 
3463  outArray.endianess_ = Endian::LITTLE;
3464  return outArray;
3465  }
3466  default:
3467  {
3468  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3469  return {}; // get rid of compiler warning
3470  }
3471  }
3472  break;
3473  }
3474  case Endian::LITTLE:
3475  {
3476  switch (inEndianess)
3477  {
3478  case Endian::NATIVE:
3479  {
3480  if (nativeIsLittle)
3481  {
3482  auto outArray = NdArray(*this);
3483  outArray.endianess_ = Endian::NATIVE;
3484  return outArray;
3485  }
3486  else
3487  {
3488  NdArray<dtype> outArray(shape_);
3489 
3490  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3491 
3492  outArray.endianess_ = Endian::NATIVE;
3493  return outArray;
3494  }
3495  }
3496  case Endian::BIG:
3497  {
3498  NdArray<dtype> outArray(shape_);
3499 
3500  stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3501 
3502  outArray.endianess_ = Endian::BIG;
3503  return outArray;
3504  }
3505  case Endian::LITTLE:
3506  {
3507  return NdArray(*this);
3508  }
3509  default:
3510  {
3511  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3512  return {}; // get rid of compiler warning
3513  }
3514  }
3515  break;
3516  }
3517  default:
3518  {
3519  THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3520  return {}; // get rid of compiler warning
3521  }
3522  }
3523  }
3524 
3525  //============================================================================
3526  // Method Description:
3537  {
3539 
3540  const auto function = [](dtype i) -> bool
3541  {
3542  return i != dtype{ 0 };
3543  };
3544 
3545  switch (inAxis)
3546  {
3547  case Axis::NONE:
3548  {
3549  NdArray<bool> returnArray = { stl_algorithms::none_of(cbegin(), cend(), function) };
3550  return returnArray;
3551  }
3552  case Axis::COL:
3553  {
3554  NdArray<bool> returnArray(1, shape_.rows);
3555  for (uint32 row = 0; row < shape_.rows; ++row)
3556  {
3557  returnArray(0, row) = stl_algorithms::none_of(cbegin(row), cend(row), function);
3558  }
3559 
3560  return returnArray;
3561  }
3562  case Axis::ROW:
3563  {
3564  NdArray<dtype> arrayTransposed = transpose();
3565  NdArray<bool> returnArray(1, arrayTransposed.shape_.rows);
3566  for (uint32 row = 0; row < arrayTransposed.shape_.rows; ++row)
3567  {
3568  returnArray(0, row) = stl_algorithms::none_of(arrayTransposed.cbegin(row), arrayTransposed.cend(row), function);
3569  }
3570 
3571  return returnArray;
3572  }
3573  default:
3574  {
3575  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3576  return {}; // get rid of compiler warning
3577  }
3578  }
3579  }
3580 
3581  //============================================================================
3582  // Method Description:
3592  std::pair<NdArray<uint32>, NdArray<uint32>> nonzero() const;
3593 
3594  //============================================================================
3595  // Method Description:
3602  uint32 numCols() const noexcept
3603  {
3604  return shape_.cols;
3605  }
3606 
3607  //============================================================================
3608  // Method Description:
3615  uint32 numRows() const noexcept
3616  {
3617  return shape_.rows;
3618  }
3619 
3620  //============================================================================
3621  // Method Description:
3625  NdArray<dtype>& ones() noexcept
3626  {
3628 
3629  fill(dtype{ 1 });
3630  return *this;
3631  }
3632 
3633  //============================================================================
3634  // Method Description:
3639  bool ownsInternalData() noexcept
3640  {
3641  return ownsPtr_;
3642  }
3643 
3644  //============================================================================
3645  // Method Description:
3661  {
3663 
3664  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3665  {
3666  return lhs < rhs;
3667  };
3668 
3669  switch (inAxis)
3670  {
3671  case Axis::NONE:
3672  {
3673  if (inKth >= size_)
3674  {
3675  std::string errStr = "kth(=" + utils::num2str(inKth);
3676  errStr += ") out of bounds (" + utils::num2str(size_) + ")";
3678  }
3679 
3680  stl_algorithms::nth_element(begin(), begin() + inKth, end(), comparitor);
3681  break;
3682  }
3683  case Axis::COL:
3684  {
3685  if (inKth >= shape_.cols)
3686  {
3687  std::string errStr = "kth(=" + utils::num2str(inKth);
3688  errStr += ") out of bounds (" + utils::num2str(shape_.cols) + ")";
3690  }
3691 
3692  for (uint32 row = 0; row < shape_.rows; ++row)
3693  {
3694  stl_algorithms::nth_element(begin(row), begin(row) + inKth, end(row), comparitor);
3695  }
3696  break;
3697  }
3698  case Axis::ROW:
3699  {
3700  if (inKth >= shape_.rows)
3701  {
3702  std::string errStr = "kth(=" + utils::num2str(inKth);
3703  errStr += ") out of bounds (" + utils::num2str(shape_.rows) + ")";
3705  }
3706 
3707  NdArray<dtype> transposedArray = transpose();
3708  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3709  {
3710  stl_algorithms::nth_element(transposedArray.begin(row), transposedArray.begin(row) + inKth,
3711  transposedArray.end(row), comparitor);
3712  }
3713  *this = transposedArray.transpose();
3714  break;
3715  }
3716  }
3717 
3718  return *this;
3719  }
3720 
3721  //============================================================================
3722  // Method Description:
3726  void print() const
3727  {
3729 
3730  std::cout << *this;
3731  }
3732 
3733  //============================================================================
3734  // Method Description:
3745  {
3747 
3748  switch (inAxis)
3749  {
3750  case Axis::NONE:
3751  {
3752  dtype product = std::accumulate(cbegin(), cend(),
3753  dtype{ 1 }, std::multiplies<dtype>());
3754  NdArray<dtype> returnArray = { product };
3755  return returnArray;
3756  }
3757  case Axis::COL:
3758  {
3759  NdArray<dtype> returnArray(1, shape_.rows);
3760  for (uint32 row = 0; row < shape_.rows; ++row)
3761  {
3762  returnArray(0, row) = std::accumulate(cbegin(row), cend(row),
3763  dtype{ 1 }, std::multiplies<dtype>());
3764  }
3765 
3766  return returnArray;
3767  }
3768  case Axis::ROW:
3769  {
3770  NdArray<dtype> transposedArray = transpose();
3771  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3772  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3773  {
3774  returnArray(0, row) = std::accumulate(transposedArray.cbegin(row), transposedArray.cend(row),
3775  dtype{ 1 }, std::multiplies<dtype>());
3776  }
3777 
3778  return returnArray;
3779  }
3780  default:
3781  {
3782  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3783  return {}; // get rid of compiler warning
3784  }
3785  }
3786  }
3787 
3788  //============================================================================
3789  // Method Description:
3800  {
3802 
3803  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3804  {
3805  return lhs < rhs;
3806  };
3807 
3808  switch (inAxis)
3809  {
3810  case Axis::NONE:
3811  {
3812  const auto result = stl_algorithms::minmax_element(cbegin(), cend(), comparitor);
3813  NdArray<dtype> returnArray = { *result.second - *result.first };
3814  return returnArray;
3815  }
3816  case Axis::COL:
3817  {
3818  NdArray<dtype> returnArray(1, shape_.rows);
3819  for (uint32 row = 0; row < shape_.rows; ++row)
3820  {
3821  const auto result = stl_algorithms::minmax_element(cbegin(row), cend(row), comparitor);
3822  returnArray(0, row) = *result.second - *result.first;
3823  }
3824 
3825  return returnArray;
3826  }
3827  case Axis::ROW:
3828  {
3829  NdArray<dtype> transposedArray = transpose();
3830  NdArray<dtype> returnArray(1, transposedArray.shape_.rows);
3831  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3832  {
3833  const auto result = stl_algorithms::minmax_element(transposedArray.cbegin(row), transposedArray.cend(row), comparitor);
3834  returnArray(0, row) = *result.second - *result.first;
3835  }
3836 
3837  return returnArray;
3838  }
3839  default:
3840  {
3841  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3842  return {}; // get rid of compiler warning
3843  }
3844  }
3845  }
3846 
3847  //============================================================================
3848  // Method Description:
3856  NdArray<dtype>& put(int32 inIndex, value_type inValue)
3857  {
3858  at(inIndex) = inValue;
3859 
3860  return *this;
3861  }
3862 
3863  //============================================================================
3864  // Method Description:
3873  NdArray<dtype>& put(int32 inRow, int32 inCol, value_type inValue)
3874  {
3875  at(inRow, inCol) = inValue;
3876 
3877  return *this;
3878  }
3879 
3880  //============================================================================
3881  // Method Description:
3889  NdArray<dtype>& put(const NdArray<uint32>& inIndices, value_type inValue)
3890  {
3891  for (auto index : inIndices)
3892  {
3893  put(index, inValue);
3894  }
3895 
3896  return *this;
3897  }
3898 
3899  //============================================================================
3900  // Method Description:
3908  NdArray<dtype>& put(const NdArray<uint32>& inIndices, const NdArray<dtype>& inValues)
3909  {
3910  if (inIndices.size() != inValues.size())
3911  {
3912  THROW_INVALID_ARGUMENT_ERROR("Input indices do not match values dimensions.");
3913  }
3914 
3915  uint32 counter = 0;
3916  for (auto index : inIndices)
3917  {
3918  put(index, inValues[counter++]);
3919  }
3920 
3921  return *this;
3922  }
3923 
3924  //============================================================================
3925  // Method Description:
3933  NdArray<dtype>& put(const Slice& inSlice, value_type inValue)
3934  {
3935  Slice inSliceCopy(inSlice);
3936  inSliceCopy.makePositiveAndValidate(size_);
3937 
3938  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
3939  {
3940  put(i, inValue);
3941  }
3942 
3943  return *this;
3944  }
3945 
3946  //============================================================================
3947  // Method Description:
3955  NdArray<dtype>& put(const Slice& inSlice, const NdArray<dtype>& inValues)
3956  {
3957  Slice inSliceCopy(inSlice);
3958  inSliceCopy.makePositiveAndValidate(size_);
3959 
3960  std::vector<uint32> indices;
3961  for (int32 i = inSliceCopy.start; i < inSliceCopy.stop; i += inSliceCopy.step)
3962  {
3963  indices.push_back(i);
3964  }
3965 
3966  return put(NdArray<uint32>(indices), inValues);
3967  }
3968 
3969  //============================================================================
3970  // Method Description:
3979  NdArray<dtype>& put(const Slice& inRowSlice, const Slice& inColSlice, value_type inValue)
3980  {
3981  Slice inRowSliceCopy(inRowSlice);
3982  Slice inColSliceCopy(inColSlice);
3983 
3984  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
3985  inColSliceCopy.makePositiveAndValidate(shape_.cols);
3986 
3987  std::vector<uint32> indices;
3988  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
3989  {
3990  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
3991  {
3992  put(row, col, inValue);
3993  }
3994  }
3995 
3996  return *this;
3997  }
3998 
3999  //============================================================================
4000  // Method Description:
4009  NdArray<dtype>& put(const Slice& inRowSlice, int32 inColIndex, value_type inValue)
4010  {
4011  Slice inRowSliceCopy(inRowSlice);
4012  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
4013 
4014  std::vector<uint32> indices;
4015  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
4016  {
4017  put(row, inColIndex, inValue);
4018  }
4019 
4020  return *this;
4021  }
4022 
4023  //============================================================================
4024  // Method Description:
4033  NdArray<dtype>& put(int32 inRowIndex, const Slice& inColSlice, value_type inValue)
4034  {
4035  Slice inColSliceCopy(inColSlice);
4036  inColSliceCopy.makePositiveAndValidate(shape_.cols);
4037 
4038  std::vector<uint32> indices;
4039  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
4040  {
4041  put(inRowIndex, col, inValue);
4042  }
4043 
4044  return *this;
4045  }
4046 
4047  //============================================================================
4048  // Method Description:
4057  NdArray<dtype>& put(const Slice& inRowSlice, const Slice& inColSlice, const NdArray<dtype>& inValues)
4058  {
4059  Slice inRowSliceCopy(inRowSlice);
4060  Slice inColSliceCopy(inColSlice);
4061 
4062  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
4063  inColSliceCopy.makePositiveAndValidate(shape_.cols);
4064 
4065  std::vector<uint32> indices;
4066  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
4067  {
4068  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
4069  {
4070  const uint32 index = row * shape_.cols + col;
4071  indices.push_back(index);
4072  }
4073  }
4074 
4075  return put(NdArray<uint32>(indices), inValues);
4076  }
4077 
4078  //============================================================================
4079  // Method Description:
4088  NdArray<dtype>& put(const Slice& inRowSlice, int32 inColIndex, const NdArray<dtype>& inValues)
4089  {
4090  Slice inRowSliceCopy(inRowSlice);
4091  inRowSliceCopy.makePositiveAndValidate(shape_.rows);
4092 
4093  std::vector<uint32> indices;
4094  for (int32 row = inRowSliceCopy.start; row < inRowSliceCopy.stop; row += inRowSliceCopy.step)
4095  {
4096  const uint32 index = row * shape_.cols + inColIndex;
4097  indices.push_back(index);
4098  }
4099 
4100  return put(NdArray<uint32>(indices), inValues);
4101  }
4102 
4103  //============================================================================
4104  // Method Description:
4113  NdArray<dtype>& put(int32 inRowIndex, const Slice& inColSlice, const NdArray<dtype>& inValues)
4114  {
4115  Slice inColSliceCopy(inColSlice);
4116  inColSliceCopy.makePositiveAndValidate(shape_.cols);
4117 
4118  std::vector<uint32> indices;
4119  for (int32 col = inColSliceCopy.start; col < inColSliceCopy.stop; col += inColSliceCopy.step)
4120  {
4121  const uint32 index = inRowIndex * shape_.cols + col;
4122  indices.push_back(index);
4123  }
4124 
4125  return put(NdArray<uint32>(indices), inValues);
4126  }
4127 
4128  //============================================================================
4129  // Method Description:
4136  {
4137  if (inMask.shape() != shape_)
4138  {
4139  THROW_INVALID_ARGUMENT_ERROR("input inMask must be the same shape as the array it is masking.");
4140  }
4141 
4142  return put(inMask.flatnonzero(), inValue);
4143  }
4144 
4145  //============================================================================
4146  // Method Description:
4152  NdArray<dtype>& putMask(const NdArray<bool>& inMask, const NdArray<dtype>& inValues)
4153  {
4154  if (inMask.shape() != shape_)
4155  {
4156  THROW_INVALID_ARGUMENT_ERROR("input inMask must be the same shape as the array it is masking.");
4157  }
4158 
4159  return put(inMask.flatnonzero(), inValues);
4160  }
4161 
4162  //============================================================================
4163  // Method Description:
4170  NdArray<dtype>& ravel() noexcept
4171  {
4172  reshape(size_);
4173  return *this;
4174  }
4175 
4176  //============================================================================
4177  // Method Description:
4187  NdArray<dtype> repeat(uint32 inNumRows, uint32 inNumCols) const
4188  {
4189  NdArray<dtype> returnArray(shape_.rows * inNumRows, shape_.cols * inNumCols);
4190 
4191  for (uint32 row = 0; row < inNumRows; ++row)
4192  {
4193  for (uint32 col = 0; col < inNumCols; ++col)
4194  {
4195  std::vector<uint32> indices(shape_.size());
4196 
4197  const uint32 rowStart = row * shape_.rows;
4198  const uint32 colStart = col * shape_.cols;
4199 
4200  const uint32 rowEnd = (row + 1) * shape_.rows;
4201  const uint32 colEnd = (col + 1) * shape_.cols;
4202 
4203  uint32 counter = 0;
4204  for (uint32 rowIdx = rowStart; rowIdx < rowEnd; ++rowIdx)
4205  {
4206  for (uint32 colIdx = colStart; colIdx < colEnd; ++colIdx)
4207  {
4208  indices[counter++] = rowIdx * returnArray.shape_.cols + colIdx;
4209  }
4210  }
4211 
4212  returnArray.put(NdArray<uint32>(indices), *this);
4213  }
4214  }
4215 
4216  return returnArray;
4217  }
4218 
4219  //============================================================================
4220  // Method Description:
4230  NdArray<dtype> repeat(const Shape& inRepeatShape) const
4231  {
4232  return repeat(inRepeatShape.rows, inRepeatShape.cols);
4233  }
4234 
4235  //============================================================================
4236  // Method Description:
4242  void replace(value_type oldValue, value_type newValue)
4243  {
4245 
4246  stl_algorithms::replace(begin(), end(), oldValue, newValue);
4247  }
4248 
4249  //============================================================================
4250  // Method Description:
4261  {
4262  if (inSize != size_)
4263  {
4264  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into shape ";
4265  errStr += "[" + utils::num2str(1) + ", " + utils::num2str(inSize) + "]";
4266  THROW_RUNTIME_ERROR(errStr);
4267  }
4268 
4269  shape_.rows = 1;
4270  shape_.cols = inSize;
4271 
4272  return *this;
4273  }
4274 
4275  //============================================================================
4276  // Method Description:
4287  NdArray<dtype>& reshape(int32 inNumRows, int32 inNumCols)
4288  {
4289  if (inNumRows < 0)
4290  {
4291  if (size_ % inNumCols == 0)
4292  {
4293  return reshape(size_ / inNumCols, inNumCols);
4294  }
4295 
4296  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into a shape ";
4297  errStr += "with " + utils::num2str(inNumCols) + " columns";
4299 
4300  }
4301 
4302  if (inNumCols < 0)
4303  {
4304  if (size_ % inNumRows == 0)
4305  {
4306  return reshape(inNumRows, size_ / inNumRows);
4307  }
4308 
4309  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into a shape ";
4310  errStr += "with " + utils::num2str(inNumRows) + " rows";
4312 
4313  }
4314 
4315  if (static_cast<uint32>(inNumRows * inNumCols) != size_)
4316  {
4317  std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into shape ";
4318  errStr += "[" + utils::num2str(inNumRows) + ", " + utils::num2str(inNumCols) + "]";
4320  }
4321 
4322  shape_.rows = static_cast<uint32>(inNumRows);
4323  shape_.cols = static_cast<uint32>(inNumCols);
4324 
4325  return *this;
4326  }
4327 
4328  //============================================================================
4329  // Method Description:
4340  NdArray<dtype>& reshape(const Shape& inShape)
4341  {
4342  return reshape(inShape.rows, inShape.cols);
4343  }
4344 
4345  //============================================================================
4346  // Method Description:
4355  NdArray<dtype>& resizeFast(uint32 inNumRows, uint32 inNumCols)
4356  {
4357  newArray(Shape(inNumRows, inNumCols));
4358  return *this;
4359  }
4360 
4361  //============================================================================
4362  // Method Description:
4371  NdArray<dtype>& resizeFast(const Shape& inShape)
4372  {
4373  return resizeFast(inShape.rows, inShape.cols);
4374  }
4375 
4376  //============================================================================
4377  // Method Description:
4388  NdArray<dtype>& resizeSlow(uint32 inNumRows, uint32 inNumCols)
4389  {
4390  std::vector<dtype> oldData(size_);
4391  stl_algorithms::copy(begin(), end(), oldData.begin());
4392 
4393  const Shape inShape(inNumRows, inNumCols);
4394  const Shape oldShape = shape_;
4395 
4396  newArray(inShape);
4397 
4398  for (uint32 row = 0; row < inShape.rows; ++row)
4399  {
4400  for (uint32 col = 0; col < inShape.cols; ++col)
4401  {
4402  if (row >= oldShape.rows || col >= oldShape.cols)
4403  {
4404  operator()(row, col) = dtype{ 0 }; // zero fill
4405  }
4406  else
4407  {
4408  operator()(row, col) = oldData[row * oldShape.cols + col];
4409  }
4410  }
4411  }
4412 
4413  return *this;
4414  }
4415 
4416  //============================================================================
4417  // Method Description:
4428  NdArray<dtype>& resizeSlow(const Shape& inShape)
4429  {
4430  return resizeSlow(inShape.rows, inShape.cols);
4431  }
4432 
4433  //============================================================================
4434  // Method Description:
4445  NdArray<dtype> round(uint8 inNumDecimals = 0) const
4446  {
4447  STATIC_ASSERT_FLOAT(dtype);
4448 
4449  NdArray<dtype> returnArray(shape_);
4450  const double multFactor = utils::power(10.0, inNumDecimals);
4451  const auto function = [multFactor](dtype value) noexcept -> dtype
4452  {
4453  return static_cast<dtype>(std::nearbyint(static_cast<double>(value) * multFactor) / multFactor);
4454  };
4455 
4456  stl_algorithms::transform(cbegin(), cend(), returnArray.begin(), function);
4457 
4458  return returnArray;
4459  }
4460 
4461  //============================================================================
4462  // Method Description:
4470  {
4471  return NdArray<dtype>(cbegin(inRow), cend(inRow));
4472  }
4473 
4474  //============================================================================
4475  // Method Description:
4483  Shape shape() const noexcept
4484  {
4485  return shape_;
4486  }
4487 
4488  //============================================================================
4489  // Method Description:
4497  size_type size() const noexcept
4498  {
4499  return size_;
4500  }
4501 
4502  //============================================================================
4503  // Method Description:
4514  {
4516 
4517  const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
4518  {
4519  return lhs < rhs;
4520  };
4521 
4522  switch (inAxis)
4523  {
4524  case Axis::NONE:
4525  {
4526  stl_algorithms::sort(begin(), end(), comparitor);
4527  break;
4528  }
4529  case Axis::COL:
4530  {
4531  for (uint32 row = 0; row < shape_.rows; ++row)
4532  {
4533  stl_algorithms::sort(begin(row), end(row), comparitor);
4534  }
4535  break;
4536  }
4537  case Axis::ROW:
4538  {
4539  NdArray<dtype> transposedArray = transpose();
4540  for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
4541  {
4542  stl_algorithms::sort(transposedArray.begin(row), transposedArray.end(row), comparitor);
4543  }
4544 
4545  *this = transposedArray.transpose();
4546  break;
4547  }
4548  }
4549 
4550  return *this;
4551  }
4552 
4553  //============================================================================
4554  // Method Description:
4560  std::string str() const
4561  {
4563 
4564  std::string out;
4565  out += "[";
4566  for (uint32 row = 0; row < shape_.rows; ++row)
4567  {
4568  out += "[";
4569  for (uint32 col = 0; col < shape_.cols; ++col)
4570  {
4571  out += utils::value2str(operator()(row, col)) + ", ";
4572  }
4573 
4574  if (row == shape_.rows - 1)
4575  {
4576  out += "]";
4577  }
4578  else
4579  {
4580  out += "]\n";
4581  }
4582  }
4583  out += "]\n";
4584  return out;
4585  }
4586 
4587  //============================================================================
4588  // Method Description:
4599  {
4601 
4602  switch (inAxis)
4603  {
4604  case Axis::NONE:
4605  {
4606  NdArray<dtype> returnArray = { std::accumulate(cbegin(), cend(), dtype{ 0 }) };
4607  return returnArray;
4608  }
4609  case Axis::COL:
4610  {
4611  NdArray<dtype> returnArray(1, shape_.rows);
4612  for (uint32 row = 0; row < shape_.rows; ++row)
4613  {
4614  returnArray(0, row) = std::accumulate(cbegin(row), cend(row), dtype{ 0 });
4615  }
4616 
4617  return returnArray;
4618  }
4619  case Axis::ROW:
4620  {
4621  NdArray<dtype> transposedArray = transpose();
4622  const Shape transShape = transposedArray.shape();
4623  NdArray<dtype> returnArray(1, transShape.rows);
4624  for (uint32 row = 0; row < transShape.rows; ++row)
4625  {
4626  returnArray(0, row) = std::accumulate(transposedArray.cbegin(row), transposedArray.cend(row), dtype{ 0 });
4627  }
4628 
4629  return returnArray;
4630  }
4631  default:
4632  {
4633  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
4634  return {}; // get rid of compiler warning
4635  }
4636  }
4637  }
4638 
4639  //============================================================================
4640  // Method Description:
4649  {
4650  return transpose();
4651  }
4652 
4653  //============================================================================
4654  // Method Description:
4662 
4666  void tofile(const std::string& inFilename) const
4667  {
4668  dump(inFilename);
4669  }
4670 
4671  //============================================================================
4672  // Method Description:
4684  void tofile(const std::string& inFilename, const char inSep) const
4685  {
4687 
4688  filesystem::File f(inFilename);
4689  if (!f.hasExt())
4690  {
4691  f.withExt("txt");
4692  }
4693 
4694  std::ofstream ofile(f.fullName().c_str());
4695  if (!ofile.good())
4696  {
4697  THROW_RUNTIME_ERROR("Input file could not be opened:\n\t" + inFilename);
4698  }
4699 
4700  uint32 counter = 0;
4701  for (auto value : *this)
4702  {
4703  ofile << value;
4704  if (counter++ != size_ - 1)
4705  {
4706  ofile << inSep;
4707  }
4708  }
4709  ofile.close();
4710  }
4711 
4712  //============================================================================
4713  // Method Description:
4721  NdArray<uint32> toIndices(Slice inSlice, Axis inAxis = Axis::ROW) const
4722  {
4723  uint32 numElements = 0;
4724  switch (inAxis)
4725  {
4726  case Axis::NONE:
4727  {
4728  numElements = inSlice.numElements(size_);
4729  break;
4730  }
4731  case Axis::ROW:
4732  {
4733  numElements = inSlice.numElements(shape_.rows);
4734  break;
4735  }
4736  case Axis::COL:
4737  {
4738  numElements = inSlice.numElements(shape_.cols);
4739  break;
4740  }
4741  default:
4742  {
4743  // not actually possible, getting rid of compiler warning
4744  THROW_INVALID_ARGUMENT_ERROR("Invalid 'inAxis' option");
4745  }
4746  }
4747 
4748  if (numElements == 0)
4749  {
4750  return {};
4751  }
4752 
4753  NdArray<uint32> indices(1, numElements);
4754  indices[0] = inSlice.start;
4755  for (uint32 i = 1; i < indices.size(); ++i)
4756  {
4757  indices[i] = static_cast<uint32>(indices[i - 1] + inSlice.step);
4758  }
4759 
4760  return indices;
4761  }
4762 
4763  //============================================================================
4764  // Method Description:
4770  std::vector<dtype> toStlVector() const
4771  {
4772  return std::vector<dtype>(cbegin(), cend());
4773  }
4774 
4775  //============================================================================
4776  // Method Description:
4787  value_type trace(uint32 inOffset = 0, Axis inAxis = Axis::ROW) const noexcept
4788  {
4790 
4791  uint32 rowStart = 0;
4792  uint32 colStart = 0;
4793  switch (inAxis)
4794  {
4795  case Axis::ROW:
4796  {
4797  rowStart += inOffset;
4798  break;
4799  }
4800  case Axis::COL:
4801  {
4802  colStart += inOffset;
4803  break;
4804  }
4805  default:
4806  {
4807  // if the user input NONE, override back to ROW
4808  inAxis = Axis::ROW;
4809  break;
4810  }
4811  }
4812 
4813  if (rowStart >= shape_.rows || colStart >= shape_.cols)
4814  {
4815  return dtype{ 0 };
4816  }
4817 
4818  uint32 col = colStart;
4819  dtype sum = 0;
4820  for (uint32 row = rowStart; row < shape_.rows; ++row)
4821  {
4822  if (col >= shape_.cols)
4823  {
4824  break;
4825  }
4826  sum += operator()(row, col++);
4827  }
4828 
4829  return sum;
4830  }
4831 
4832  //============================================================================
4833  // Method Description:
4842  {
4843  NdArray<dtype> transArray(shape_.cols, shape_.rows);
4844  for (uint32 row = 0; row < shape_.rows; ++row)
4845  {
4846  for (uint32 col = 0; col < shape_.cols; ++col)
4847  {
4848  transArray(col, row) = operator()(row, col);
4849  }
4850  }
4851  return transArray;
4852  }
4853 
4854  //============================================================================
4855  // Method Description:
4859  NdArray<dtype>& zeros() noexcept
4860  {
4862 
4863  fill(dtype{ 0 });
4864  return *this;
4865  }
4866 
4867  private:
4868  //====================================Attributes==============================
4869  allocator_type allocator_{};
4870  Shape shape_{ 0, 0 };
4871  size_type size_{ 0 };
4872  Endian endianess_{ Endian::NATIVE };
4873  pointer array_{ nullptr };
4874  bool ownsPtr_{ false };
4875 
4876  //============================================================================
4877  // Method Description:
4880  void deleteArray() noexcept
4881  {
4882  if (ownsPtr_ && array_ != nullptr)
4883  {
4884  allocator_.deallocate(array_, size_);
4885  }
4886 
4887  array_ = nullptr;
4888  shape_.rows = shape_.cols = 0;
4889  size_ = 0;
4890  ownsPtr_ = false;
4891  endianess_ = Endian::NATIVE;
4892  }
4893 
4894  //============================================================================
4895  // Method Description:
4898  void newArray()
4899  {
4900  if (size_ > 0)
4901  {
4902  array_ = allocator_.allocate(size_);
4903  ownsPtr_ = true;
4904  }
4905  }
4906 
4907  //============================================================================
4908  // Method Description:
4914  void newArray(const Shape& inShape)
4915  {
4916  deleteArray();
4917 
4918  shape_ = inShape;
4919  size_ = inShape.size();
4920  newArray();
4921  }
4922  };
4923 
4924  // NOTE: this needs to be defined outside of the class to get rid of a compiler
4925  // error in Visual Studio
4926  template<typename dtype, class _Alloc>
4927  std::pair<NdArray<uint32>, NdArray<uint32>> NdArray<dtype, _Alloc>::nonzero() const
4928  {
4930 
4931  std::vector<uint32> rowIndices;
4932  std::vector<uint32> colIndices;
4933 
4934  for (uint32 row = 0; row < shape_.rows; ++row)
4935  {
4936  for (uint32 col = 0; col < shape_.cols; ++col)
4937  {
4938  if (operator()(row, col) != dtype{ 0 })
4939  {
4940  rowIndices.push_back(row);
4941  colIndices.push_back(col);
4942  }
4943  }
4944  }
4945 
4946  return std::make_pair(NdArray<uint32>(rowIndices), NdArray<uint32>(colIndices));
4947  }
4948 } // namespace nc
#define THROW_RUNTIME_ERROR(msg)
Definition: Error.hpp:37
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:36
#define STATIC_ASSERT_FLOAT(dtype)
Definition: StaticAsserts.hpp:43
#define STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype)
Definition: StaticAsserts.hpp:50
#define STATIC_ASSERT_INTEGER(dtype)
Definition: StaticAsserts.hpp:40
#define STATIC_ASSERT_ARITHMETIC(dtype)
Definition: StaticAsserts.hpp:37
Custom column iterator for NdArray.
Definition: NdArrayIterators.hpp:834
Custom column const_iterator for NdArray.
Definition: NdArrayIterators.hpp:503
Custom const_iterator for NdArray.
Definition: NdArrayIterators.hpp:44
Holds 1D and 2D arrays, the main work horse of the NumCpp library.
Definition: NdArrayCore.hpp:72
uint32 numCols() const noexcept
Definition: NdArrayCore.hpp:3602
NdArray(std::vector< std::array< dtype, Dim1Size >> &in2dArray, bool copy=true)
Definition: NdArrayCore.hpp:326
const_reverse_column_iterator rcolbegin() const noexcept
Definition: NdArrayCore.hpp:1502
NdArray< dtype > at(const NdArray< int32 > &rowIndices, const NdArray< int32 > &colIndices) const
Definition: NdArrayCore.hpp:1201
NdArray< dtypeOut > astype() const
Definition: NdArrayCore.hpp:2225
NdArray< dtype > & put(int32 inIndex, value_type inValue)
Definition: NdArrayCore.hpp:3856
size_type size() const noexcept
Definition: NdArrayCore.hpp:4497
reverse_iterator rbegin() noexcept
Definition: NdArrayCore.hpp:1386
NdArray< dtype > & resizeSlow(uint32 inNumRows, uint32 inNumCols)
Definition: NdArrayCore.hpp:4388
NdArray< dtype > & put(const Slice &inRowSlice, const Slice &inColSlice, value_type inValue)
Definition: NdArrayCore.hpp:3979
NdArray< bool > issorted(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3037
const_iterator cbegin() const noexcept
Definition: NdArrayCore.hpp:1270
NdArray< dtype > operator[](const Indices &inIndices) const
Definition: NdArrayCore.hpp:784
const_reference at(int32 inIndex) const
Definition: NdArrayCore.hpp:1050
const_column_iterator ccolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1370
NdArrayConstColumnIterator< dtype, size_type, const_pointer, difference_type > const_column_iterator
Definition: NdArrayCore.hpp:96
NdArray< dtype > round(uint8 inNumDecimals=0) const
Definition: NdArrayCore.hpp:4445
NdArray< bool > any(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1963
const_pointer data() const noexcept
Definition: NdArrayCore.hpp:2689
NdArray< uint32 > toIndices(Slice inSlice, Axis inAxis=Axis::ROW) const
Definition: NdArrayCore.hpp:4721
NdArray< dtype > at(const Slice &inRowSlice, int32 inColIndex) const
Definition: NdArrayCore.hpp:1169
iterator end() noexcept
Definition: NdArrayCore.hpp:1558
NdArray< dtype > operator()(Slice inRowSlice, int32 inColIndex) const
Definition: NdArrayCore.hpp:840
NdArray< dtype > & put(const Slice &inRowSlice, const Slice &inColSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:4057
NdArray(std::vector< dtype > &inVector, bool copy=true)
Definition: NdArrayCore.hpp:266
NdArray(const std::initializer_list< std::initializer_list< dtype > > &inList)
Definition: NdArrayCore.hpp:173
NdArray< dtype > prod(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3744
NdArray< dtype > copy() const
Definition: NdArrayCore.hpp:2541
NdArray< dtype > & resizeFast(const Shape &inShape)
Definition: NdArrayCore.hpp:4371
std::vector< dtype > toStlVector() const
Definition: NdArrayCore.hpp:4770
reference back(size_type row)
Definition: NdArrayCore.hpp:2380
iterator end(size_type inRow)
Definition: NdArrayCore.hpp:1572
NdArray< dtype > flatten() const
Definition: NdArrayCore.hpp:2919
void tofile(const std::string &inFilename, const char inSep) const
Definition: NdArrayCore.hpp:4684
const_column_iterator ccolbegin() const noexcept
Definition: NdArrayCore.hpp:1356
typename AllocTraits::pointer pointer
Definition: NdArrayCore.hpp:83
Slice cSlice(int32 inStartIdx=0, uint32 inStepSize=1) const noexcept
Definition: NdArrayCore.hpp:998
reverse_iterator rbegin(size_type inRow)
Definition: NdArrayCore.hpp:1400
Shape shape() const noexcept
Definition: NdArrayCore.hpp:4483
NdArray< dtype > & byteswap() noexcept
Definition: NdArrayCore.hpp:2394
const_reverse_column_iterator rcolend() const noexcept
Definition: NdArrayCore.hpp:1846
uint32 numRows() const noexcept
Definition: NdArrayCore.hpp:3615
const dtype & const_reference
Definition: NdArrayCore.hpp:86
NdArray< dtype > & put(const Slice &inRowSlice, int32 inColIndex, value_type inValue)
Definition: NdArrayCore.hpp:4009
NdArray< dtype > & partition(uint32 inKth, Axis inAxis=Axis::NONE)
Definition: NdArrayCore.hpp:3660
bool issquare() const noexcept
Definition: NdArrayCore.hpp:3088
NdArrayIterator< dtype, pointer, difference_type > iterator
Definition: NdArrayCore.hpp:90
bool isflat() const noexcept
Definition: NdArrayCore.hpp:3025
Endian endianess() const noexcept
Definition: NdArrayCore.hpp:2860
void tofile(const std::string &inFilename) const
Definition: NdArrayCore.hpp:4666
const_reverse_column_iterator crcolbegin() const noexcept
Definition: NdArrayCore.hpp:1528
const_reverse_column_iterator crcolend(size_type inCol) const
Definition: NdArrayCore.hpp:1886
column_iterator colbegin(size_type inCol)
Definition: NdArrayCore.hpp:1314
NdArrayColumnIterator< dtype, size_type, pointer, difference_type > column_iterator
Definition: NdArrayCore.hpp:95
NdArray< bool > none(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3536
NdArray< dtype > at(const Slice &inSlice) const
Definition: NdArrayCore.hpp:1137
reference at(int32 inIndex)
Definition: NdArrayCore.hpp:1027
NdArray< dtype > & sort(Axis inAxis=Axis::NONE)
Definition: NdArrayCore.hpp:4513
pointer data() noexcept
Definition: NdArrayCore.hpp:2679
bool isempty() const noexcept
Definition: NdArrayCore.hpp:3012
column_iterator colbegin() noexcept
Definition: NdArrayCore.hpp:1300
const_reference front(size_type row) const
Definition: NdArrayCore.hpp:2957
reverse_column_iterator rcolend(size_type inCol)
Definition: NdArrayCore.hpp:1830
NdArray< dtype > sum(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:4598
NdArray(Iterator inFirst, Iterator inLast)
Definition: NdArrayCore.hpp:423
NdArray< dtype > operator[](const Slice &inSlice) const
Definition: NdArrayCore.hpp:732
reverse_column_iterator rcolbegin() noexcept
Definition: NdArrayCore.hpp:1472
NdArrayConstIterator< dtype, const_pointer, difference_type > const_iterator
Definition: NdArrayCore.hpp:91
const_iterator cbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1284
const_column_iterator ccolend(size_type inCol) const
Definition: NdArrayCore.hpp:1800
NdArray< dtype > cumsum(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2621
NdArray< dtype > median(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3239
NdArray< dtype > getByMask(const NdArray< bool > &inMask) const
Definition: NdArrayCore.hpp:2999
const_iterator cend(size_type inRow) const
Definition: NdArrayCore.hpp:1628
NdArray< dtype > column(uint32 inColumn)
Definition: NdArrayCore.hpp:2478
const_reverse_column_iterator rcolend(size_type inCol) const
Definition: NdArrayCore.hpp:1860
NdArray< dtype > & putMask(const NdArray< bool > &inMask, value_type inValue)
Definition: NdArrayCore.hpp:4135
const_iterator end(size_type inRow) const
Definition: NdArrayCore.hpp:1602
reference back() noexcept
Definition: NdArrayCore.hpp:2356
const_reverse_column_iterator crcolend() const noexcept
Definition: NdArrayCore.hpp:1872
const_reference back(size_type row) const
Definition: NdArrayCore.hpp:2368
reverse_column_iterator rcolbegin(size_type inCol)
Definition: NdArrayCore.hpp:1486
NdArray(const std::deque< std::deque< dtype >> &in2dDeque)
Definition: NdArrayCore.hpp:370
NdArray< dtype > & put(int32 inRow, int32 inCol, value_type inValue)
Definition: NdArrayCore.hpp:3873
iterator begin(size_type inRow)
Definition: NdArrayCore.hpp:1228
const_reverse_iterator rend() const noexcept
Definition: NdArrayCore.hpp:1674
NdArray< dtype > clip(value_type inMin, value_type inMax) const
Definition: NdArrayCore.hpp:2438
const_reverse_column_iterator rcolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1516
NdArray< dtype > & operator=(NdArray< dtype > &&rhs) noexcept
Definition: NdArrayCore.hpp:617
typename AllocTraits::difference_type difference_type
Definition: NdArrayCore.hpp:88
NdArray< uint32 > argmin(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2080
const_iterator end() const noexcept
Definition: NdArrayCore.hpp:1588
bool ownsInternalData() noexcept
Definition: NdArrayCore.hpp:3639
NdArray< dtype > & fill(value_type inFillValue) noexcept
Definition: NdArrayCore.hpp:2878
column_iterator colend() noexcept
Definition: NdArrayCore.hpp:1730
NdArray< dtype > operator()(Slice inRowSlice, Slice inColSlice) const
Definition: NdArrayCore.hpp:811
NdArray< dtype > & put(const NdArray< uint32 > &inIndices, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3908
const_reference back() const noexcept
Definition: NdArrayCore.hpp:2344
NdArray< dtype > operator()(int32 inRowIndex, Slice inColSlice) const
Definition: NdArrayCore.hpp:863
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: NdArrayCore.hpp:93
NdArray(const_pointer inPtr, UIntType1 numRows, UIntType2 numCols)
Definition: NdArrayCore.hpp:465
NdArray< dtype > cumprod(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2557
uint64 nbytes() const noexcept
Definition: NdArrayCore.hpp:3354
const_reference at(int32 inRowIndex, int32 inColIndex) const
Definition: NdArrayCore.hpp:1105
NdArray< dtype > transpose() const
Definition: NdArrayCore.hpp:4841
NdArray< dtype > swapaxes() const
Definition: NdArrayCore.hpp:4648
NdArray< dtype > & put(int32 inRowIndex, const Slice &inColSlice, value_type inValue)
Definition: NdArrayCore.hpp:4033
NdArray(const std::list< dtype > &inList)
Definition: NdArrayCore.hpp:403
NdArray()=default
NdArray< dtype > at(int32 inRowIndex, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:1185
const_reference front() const noexcept
Definition: NdArrayCore.hpp:2933
NdArray< dtype > repeat(const Shape &inRepeatShape) const
Definition: NdArrayCore.hpp:4230
~NdArray() noexcept
Definition: NdArrayCore.hpp:558
NdArray< dtype > min(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3180
NdArray(pointer inPtr, uint32 numRows, uint32 numCols, Bool takeOwnership) noexcept
Definition: NdArrayCore.hpp:508
NdArray< dtype > & reshape(const Shape &inShape)
Definition: NdArrayCore.hpp:4340
reference front() noexcept
Definition: NdArrayCore.hpp:2945
NdArray(size_type inNumRows, size_type inNumCols)
Definition: NdArrayCore.hpp:127
Allocator allocator_type
Definition: NdArrayCore.hpp:82
void print() const
Definition: NdArrayCore.hpp:3726
const_reverse_column_iterator crcolbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1542
reverse_iterator rend(size_type inRow)
Definition: NdArrayCore.hpp:1658
NdArray< uint32 > flatnonzero() const
Definition: NdArrayCore.hpp:2892
NdArray(size_type inSquareSize)
Definition: NdArrayCore.hpp:113
NdArray< dtype > operator()(int32 rowIndex, const Indices &colIndices) const
Definition: NdArrayCore.hpp:923
reverse_iterator rend() noexcept
Definition: NdArrayCore.hpp:1644
const_reverse_iterator rend(size_type inRow) const
Definition: NdArrayCore.hpp:1688
NdArray< dtype > getByIndices(const NdArray< uint32 > &inIndices) const
Definition: NdArrayCore.hpp:2983
typename AllocTraits::const_pointer const_pointer
Definition: NdArrayCore.hpp:84
NdArray< dtype > & resizeSlow(const Shape &inShape)
Definition: NdArrayCore.hpp:4428
const_reverse_iterator crbegin() const noexcept
Definition: NdArrayCore.hpp:1442
const_column_iterator colend(size_type inCol) const
Definition: NdArrayCore.hpp:1774
std::reverse_iterator< iterator > reverse_iterator
Definition: NdArrayCore.hpp:92
NdArray(const std::initializer_list< dtype > &inList)
Definition: NdArrayCore.hpp:155
NdArray< dtype > operator()(const Indices &rowIndices, Slice colSlice) const
Definition: NdArrayCore.hpp:906
NdArray(const std::vector< std::vector< dtype >> &in2dVector)
Definition: NdArrayCore.hpp:291
const_reverse_iterator rbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1430
const_iterator cend() const noexcept
Definition: NdArrayCore.hpp:1614
std::string str() const
Definition: NdArrayCore.hpp:4560
std::reverse_iterator< const_column_iterator > const_reverse_column_iterator
Definition: NdArrayCore.hpp:98
reference operator[](int32 inIndex) noexcept
Definition: NdArrayCore.hpp:645
NdArray< dtype > & reshape(int32 inNumRows, int32 inNumCols)
Definition: NdArrayCore.hpp:4287
NdArray(NdArray< dtype > &&inOtherArray) noexcept
Definition: NdArrayCore.hpp:541
NdArray< dtype > & nans() noexcept
Definition: NdArrayCore.hpp:3337
NdArray< dtype > & put(const NdArray< uint32 > &inIndices, value_type inValue)
Definition: NdArrayCore.hpp:3889
NdArray< dtype > ptp(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3799
const_reference operator()(int32 inRowIndex, int32 inColIndex) const noexcept
Definition: NdArrayCore.hpp:707
reference front(size_type row)
Definition: NdArrayCore.hpp:2969
NdArray< dtype > diagonal(int32 inOffset=0, Axis inAxis=Axis::ROW) const
Definition: NdArrayCore.hpp:2718
NdArray< dtype > & putMask(const NdArray< bool > &inMask, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:4152
NdArray< dtype > operator[](const NdArray< bool > &inMask) const
Definition: NdArrayCore.hpp:755
NdArray< dtype > row(uint32 inRow)
Definition: NdArrayCore.hpp:4469
NdArray< dtype > operator()(const Indices &rowIndices, int32 colIndex) const
Definition: NdArrayCore.hpp:888
const_iterator begin(size_type inRow) const
Definition: NdArrayCore.hpp:1258
iterator begin() noexcept
Definition: NdArrayCore.hpp:1214
NdArray< dtype > & put(const Slice &inSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:3955
const_column_iterator colbegin() const noexcept
Definition: NdArrayCore.hpp:1330
NdArray< dtype > max(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3123
std::reverse_iterator< column_iterator > reverse_column_iterator
Definition: NdArrayCore.hpp:97
NdArray< dtype > & operator=(const NdArray< dtype > &rhs)
Definition: NdArrayCore.hpp:572
value_type item() const
Definition: NdArrayCore.hpp:3102
reference operator()(int32 inRowIndex, int32 inColIndex) noexcept
Definition: NdArrayCore.hpp:683
const_column_iterator colend() const noexcept
Definition: NdArrayCore.hpp:1760
NdArray< dtype > & resizeFast(uint32 inNumRows, uint32 inNumCols)
Definition: NdArrayCore.hpp:4355
const_reverse_iterator crend() const noexcept
Definition: NdArrayCore.hpp:1700
NdArray< dtype > & ones() noexcept
Definition: NdArrayCore.hpp:3625
NdArray< dtype > operator()(RowIndices rowIndices, ColIndices colIndices) const
Definition: NdArrayCore.hpp:959
NdArray< dtype > & zeros() noexcept
Definition: NdArrayCore.hpp:4859
const_column_iterator colbegin(size_type inCol) const
Definition: NdArrayCore.hpp:1344
NdArray< dtype > dot(const NdArray< dtype > &inOtherArray) const
Definition: NdArrayCore.hpp:2788
NdArray< dtype > repeat(uint32 inNumRows, uint32 inNumCols) const
Definition: NdArrayCore.hpp:4187
NdArray< dtype > & reshape(size_type inSize)
Definition: NdArrayCore.hpp:4260
NdArray< bool > contains(value_type inValue, Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2492
const_column_iterator ccolend() const noexcept
Definition: NdArrayCore.hpp:1786
NdArray< uint32 > argmax(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2020
value_type trace(uint32 inOffset=0, Axis inAxis=Axis::ROW) const noexcept
Definition: NdArrayCore.hpp:4787
reverse_column_iterator rcolend() noexcept
Definition: NdArrayCore.hpp:1816
NdArray(std::array< dtype, ArraySize > &inArray, bool copy=true)
Definition: NdArrayCore.hpp:209
NdArray< dtype > & put(int32 inRowIndex, const Slice &inColSlice, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:4113
const_reverse_iterator rbegin() const noexcept
Definition: NdArrayCore.hpp:1416
NdArray(const_pointer inPtr, size_type size)
Definition: NdArrayCore.hpp:442
NdArray(const std::deque< dtype > &inDeque)
Definition: NdArrayCore.hpp:353
NdArray(std::array< std::array< dtype, Dim1Size >, Dim0Size > &in2dArray, bool copy=true)
Definition: NdArrayCore.hpp:237
void dump(const std::string &inFilename) const
Definition: NdArrayCore.hpp:2832
dtype & reference
Definition: NdArrayCore.hpp:85
pointer dataRelease() noexcept
Definition: NdArrayCore.hpp:2701
reference at(int32 inRowIndex, int32 inColIndex)
Definition: NdArrayCore.hpp:1073
NdArray< dtype > at(const Slice &inRowSlice, const Slice &inColSlice) const
Definition: NdArrayCore.hpp:1153
NdArray< dtype > operator()(Slice rowSlice, const Indices &colIndices) const
Definition: NdArrayCore.hpp:941
NdArray(const NdArray< dtype > &inOtherArray)
Definition: NdArrayCore.hpp:522
NdArray< uint32 > argsort(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2139
uint32 size_type
Definition: NdArrayCore.hpp:87
const_iterator begin() const noexcept
Definition: NdArrayCore.hpp:1244
NdArray< dtype > & operator=(value_type inValue) noexcept
Definition: NdArrayCore.hpp:598
NdArray< dtype > newbyteorder(Endian inEndianess) const
Definition: NdArrayCore.hpp:3371
column_iterator colend(size_type inCol)
Definition: NdArrayCore.hpp:1744
NdArray< dtype > & put(const Slice &inSlice, value_type inValue)
Definition: NdArrayCore.hpp:3933
const_reference operator[](int32 inIndex) const noexcept
Definition: NdArrayCore.hpp:664
NdArray< dtype > & ravel() noexcept
Definition: NdArrayCore.hpp:4170
dtype value_type
Definition: NdArrayCore.hpp:81
NdArray(pointer inPtr, size_type size, Bool takeOwnership) noexcept
Definition: NdArrayCore.hpp:488
void replace(value_type oldValue, value_type newValue)
Definition: NdArrayCore.hpp:4242
NdArray< dtype > & put(const Slice &inRowSlice, int32 inColIndex, const NdArray< dtype > &inValues)
Definition: NdArrayCore.hpp:4088
Slice rSlice(int32 inStartIdx=0, uint32 inStepSize=1) const noexcept
Definition: NdArrayCore.hpp:1013
const_reverse_iterator crend(size_type inRow) const
Definition: NdArrayCore.hpp:1714
const_reverse_iterator crbegin(size_type inRow) const
Definition: NdArrayCore.hpp:1456
NdArray(const Shape &inShape)
Definition: NdArrayCore.hpp:141
NdArray< bool > all(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:1907
Custom iterator for NdArray.
Definition: NdArrayIterators.hpp:324
A Shape Class for NdArrays.
Definition: Core/Shape.hpp:41
uint32 rows
Definition: Core/Shape.hpp:44
uint32 cols
Definition: Core/Shape.hpp:45
uint32 size() const noexcept
Definition: Core/Shape.hpp:102
A Class for slicing into NdArrays.
Definition: Slice.hpp:44
int32 step
Definition: Slice.hpp:49
int32 start
Definition: Slice.hpp:47
void makePositiveAndValidate(uint32 inArraySize)
Definition: Slice.hpp:137
uint32 numElements(uint32 inArraySize)
Definition: Slice.hpp:188
int32 stop
Definition: Slice.hpp:48
Provides simple filesystem functions.
Definition: Filesystem.hpp:40
constexpr auto j
Definition: Constants.hpp:45
const double nan
NaN.
Definition: Constants.hpp:44
bool isLittleEndian() noexcept
Definition: Endian.hpp:44
dtype byteSwap(dtype value) noexcept
Definition: Endian.hpp:63
dtype f(dtype inDofN, dtype inDofD)
Definition: f.hpp:56
bool any_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:76
void sort(RandomIt first, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:629
bool none_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:379
ForwardIt max_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:268
void stable_sort(RandomIt first, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:664
OutputIt transform(InputIt first, InputIt last, OutputIt destination, UnaryOperation unaryFunction)
Definition: StlAlgorithms.hpp:702
bool all_of(InputIt first, InputIt last, UnaryPredicate p) noexcept
Definition: StlAlgorithms.hpp:57
void for_each(InputIt first, InputIt last, UnaryFunction f)
Definition: StlAlgorithms.hpp:213
InputIt find(InputIt first, InputIt last, const T &value) noexcept
Definition: StlAlgorithms.hpp:195
constexpr OutputIt unique_copy(InputIt first, InputIt last, OutputIt destination) noexcept
Definition: StlAlgorithms.hpp:744
std::pair< ForwardIt, ForwardIt > minmax_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:341
void replace(ForwardIt first, ForwardIt last, const T &oldValue, const T &newValue) noexcept
Definition: StlAlgorithms.hpp:435
bool is_sorted(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:231
OutputIt copy(InputIt first, InputIt last, OutputIt destination) noexcept
Definition: StlAlgorithms.hpp:95
void nth_element(RandomIt first, RandomIt nth, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:397
ForwardIt min_element(ForwardIt first, ForwardIt last) noexcept
Definition: StlAlgorithms.hpp:304
void fill(ForwardIt first, ForwardIt last, const T &value) noexcept
Definition: StlAlgorithms.hpp:174
std::string num2str(dtype inNumber)
Definition: num2str.hpp:46
dtype power(dtype inValue, uint8 inPower) noexcept
Definition: Utils/power.hpp:48
std::string value2str(dtype inValue)
Definition: value2str.hpp:48
Definition: Coordinate.hpp:45
NdArray< dtype > repeat(const NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition: repeat.hpp:50
std::pair< NdArray< uint32 >, NdArray< uint32 > > nonzero(const NdArray< dtype > &inArray)
Definition: nonzero.hpp:50
NdArray< dtype > & resizeFast(NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition: resizeFast.hpp:51
Axis
Enum To describe an axis.
Definition: Types.hpp:46
NdArray< dtype > & reshape(NdArray< dtype > &inArray, uint32 inSize)
Definition: reshape.hpp:52
std::int64_t int64
Definition: Types.hpp:35
auto abs(dtype inValue) noexcept
Definition: abs.hpp:51
std::uint64_t uint64
Definition: Types.hpp:39
NdArray< dtype > & resizeSlow(NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition: resizeSlow.hpp:53
Endian
Enum for endianess.
Definition: Types.hpp:50
std::int32_t int32
Definition: Types.hpp:36
std::uint8_t uint8
Definition: Types.hpp:42
NdArray< dtype > sum(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition: sum.hpp:47
NdArray< dtype > & put(NdArray< dtype > &inArray, const NdArray< uint32 > &inIndices, dtype inValue)
Definition: put.hpp:49
NdArray< dtype > transpose(const NdArray< dtype > &inArray)
Definition: transpose.hpp:47
typename std::enable_if< B, T >::type enable_if_t
Definition: TypeTraits.hpp:40
std::uint32_t uint32
Definition: Types.hpp:40
void dump(const NdArray< dtype > &inArray, const std::string &inFilename)
Definition: dump.hpp:47