NumCpp  2.14.0
A Templatized Header Only C++ Implementation of the Python NumPy Library
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
NdArrayCore.hpp
Go to the documentation of this file.
1
28#pragma once
29
30#include <array>
31#include <cmath>
32#include <deque>
33#include <filesystem>
34#include <forward_list>
35#include <fstream>
36#include <initializer_list>
37#include <iostream>
38#include <iterator>
39#include <list>
40#include <memory>
41#include <numeric>
42#include <set>
43#include <string>
44#include <type_traits>
45#include <utility>
46#include <vector>
47
50#include "NumCpp/Core/Enums.hpp"
57#include "NumCpp/Core/Shape.hpp"
58#include "NumCpp/Core/Slice.hpp"
59#include "NumCpp/Core/Types.hpp"
65#include "NumCpp/Utils/sqr.hpp"
67
68namespace nc
69{
70 namespace type_traits
71 {
72 //============================================================================
73 // Class Description:
76 template<typename>
77 struct is_ndarray_int : std::false_type
78 {
79 };
80
81 //============================================================================
82 // Class Description:
85
86 template<typename dtype, typename Allocator>
88 {
89 static constexpr bool value = std::is_integral_v<dtype>;
90 };
91
92 //============================================================================
93 // Class Description:
96 template<typename T>
98
99 //============================================================================
100 // Class Description:
103 template<typename>
104 struct is_ndarray_signed_int : std::false_type
105 {
106 };
107
108 //============================================================================
109 // Class Description:
112
113 template<typename dtype, typename Allocator>
115 {
116 static constexpr bool value = std::is_signed_v<dtype>;
117 };
118
119 //============================================================================
120 // Class Description:
123 template<typename T>
125
126 //============================================================================
127 // Class Description:
130 template<typename T>
131 using ndarray_int_concept = std::enable_if_t<is_ndarray_int_v<T>, int>;
132 } // namespace type_traits
133
134 //================================================================================
135 // Class Description:
137 template<typename dtype, class Allocator = std::allocator<dtype>>
139 {
140 private:
142 static_assert(std::is_same_v<dtype, typename Allocator::value_type>,
143 "value_type and Allocator::value_type must match");
144
145 using AllocType = typename std::allocator_traits<Allocator>::template rebind_alloc<dtype>;
146 using AllocTraits = std::allocator_traits<AllocType>;
147
148 public:
152 using pointer = typename AllocTraits::pointer;
153 using const_pointer = typename AllocTraits::const_pointer;
154 using reference = dtype&;
155 using const_reference = const dtype&;
158 using difference_type = typename AllocTraits::difference_type;
159
162 using reverse_iterator = std::reverse_iterator<iterator>;
163 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
164
167 using reverse_column_iterator = std::reverse_iterator<column_iterator>;
168 using const_reverse_column_iterator = std::reverse_iterator<const_column_iterator>;
169
170 //============================================================================
171 // Method Description:
174 NdArray() = default;
175
176 //============================================================================
177 // Method Description:
183 shape_{ inSquareSize, inSquareSize },
184 size_{ inSquareSize * inSquareSize }
185 {
186 newArray();
187 }
188
189 //============================================================================
190 // Method Description:
197 shape_{ inNumRows, inNumCols },
198 size_{ inNumRows * inNumCols }
199 {
200 newArray();
201 }
202
203 //============================================================================
204 // Method Description:
209 explicit NdArray(const Shape& inShape) :
210 shape_{ inShape },
211 size_{ shape_.size() }
212 {
213 newArray();
214 }
215
216 //============================================================================
217 // Method Description:
222 NdArray(std::initializer_list<dtype> inList) :
223 shape_{ 1, static_cast<uint32>(inList.size()) },
224 size_{ shape_.size() }
225 {
226 newArray();
227 if (size_ > 0)
228 {
229 stl_algorithms::copy(inList.begin(), inList.end(), begin());
230 }
231 }
232
233 //============================================================================
234 // Method Description:
239 NdArray(const std::initializer_list<std::initializer_list<dtype>>& inList) :
240 shape_{ static_cast<uint32>(inList.size()), 0 }
241 {
242 for (const auto& list : inList)
243 {
244 if (shape_.cols == 0)
245 {
246 shape_.cols = static_cast<uint32>(list.size());
247 }
248 else if (list.size() != shape_.cols)
249 {
251 "All rows of the initializer list needs to have the same number of elements");
252 }
253 }
254
255 size_ = shape_.size();
256 newArray();
257 uint32 row = 0;
258 for (const auto& list : inList)
259 {
260 const auto ptr = begin() += row * shape_.cols;
261 stl_algorithms::copy(list.begin(), list.end(), ptr);
262 ++row;
263 }
264 }
265
266 //============================================================================
267 // Method Description:
273 template<size_t ArraySize, std::enable_if_t<is_valid_dtype_v<dtype>, int> = 0>
274 NdArray(std::array<dtype, ArraySize>& inArray, PointerPolicy policy = PointerPolicy::COPY) :
275 shape_{ 1, static_cast<uint32>(ArraySize) },
276 size_{ shape_.size() }
277 {
278 switch (policy)
279 {
281 {
282 newArray();
283 if (size_ > 0)
284 {
285 stl_algorithms::copy(inArray.begin(), inArray.end(), begin());
286 }
287 break;
288 }
290 {
291 array_ = inArray.data();
292 ownsPtr_ = false;
293 break;
294 }
295 default:
296 {
297 THROW_RUNTIME_ERROR("Unimplemented PointerPolicy type");
298 }
299 }
300 }
301
302 //============================================================================
303 // Method Description:
309 template<size_t Dim0Size, size_t Dim1Size>
310 NdArray(std::array<std::array<dtype, Dim1Size>, Dim0Size>& in2dArray,
313 size_{ shape_.size() }
314 {
315 switch (policy)
316 {
318 {
319 newArray();
320 if (size_ > 0)
321 {
322 const auto start = in2dArray.front().begin();
323 stl_algorithms::copy(start, start + size_, begin());
324 }
325 break;
326 }
328 {
329 array_ = in2dArray.front().data();
330 ownsPtr_ = false;
331 break;
332 }
333 default:
334 {
335 THROW_RUNTIME_ERROR("Unimplemented PointerPolicy type");
336 }
337 }
338 }
339
340 //============================================================================
341 // Method Description:
347 template<std::enable_if_t<is_valid_dtype_v<dtype>, int> = 0>
349 shape_{ 1, static_cast<uint32>(inVector.size()) },
350 size_{ shape_.size() }
351 {
352 switch (policy)
353 {
355 {
356 newArray();
357 if (size_ > 0)
358 {
359 stl_algorithms::copy(inVector.begin(), inVector.end(), begin());
360 }
361 break;
362 }
364 {
365 array_ = inVector.data();
366 ownsPtr_ = false;
367 break;
368 }
369 default:
370 {
371 THROW_RUNTIME_ERROR("Unimplemented PointerPolicy type");
372 }
373 }
374 }
375
376 //============================================================================
377 // Method Description:
382 explicit NdArray(const std::vector<std::vector<dtype>>& in2dVector) :
383 shape_{ static_cast<uint32>(in2dVector.size()), 0 }
384 {
385 for (const auto& row : in2dVector)
386 {
387 if (shape_.cols == 0)
388 {
389 shape_.cols = static_cast<uint32>(row.size());
390 }
391 else if (row.size() != shape_.cols)
392 {
393 THROW_INVALID_ARGUMENT_ERROR("All rows of the 2d vector need to have the same number of elements");
394 }
395 }
396
397 size_ = shape_.size();
398
399 newArray();
400 auto currentPosition = begin();
401 for (const auto& row : in2dVector)
402 {
404 currentPosition += shape_.cols;
405 }
406 }
407
408 //============================================================================
409 // Method Description:
415 template<size_t Dim1Size>
416 NdArray(std::vector<std::array<dtype, Dim1Size>>& in2dArray, PointerPolicy policy = PointerPolicy::COPY) :
418 size_{ shape_.size() }
419 {
420 switch (policy)
421 {
423 {
424 newArray();
425 if (size_ > 0)
426 {
427 const auto start = in2dArray.front().begin();
428 stl_algorithms::copy(start, start + size_, begin());
429 }
430 break;
431 }
433 {
434 array_ = in2dArray.front().data();
435 ownsPtr_ = false;
436 break;
437 }
438 default:
439 {
440 THROW_RUNTIME_ERROR("Unimplemented PointerPolicy type");
441 }
442 }
443 }
444
445 //============================================================================
446 // Method Description:
451 template<std::enable_if_t<is_valid_dtype_v<dtype>, int> = 0>
452 explicit NdArray(const std::deque<dtype>& inDeque) :
453 shape_{ 1, static_cast<uint32>(inDeque.size()) },
454 size_{ shape_.size() }
455 {
456 newArray();
457 if (size_ > 0)
458 {
459 stl_algorithms::copy(inDeque.begin(), inDeque.end(), begin());
460 }
461 }
462
463 //============================================================================
464 // Method Description:
469 explicit NdArray(const std::deque<std::deque<dtype>>& in2dDeque) :
470 shape_{ static_cast<uint32>(in2dDeque.size()), 0 }
471 {
472 for (const auto& row : in2dDeque)
473 {
474 if (shape_.cols == 0)
475 {
476 shape_.cols = static_cast<uint32>(row.size());
477 }
478 else if (row.size() != shape_.cols)
479 {
480 THROW_INVALID_ARGUMENT_ERROR("All rows of the 2d vector need to have the same number of elements");
481 }
482 }
483
484 size_ = shape_.size();
485
486 newArray();
487 auto currentPosition = begin();
488 for (const auto& row : in2dDeque)
489 {
491 currentPosition += shape_.cols;
492 }
493 }
494
495 //============================================================================
496 // Method Description:
501 explicit NdArray(const std::list<dtype>& inList) :
502 shape_{ 1, static_cast<uint32>(inList.size()) },
503 size_{ shape_.size() }
504 {
505 newArray();
506 if (size_ > 0)
507 {
508 stl_algorithms::copy(inList.begin(), inList.end(), begin());
509 }
510 }
511
512 //============================================================================
513 // Method Description:
519 template<typename Iterator,
520 std::enable_if_t<std::is_same_v<typename std::iterator_traits<Iterator>::value_type, dtype>, int> = 0>
522 shape_{ 1, static_cast<uint32>(std::distance(inFirst, inLast)) },
523 size_{ shape_.size() }
524 {
525 newArray();
526 if (size_ > 0)
527 {
529 }
530 }
531
532 //============================================================================
533 // Method Description:
539 template<typename UIntType,
540 std::enable_if_t<std::is_integral_v<UIntType> && !std::is_same_v<UIntType, bool>, int> = 0>
545
546 //============================================================================
547 // Method Description:
554 template<typename UIntType1,
555 typename UIntType2,
556 std::enable_if_t<std::is_integral_v<UIntType1> && !std::is_same_v<UIntType1, bool>, int> = 0,
557 std::enable_if_t<std::is_integral_v<UIntType2> && !std::is_same_v<UIntType2, bool>, int> = 0>
559 shape_(numRows, numCols),
560 size_{ shape_.size() }
561 {
562 newArray();
563 if (inPtr != nullptr && size_ > 0)
564 {
566 }
567 }
568
569 //============================================================================
570 // Method Description:
578 template<typename UIntType,
579 std::enable_if_t<std::is_integral_v<UIntType> && !std::is_same_v<UIntType, bool>, int> = 0>
584
585 //============================================================================
586 // Method Description:
595 template<typename UIntType1,
596 typename UIntType2,
597 std::enable_if_t<std::is_integral_v<UIntType1> && !std::is_same_v<UIntType1, bool>, int> = 0,
598 std::enable_if_t<std::is_integral_v<UIntType2> && !std::is_same_v<UIntType2, bool>, int> = 0>
600 shape_(numRows, numCols),
601 size_{ shape_.size() }
602 {
603 switch (policy)
604 {
606 {
607 newArray();
608 if (inPtr != nullptr && size_ > 0)
609 {
611 }
612 break;
613 }
615 {
616 array_ = inPtr;
617 ownsPtr_ = false;
618 break;
619 }
620 default:
621 {
622 THROW_RUNTIME_ERROR("Unimplemented PointerPolicy type");
623 }
624 }
625 }
626
627 //============================================================================
628 // Method Description:
634 shape_{ inOtherArray.shape_ },
635 size_{ inOtherArray.size_ },
636 endianess_{ inOtherArray.endianess_ }
637 {
638 newArray();
639 if (size_ > 0)
640 {
642 }
643 }
644
645 //============================================================================
646 // Method Description:
652 shape_{ inOtherArray.shape_ },
653 size_{ inOtherArray.size_ },
654 endianess_{ inOtherArray.endianess_ },
655 array_{ inOtherArray.array_ },
656 ownsPtr_{ inOtherArray.ownsPtr_ }
657 {
658 inOtherArray.shape_.rows = inOtherArray.shape_.cols = 0;
659 inOtherArray.size_ = 0;
660 inOtherArray.ownsPtr_ = false;
661 inOtherArray.array_ = nullptr;
662 }
663
664 //============================================================================
665 // Method Description:
669 {
670 deleteArray();
671 }
672
673 //============================================================================
674 // Method Description:
678 explicit operator bool() const noexcept
679 {
680 return isempty();
681 }
682
683 //============================================================================
684 // Method Description:
691 {
692 if (&rhs != this)
693 {
694 if (rhs.size_ > 0)
695 {
696 newArray(rhs.shape_);
697 endianess_ = rhs.endianess_;
698
699 stl_algorithms::copy(rhs.cbegin(), rhs.cend(), begin());
700 }
701 }
702
703 return *this;
704 }
705
706 //============================================================================
707 // Method Description:
715 {
716 if (array_ != nullptr)
717 {
719 }
720
721 return *this;
722 }
723
724 //============================================================================
725 // Method Description:
732 {
733 if (&rhs != this)
734 {
735 deleteArray();
736 shape_ = rhs.shape_;
737 size_ = rhs.size_;
738 endianess_ = rhs.endianess_;
739 array_ = rhs.array_;
740 ownsPtr_ = rhs.ownsPtr_;
741
742 rhs.shape_.rows = rhs.shape_.cols = rhs.size_ = 0;
743 rhs.array_ = nullptr;
744 rhs.ownsPtr_ = false;
745 }
746
747 return *this;
748 }
749
750 //============================================================================
751 // Method Description:
758 {
759 return const_cast<reference>(const_cast<const self_type*>(this)->operator[](inIndex));
760 }
761
762 //============================================================================
763 // Method Description:
770 {
771 if (inIndex < 0)
772 {
773 inIndex += size_;
774 }
775
776 return array_[inIndex];
777 }
778
779 //============================================================================
780 // Method Description:
788 {
789 return const_cast<reference>(const_cast<const self_type*>(this)->operator()(inRowIndex, inColIndex));
790 }
791
792 //============================================================================
793 // Method Description:
801 {
802 if (inRowIndex < 0)
803 {
804 inRowIndex += shape_.rows;
805 }
806
807 if (inColIndex < 0)
808 {
809 inColIndex += shape_.cols;
810 }
811
812 return array_[inRowIndex * shape_.cols + inColIndex];
813 }
814
815 //============================================================================
816 // Method Description:
827
828 //============================================================================
829 // Method Description:
836 {
837 return operator[](inMask.flatnonzero());
838 }
839
840 //============================================================================
841 // Method Description:
848 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
850 {
851 auto outArray = self_type(1, static_cast<size_type>(inIndices.size()));
852 size_type i = 0;
853 for (auto& index : inIndices)
854 {
855 outArray[i++] = operator[](static_cast<index_type>(index));
856 }
857
858 return outArray;
859 }
860
861 //============================================================================
862 // Method Description:
874
875 //============================================================================
876 // Method Description:
889
890 //============================================================================
891 // Method Description:
904
905 //============================================================================
906 // Method Description:
914 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
920
921 //============================================================================
922 // Method Description:
930 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
935
936 //============================================================================
937 // Method Description:
945 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
951
952 //============================================================================
953 // Method Description:
961 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
966
967 //============================================================================
968 // Method Description:
976 template<typename RowIndices,
977 typename ColIndices,
981 {
983
985 for (auto rowIter = rowIndices.begin(); rowIter != rowIndices.end(); ++rowIter)
986 {
988 for (auto colIter = colIndices.begin(); colIter != colIndices.end(); ++colIter)
989 {
991 }
992
993 ++rowCounter;
994 }
995
996 return returnArray;
997 }
998
999 //============================================================================
1000 // Method Description:
1009 {
1010 return Slice(inStartIdx, shape_.cols, inStepSize); // NOLINT(modernize-return-braced-init-list)
1011 }
1012
1013 //============================================================================
1014 // Method Description:
1023 {
1024 return Slice(inStartIdx, shape_.rows, inStepSize); // NOLINT(modernize-return-braced-init-list)
1025 }
1026
1027 //============================================================================
1028 // Method Description:
1035 {
1036 return const_cast<reference>(const_cast<const self_type*>(this)->at(inIndex));
1037 }
1038
1039 //============================================================================
1040 // Method Description:
1047 {
1048 // this doesn't allow for calling the first element as -size_...
1049 // but why would you really want to do that anyway?
1050 if (std::abs(inIndex) > static_cast<int64>(size_ - 1))
1051 {
1052 std::string errStr = "Input index " + utils::num2str(inIndex);
1053 errStr += " is out of bounds for array of size " + utils::num2str(size_) + ".";
1055 }
1056
1057 return operator[](inIndex); // cppcheck-suppress returnTempReference
1058 }
1059
1060 //============================================================================
1061 // Method Description:
1069 {
1070 return const_cast<reference>(const_cast<const self_type*>(this)->at(inRowIndex, inColIndex));
1071 }
1072
1073 //============================================================================
1074 // Method Description:
1082 {
1083 // this doesn't allow for calling the first element as -size_...
1084 // but why would you really want to do that anyway?
1085 if (std::abs(inRowIndex) > static_cast<index_type>(shape_.rows - 1))
1086 {
1087 std::string errStr = "Row index " + utils::num2str(inRowIndex);
1088 errStr += " is out of bounds for array of size " + utils::num2str(shape_.rows) + ".";
1090 }
1091
1092 // this doesn't allow for calling the first element as -size_...
1093 // but why would you really want to do that anyway?
1094 if (std::abs(inColIndex) > static_cast<index_type>(shape_.cols - 1))
1095 {
1096 std::string errStr = "Column index " + utils::num2str(inColIndex);
1097 errStr += " is out of bounds for array of size " + utils::num2str(shape_.cols) + ".";
1099 }
1100
1101 return operator()(inRowIndex, inColIndex); // cppcheck-suppress returnTempReference
1102 }
1103
1104 //============================================================================
1105 // Method Description:
1112 {
1113 return at(toIndices(inSlice, Axis::NONE));
1114 }
1115
1116 //============================================================================
1117 // Method Description:
1124 {
1125 if (inMask.shape() != shape_)
1126 {
1127 THROW_INVALID_ARGUMENT_ERROR("Input mask must have the same dimensions as array.");
1128 }
1129
1130 return operator[](inMask);
1131 }
1132
1133 //============================================================================
1134 // Method Description:
1140 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
1142 {
1144 inIndices.end(),
1145 [this](auto index)
1146 {
1147 auto indexSigned = static_cast<index_type>(index);
1148 if (indexSigned < 0)
1149 {
1150 indexSigned += size_;
1151 }
1152
1153 if (indexSigned < 0 || indexSigned > static_cast<index_type>(size_ - 1))
1154 {
1155 THROW_INVALID_ARGUMENT_ERROR("Index exceeds matrix dimensions");
1156 }
1157 });
1158
1159 return operator[](inIndices);
1160 }
1161
1162 //============================================================================
1163 // Method Description:
1171 {
1172 return at(toIndices(inRowSlice, Axis::ROW), toIndices(inColSlice, Axis::COL));
1173 }
1174
1175 //============================================================================
1176 // Method Description:
1184 {
1186 return at(toIndices(inRowSlice, Axis::ROW), colIndices);
1187 }
1188
1189 //============================================================================
1190 // Method Description:
1198 {
1200 return at(rowIndices, toIndices(inColSlice, Axis::COL));
1201 }
1202
1203 //============================================================================
1204 // Method Description:
1211 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
1213 {
1215 return at(rowIndices, colIndices);
1216 }
1217
1218 //============================================================================
1219 // Method Description:
1226 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
1228 {
1229 return at(rowIndices, toIndices(colSlice, Axis::COL));
1230 }
1231
1232 //============================================================================
1233 // Method Description:
1240 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
1242 {
1244 return at(rowIndices, colIndices);
1245 }
1246
1247 //============================================================================
1248 // Method Description:
1255 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
1257 {
1258 return at(toIndices(rowSlice, Axis::ROW), colIndices);
1259 }
1260
1261 //============================================================================
1262 // Method Description:
1269 template<typename RowIndices,
1270 typename ColIndices,
1274 {
1276 rowIndices.end(),
1277 [this](auto row)
1278 {
1279 auto rowSigned = static_cast<index_type>(row);
1280 if (rowSigned < 0)
1281 {
1282 rowSigned += shape_.rows;
1283 }
1284
1285 if (rowSigned < 0 || rowSigned > static_cast<index_type>(shape_.rows - 1))
1286 {
1287 THROW_INVALID_ARGUMENT_ERROR("Row index exceeds matrix dimensions");
1288 }
1289 });
1290
1292 colIndices.end(),
1293 [this](auto col)
1294 {
1295 auto colSigned = static_cast<index_type>(col);
1296 if (colSigned < 0)
1297 {
1298 colSigned += shape_.cols;
1299 }
1300
1301 if (colSigned < 0 || colSigned > static_cast<index_type>(shape_.cols - 1))
1302 {
1303 THROW_INVALID_ARGUMENT_ERROR("Column index exceeds matrix dimensions");
1304 }
1305 });
1306
1307 return operator()(rowIndices, colIndices);
1308 }
1309
1310 //============================================================================
1311 // Method Description:
1315 [[nodiscard]] iterator begin() noexcept
1316 {
1317 return iterator(array_);
1318 }
1319
1320 //============================================================================
1321 // Method Description:
1327 [[nodiscard]] iterator begin(size_type inRow)
1328 {
1329 if (inRow >= shape_.rows)
1330 {
1331 THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1332 }
1333
1334 return begin() += (inRow * shape_.cols);
1335 }
1336
1337 //============================================================================
1338 // Method Description:
1342 [[nodiscard]] const_iterator begin() const noexcept
1343 {
1344 return cbegin();
1345 }
1346
1347 //============================================================================
1348 // Method Description:
1354 [[nodiscard]] const_iterator begin(size_type inRow) const
1355 {
1356 return cbegin(inRow);
1357 }
1358
1359 //============================================================================
1360 // Method Description:
1365 [[nodiscard]] const_iterator cbegin() const noexcept
1366 {
1367 return const_iterator(array_);
1368 }
1369
1370 //============================================================================
1371 // Method Description:
1377 [[nodiscard]] const_iterator cbegin(size_type inRow) const
1378 {
1379 if (inRow >= shape_.rows)
1380 {
1381 THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1382 }
1383
1384 return cbegin() += (inRow * shape_.cols);
1385 }
1386
1387 //============================================================================
1388 // Method Description:
1392 [[nodiscard]] column_iterator colbegin() noexcept
1393 {
1394 return column_iterator(array_, shape_.rows, shape_.cols);
1395 }
1396
1397 //============================================================================
1398 // Method Description:
1405 {
1406 if (inCol >= shape_.cols)
1407 {
1408 THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1409 }
1410
1411 return colbegin() += (inCol * shape_.rows);
1412 }
1413
1414 //============================================================================
1415 // Method Description:
1419 [[nodiscard]] const_column_iterator colbegin() const noexcept
1420 {
1421 return ccolbegin();
1422 }
1423
1424 //============================================================================
1425 // Method Description:
1431 [[nodiscard]] const_column_iterator colbegin(size_type inCol) const
1432 {
1433 return ccolbegin(inCol);
1434 }
1435
1436 //============================================================================
1437 // Method Description:
1442 [[nodiscard]] const_column_iterator ccolbegin() const noexcept
1443 {
1444 return const_column_iterator(array_, shape_.rows, shape_.cols);
1445 }
1446
1447 //============================================================================
1448 // Method Description:
1454 [[nodiscard]] const_column_iterator ccolbegin(size_type inCol) const
1455 {
1456 if (inCol >= shape_.cols)
1457 {
1458 THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1459 }
1460
1461 return ccolbegin() += (inCol * shape_.rows);
1462 }
1463
1464 //============================================================================
1465 // Method Description:
1469 [[nodiscard]] reverse_iterator rbegin() noexcept
1470 {
1471 return reverse_iterator(end());
1472 }
1473
1474 //============================================================================
1475 // Method Description:
1481 [[nodiscard]] reverse_iterator rbegin(size_type inRow)
1482 {
1483 if (inRow >= shape_.rows)
1484 {
1485 THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1486 }
1487
1488 return rbegin() += (shape_.rows - inRow - 1) * shape_.cols;
1489 }
1490
1491 //============================================================================
1492 // Method Description:
1496 [[nodiscard]] const_reverse_iterator rbegin() const noexcept
1497 {
1498 return crbegin();
1499 }
1500
1501 //============================================================================
1502 // Method Description:
1508 [[nodiscard]] const_reverse_iterator rbegin(size_type inRow) const
1509 {
1510 return crbegin(inRow);
1511 }
1512
1513 //============================================================================
1514 // Method Description:
1519 [[nodiscard]] const_reverse_iterator crbegin() const noexcept
1520 {
1521 return const_reverse_iterator(cend());
1522 }
1523
1524 //============================================================================
1525 // Method Description:
1531 [[nodiscard]] const_reverse_iterator crbegin(size_type inRow) const
1532 {
1533 if (inRow >= shape_.rows)
1534 {
1535 THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1536 }
1537
1538 return crbegin() += (shape_.rows - inRow - 1) * shape_.cols;
1539 }
1540
1541 //============================================================================
1542 // Method Description:
1546 [[nodiscard]] reverse_column_iterator rcolbegin() noexcept
1547 {
1548 return reverse_column_iterator(colend());
1549 }
1550
1551 //============================================================================
1552 // Method Description:
1559 {
1560 if (inCol >= shape_.cols)
1561 {
1562 THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1563 }
1564
1565 return rcolbegin() += (shape_.cols - inCol - 1) * shape_.rows;
1566 }
1567
1568 //============================================================================
1569 // Method Description:
1573 [[nodiscard]] const_reverse_column_iterator rcolbegin() const noexcept
1574 {
1575 return crcolbegin();
1576 }
1577
1578 //============================================================================
1579 // Method Description:
1586 {
1587 return crcolbegin(inCol);
1588 }
1589
1590 //============================================================================
1591 // Method Description:
1596 [[nodiscard]] const_reverse_column_iterator crcolbegin() const noexcept
1597 {
1598 return const_reverse_column_iterator(ccolend());
1599 }
1600
1601 //============================================================================
1602 // Method Description:
1609 {
1610 if (inCol >= shape_.cols)
1611 {
1612 THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1613 }
1614
1615 return crcolbegin() += (shape_.cols - inCol - 1) * shape_.rows;
1616 }
1617
1618 //============================================================================
1619 // Method Description:
1623 [[nodiscard]] iterator end() noexcept
1624 {
1625 return begin() += size_;
1626 }
1627
1628 //============================================================================
1629 // Method Description:
1635 [[nodiscard]] iterator end(size_type inRow)
1636 {
1637 if (inRow >= shape_.rows)
1638 {
1639 THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1640 }
1641
1642 return begin(inRow) += shape_.cols;
1643 }
1644
1645 //============================================================================
1646 // Method Description:
1650 [[nodiscard]] const_iterator end() const noexcept
1651 {
1652 return cend();
1653 }
1654
1655 //============================================================================
1656 // Method Description:
1662 [[nodiscard]] const_iterator end(size_type inRow) const
1663 {
1664 return cend(inRow);
1665 }
1666
1667 //============================================================================
1668 // Method Description:
1673 [[nodiscard]] const_iterator cend() const noexcept
1674 {
1675 return cbegin() += size_;
1676 }
1677
1678 //============================================================================
1679 // Method Description:
1685 [[nodiscard]] const_iterator cend(size_type inRow) const
1686 {
1687 if (inRow >= shape_.rows)
1688 {
1689 THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1690 }
1691
1692 return cbegin(inRow) += shape_.cols;
1693 }
1694
1695 //============================================================================
1696 // Method Description:
1700 [[nodiscard]] reverse_iterator rend() noexcept
1701 {
1702 return rbegin() += size_;
1703 }
1704
1705 //============================================================================
1706 // Method Description:
1712 [[nodiscard]] reverse_iterator rend(size_type inRow)
1713 {
1714 if (inRow >= shape_.rows)
1715 {
1716 THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1717 }
1718
1719 return rbegin(inRow) += shape_.cols;
1720 }
1721
1722 //============================================================================
1723 // Method Description:
1727 [[nodiscard]] const_reverse_iterator rend() const noexcept
1728 {
1729 return crend();
1730 }
1731
1732 //============================================================================
1733 // Method Description:
1739 [[nodiscard]] const_reverse_iterator rend(size_type inRow) const
1740 {
1741 return crend(inRow);
1742 }
1743
1744 //============================================================================
1745 // Method Description:
1750 [[nodiscard]] const_reverse_iterator crend() const noexcept
1751 {
1752 return crbegin() += size_;
1753 }
1754
1755 //============================================================================
1756 // Method Description:
1762 [[nodiscard]] const_reverse_iterator crend(size_type inRow) const
1763 {
1764 if (inRow >= shape_.rows)
1765 {
1766 THROW_INVALID_ARGUMENT_ERROR("input row is greater than the number of rows in the array.");
1767 }
1768
1769 return crbegin(inRow) += shape_.cols;
1770 }
1771
1772 //============================================================================
1773 // Method Description:
1777 [[nodiscard]] column_iterator colend() noexcept
1778 {
1779 return colbegin() += size_;
1780 }
1781
1782 //============================================================================
1783 // Method Description:
1789 [[nodiscard]] column_iterator colend(size_type inCol)
1790 {
1791 if (inCol >= shape_.cols)
1792 {
1793 THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1794 }
1795
1796 return colbegin(inCol) += shape_.rows;
1797 }
1798
1799 //============================================================================
1800 // Method Description:
1804 [[nodiscard]] const_column_iterator colend() const noexcept
1805 {
1806 return ccolend();
1807 }
1808
1809 //============================================================================
1810 // Method Description:
1816 [[nodiscard]] const_column_iterator colend(size_type inCol) const
1817 {
1818 return ccolend(inCol);
1819 }
1820
1821 //============================================================================
1822 // Method Description:
1827 [[nodiscard]] const_column_iterator ccolend() const noexcept
1828 {
1829 return ccolbegin() += size_;
1830 }
1831
1832 //============================================================================
1833 // Method Description:
1839 [[nodiscard]] const_column_iterator ccolend(size_type inCol) const
1840 {
1841 if (inCol >= shape_.cols)
1842 {
1843 THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1844 }
1845
1846 return ccolbegin(inCol) += shape_.rows;
1847 }
1848
1849 //============================================================================
1850 // Method Description:
1854 [[nodiscard]] reverse_column_iterator rcolend() noexcept
1855 {
1856 return rcolbegin() += size_;
1857 }
1858
1859 //============================================================================
1860 // Method Description:
1867 {
1868 if (inCol >= shape_.cols)
1869 {
1870 THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1871 }
1872
1873 return rcolbegin(inCol) += shape_.rows;
1874 }
1875
1876 //============================================================================
1877 // Method Description:
1881 [[nodiscard]] const_reverse_column_iterator rcolend() const noexcept
1882 {
1883 return crcolend();
1884 }
1885
1886 //============================================================================
1887 // Method Description:
1894 {
1895 return crcolend(inCol);
1896 }
1897
1898 //============================================================================
1899 // Method Description:
1904 [[nodiscard]] const_reverse_column_iterator crcolend() const noexcept
1905 {
1906 return crcolbegin() += size_;
1907 }
1908
1909 //============================================================================
1910 // Method Description:
1917 {
1918 if (inCol >= shape_.cols)
1919 {
1920 THROW_INVALID_ARGUMENT_ERROR("input col is greater than the number of cols in the array.");
1921 }
1922
1923 return crcolbegin(inCol) += shape_.rows;
1924 }
1925
1926 //============================================================================
1927 // Method Description:
1935 [[nodiscard]] NdArray<bool> all(Axis inAxis = Axis::NONE) const
1936 {
1938
1939 const auto function = [](dtype i) -> bool { return !utils::essentiallyEqual(i, dtype{ 0 }); };
1940
1941 switch (inAxis)
1942 {
1943 case Axis::NONE:
1944 {
1945 NdArray<bool> returnArray = { stl_algorithms::all_of(cbegin(), cend(), function) };
1946 return returnArray;
1947 }
1948 case Axis::COL:
1949 {
1950 NdArray<bool> returnArray(1, shape_.rows);
1951 for (uint32 row = 0; row < shape_.rows; ++row)
1952 {
1953 returnArray(0, row) = stl_algorithms::all_of(cbegin(row), cend(row), function);
1954 }
1955
1956 return returnArray;
1957 }
1958 case Axis::ROW:
1959 {
1960 return transpose().all(Axis::COL);
1961 }
1962 default:
1963 {
1964 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
1965 return {}; // get rid of compiler warning
1966 }
1967 }
1968 }
1969
1970 //============================================================================
1971 // Method Description:
1979 [[nodiscard]] NdArray<bool> any(Axis inAxis = Axis::NONE) const
1980 {
1982
1983 const auto function = [](dtype i) -> bool { return !utils::essentiallyEqual(i, dtype{ 0 }); };
1984
1985 switch (inAxis)
1986 {
1987 case Axis::NONE:
1988 {
1989 NdArray<bool> returnArray = { stl_algorithms::any_of(cbegin(), cend(), function) };
1990 return returnArray;
1991 }
1992 case Axis::COL:
1993 {
1994 NdArray<bool> returnArray(1, shape_.rows);
1995 for (uint32 row = 0; row < shape_.rows; ++row)
1996 {
1997 returnArray(0, row) = stl_algorithms::any_of(cbegin(row), cend(row), function);
1998 }
1999
2000 return returnArray;
2001 }
2002 case Axis::ROW:
2003 {
2004 return transpose().any(Axis::COL);
2005 }
2006 default:
2007 {
2008 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2009 return {}; // get rid of compiler warning
2010 }
2011 }
2012 }
2013
2014 //============================================================================
2015 // Method Description:
2024 [[nodiscard]] NdArray<size_type> argmax(Axis inAxis = Axis::NONE) const
2025 {
2027
2028 const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
2029
2030 switch (inAxis)
2031 {
2032 case Axis::NONE:
2033 {
2034 NdArray<size_type> returnArray = { static_cast<size_type>(
2035 stl_algorithms::max_element(cbegin(), cend(), comparitor) - cbegin()) };
2036 return returnArray;
2037 }
2038 case Axis::COL:
2039 {
2040 NdArray<size_type> returnArray(1, shape_.rows);
2041 for (size_type row = 0; row < shape_.rows; ++row)
2042 {
2043 returnArray(0, row) = static_cast<size_type>(
2044 stl_algorithms::max_element(cbegin(row), cend(row), comparitor) - cbegin(row));
2045 }
2046
2047 return returnArray;
2048 }
2049 case Axis::ROW:
2050 {
2051 return transpose().argmax(Axis::COL);
2052 }
2053 default:
2054 {
2055 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2056 return {}; // get rid of compiler warning
2057 }
2058 }
2059 }
2060
2061 //============================================================================
2062 // Method Description:
2071 [[nodiscard]] NdArray<size_type> argmin(Axis inAxis = Axis::NONE) const
2072 {
2074
2075 const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
2076
2077 switch (inAxis)
2078 {
2079 case Axis::NONE:
2080 {
2081 NdArray<size_type> returnArray = { static_cast<size_type>(
2082 stl_algorithms::min_element(cbegin(), cend(), comparitor) - cbegin()) };
2083 return returnArray;
2084 }
2085 case Axis::COL:
2086 {
2087 NdArray<size_type> returnArray(1, shape_.rows);
2088 for (size_type row = 0; row < shape_.rows; ++row)
2089 {
2090 returnArray(0, row) = static_cast<size_type>(
2091 stl_algorithms::min_element(cbegin(row), cend(row), comparitor) - cbegin(row));
2092 }
2093
2094 return returnArray;
2095 }
2096 case Axis::ROW:
2097 {
2098 return transpose().argmin(Axis::COL);
2099 }
2100 default:
2101 {
2102 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2103 return {}; // get rid of compiler warning
2104 }
2105 }
2106 }
2107
2108 //============================================================================
2109 // Method Description:
2120 [[nodiscard]] NdArray<size_type> argpartition(size_type inKth, Axis inAxis = Axis::NONE) const
2121 {
2123
2124 switch (inAxis)
2125 {
2126 case Axis::NONE:
2127 {
2128 if (inKth >= size_)
2129 {
2130 std::string errStr = "kth(=" + utils::num2str(inKth);
2131 errStr += ") out of bounds (" + utils::num2str(size_) + ")";
2133 }
2134
2135 std::vector<size_type> idx(size_);
2136 std::iota(idx.begin(), idx.end(), 0);
2137
2138 const auto comparitor = [this](size_type i1, size_type i2) noexcept -> bool
2139 { return (*this)[i1] < (*this)[i2]; };
2140
2141 stl_algorithms::nth_element(idx.begin(), idx.begin() + inKth, idx.end(), comparitor);
2142 return NdArray<size_type>(idx); // NOLINT(modernize-return-braced-init-list)
2143 }
2144 case Axis::COL:
2145 {
2146 if (inKth >= shape_.cols)
2147 {
2148 std::string errStr = "kth(=" + utils::num2str(inKth);
2149 errStr += ") out of bounds (" + utils::num2str(shape_.cols) + ")";
2151 }
2152
2153 NdArray<size_type> returnArray(shape_);
2154 std::vector<size_type> idx(shape_.cols);
2155
2156 for (uint32 row = 0; row < shape_.rows; ++row)
2157 {
2158 std::iota(idx.begin(), idx.end(), 0);
2159
2160 const auto comparitor = [this, row](size_type i1, size_type i2) noexcept -> bool
2161 { return operator()(row, i1) < operator()(row, i2); };
2162
2163 stl_algorithms::nth_element(idx.begin(), idx.begin() + inKth, idx.end(), comparitor);
2164
2165 for (index_type col = 0; col < static_cast<index_type>(shape_.cols); ++col)
2166 {
2167 returnArray(row, col) = idx[static_cast<size_type>(col)];
2168 }
2169 }
2170 return returnArray;
2171 }
2172 case Axis::ROW:
2173 {
2174 return transpose().argpartition(inKth, Axis::COL).transpose();
2175 }
2176 default:
2177 {
2178 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2179 return {}; // get rid of compiler warning
2180 }
2181 }
2182 }
2183
2184 //============================================================================
2185 // Method Description:
2193 [[nodiscard]] NdArray<size_type> argsort(Axis inAxis = Axis::NONE) const
2194 {
2196
2197 switch (inAxis)
2198 {
2199 case Axis::NONE:
2200 {
2201 std::vector<size_type> idx(size_);
2202 std::iota(idx.begin(), idx.end(), 0);
2203
2204 const auto comparitor = [this](size_type i1, size_type i2) noexcept -> bool
2205 { return (*this)[i1] < (*this)[i2]; };
2206
2207 stl_algorithms::stable_sort(idx.begin(), idx.end(), comparitor);
2208 return NdArray<size_type>(idx); // NOLINT(modernize-return-braced-init-list)
2209 }
2210 case Axis::COL:
2211 {
2212 NdArray<size_type> returnArray(shape_);
2213 std::vector<size_type> idx(shape_.cols);
2214
2215 for (index_type row = 0; row < static_cast<index_type>(shape_.rows); ++row)
2216 {
2217 std::iota(idx.begin(), idx.end(), 0);
2218
2219 const auto comparitor = [this, row](size_type i1, size_type i2) noexcept -> bool
2220 { return operator()(row, i1) < operator()(row, i2); };
2221
2222 stl_algorithms::stable_sort(idx.begin(), idx.end(), comparitor);
2223
2224 for (index_type col = 0; col < static_cast<index_type>(shape_.cols); ++col)
2225 {
2226 returnArray(row, col) = idx[static_cast<size_type>(col)];
2227 }
2228 }
2229 return returnArray;
2230 }
2231 case Axis::ROW:
2232 {
2233 return transpose().argsort(Axis::COL).transpose();
2234 }
2235 default:
2236 {
2237 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2238 return {}; // get rid of compiler warning
2239 }
2240 }
2241 }
2242
2243 //============================================================================
2244 // Method Description:
2252 template<typename dtypeOut,
2253 typename dtype_ = dtype,
2254 std::enable_if_t<std::is_same_v<dtype_, dtype>, int> = 0,
2255 std::enable_if_t<std::is_arithmetic_v<dtype_>, int> = 0,
2256 std::enable_if_t<std::is_arithmetic_v<dtypeOut>, int> = 0>
2257 [[nodiscard]] NdArray<dtypeOut> astype() const
2258 {
2259 if constexpr (std::is_same_v<dtypeOut, dtype>)
2260 {
2261 return *this;
2262 }
2263 else
2264 {
2265 NdArray<dtypeOut> outArray(shape_);
2266 stl_algorithms::transform(cbegin(),
2267 cend(),
2268 outArray.begin(),
2269 [](dtype value) -> dtypeOut { return static_cast<dtypeOut>(value); });
2270
2271 return outArray;
2272 }
2273 }
2274
2275 //============================================================================
2276 // Method Description:
2284 template<typename dtypeOut,
2285 typename dtype_ = dtype,
2286 std::enable_if_t<std::is_same_v<dtype_, dtype>, int> = 0,
2287 std::enable_if_t<std::is_arithmetic_v<dtype_>, int> = 0,
2288 std::enable_if_t<is_complex_v<dtypeOut>, int> = 0>
2289 [[nodiscard]] NdArray<dtypeOut> astype() const
2290 {
2291 NdArray<dtypeOut> outArray(shape_);
2292
2293 const auto function = [](const_reference value) -> dtypeOut
2294 { return std::complex<typename dtypeOut::value_type>(value); };
2295
2296 stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2297
2298 return outArray;
2299 }
2300
2301 //============================================================================
2302 // Method Description:
2310 template<typename dtypeOut,
2311 typename dtype_ = dtype,
2312 std::enable_if_t<std::is_same_v<dtype_, dtype>, int> = 0,
2313 std::enable_if_t<is_complex_v<dtype_>, int> = 0,
2314 std::enable_if_t<is_complex_v<dtypeOut>, int> = 0>
2315 [[nodiscard]] NdArray<dtypeOut> astype() const
2316 {
2317 if constexpr (std::is_same_v<dtypeOut, dtype>)
2318 {
2319 return *this;
2320 }
2321 else
2322 {
2323 const auto function = [](const_reference value) noexcept -> dtypeOut
2324 { return complex_cast<typename dtypeOut::value_type>(value); };
2325
2326 NdArray<dtypeOut> outArray(shape_);
2327 stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2328 return outArray;
2329 }
2330 }
2331
2332 //============================================================================
2333 // Method Description:
2341 template<typename dtypeOut,
2342 typename dtype_ = dtype,
2343 std::enable_if_t<std::is_same_v<dtype_, dtype>, int> = 0,
2344 std::enable_if_t<is_complex_v<dtype_>, int> = 0,
2345 std::enable_if_t<std::is_arithmetic_v<dtypeOut>, int> = 0>
2346 [[nodiscard]] NdArray<dtypeOut> astype() const
2347 {
2348 NdArray<dtypeOut> outArray(shape_);
2349
2350 const auto function = [](const_reference value) -> dtypeOut { return static_cast<dtypeOut>(value.real()); };
2351
2352 stl_algorithms::transform(cbegin(), cend(), outArray.begin(), function);
2353
2354 return outArray;
2355 }
2356
2357 //============================================================================
2358 // Method Description:
2363 [[nodiscard]] const_reference back() const noexcept
2364 {
2365 return *(cend() - 1);
2366 }
2367
2368 //============================================================================
2369 // Method Description:
2374 reference back() noexcept
2375 {
2376 return *(end() - 1);
2377 }
2378
2379 //============================================================================
2380 // Method Description:
2385 [[nodiscard]] const_reference back(size_type row) const
2386 {
2387 return *(cend(row) - 1);
2388 }
2389
2390 //============================================================================
2391 // Method Description:
2397 {
2398 return *(end(row) - 1);
2399 }
2400
2401 //============================================================================
2402 // Method Description:
2410 {
2411 STATIC_ASSERT_INTEGER(dtype);
2412
2413 stl_algorithms::for_each(begin(),
2414 end(),
2415 [](dtype& value) noexcept -> void { value = endian::byteSwap(value); });
2416
2417 switch (endianess_)
2418 {
2419 case Endian::NATIVE:
2420 {
2421 endianess_ = endian::isLittleEndian() ? Endian::BIG : Endian::LITTLE;
2422 break;
2423 }
2424 case Endian::LITTLE:
2425 {
2426 endianess_ = Endian::BIG;
2427 break;
2428 }
2429 case Endian::BIG:
2430 {
2431 endianess_ = Endian::LITTLE;
2432 break;
2433 }
2434 }
2435
2436 return *this;
2437 }
2438
2439 //============================================================================
2440 // Method Description:
2449 [[nodiscard]] self_type clip(value_type inMin, value_type inMax) const
2450 {
2452
2453 self_type outArray(shape_);
2454 stl_algorithms::transform(cbegin(),
2455 cend(),
2456 outArray.begin(),
2457 [inMin, inMax](dtype value) noexcept -> dtype
2458 {
2459#ifdef __cpp_lib_clamp
2460 const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
2461 { return lhs < rhs; };
2462
2463 return std::clamp(value, inMin, inMax, comparitor);
2464#else
2465 if (value < inMin)
2466 {
2467 return inMin;
2468 }
2469 else if (value > inMax)
2470 {
2471 return inMax;
2472 }
2473
2474 return value;
2475#endif
2476 });
2477
2478 return outArray;
2479 }
2480
2481 //============================================================================
2482 // Method Description:
2488 [[nodiscard]] self_type column(size_type inColumn) const
2489 {
2490 return operator()(rSlice(), inColumn);
2491 }
2492
2493 //============================================================================
2494 // Method Description:
2500 [[nodiscard]] self_type columns(const NdArray<size_type>& inCols) const
2501 {
2502 auto returnArray = self_type(shape_.rows, inCols.size());
2503 const auto rSlice = returnArray.rSlice();
2504
2505 for (size_type i = 0; i < inCols.size(); ++i)
2506 {
2507 returnArray.put(rSlice, i, column(inCols[i]));
2508 }
2509
2510 return returnArray;
2511 }
2512
2513 //============================================================================
2514 // Method Description:
2521 [[nodiscard]] NdArray<bool> contains(value_type inValue, Axis inAxis = Axis::NONE) const
2522 {
2524
2525 switch (inAxis)
2526 {
2527 case Axis::NONE:
2528 {
2529 NdArray<bool> returnArray = { stl_algorithms::find(cbegin(), cend(), inValue) != cend() };
2530 return returnArray;
2531 }
2532 case Axis::COL:
2533 {
2534 NdArray<bool> returnArray(1, shape_.rows);
2535 for (size_type row = 0; row < shape_.rows; ++row)
2536 {
2537 returnArray(0, row) = stl_algorithms::find(cbegin(row), cend(row), inValue) != cend(row);
2538 }
2539
2540 return returnArray;
2541 }
2542 case Axis::ROW:
2543 {
2544 return transpose().contains(inValue, Axis::COL);
2545 }
2546 default:
2547 {
2548 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2549 return {}; // get rid of compiler warning
2550 }
2551 }
2552 }
2553
2554 //============================================================================
2555 // Method Description:
2562 [[nodiscard]] self_type copy() const
2563 {
2564 return self_type(*this);
2565 }
2566
2567 //============================================================================
2568 // Method Description:
2576 [[nodiscard]] self_type cumprod(Axis inAxis = Axis::NONE) const
2577 {
2579
2580 switch (inAxis)
2581 {
2582 case Axis::NONE:
2583 {
2584 self_type returnArray(1, size_);
2585 returnArray[0] = front();
2586 for (size_type i = 1; i < size_; ++i)
2587 {
2588 returnArray[i] = returnArray[i - 1] * array_[i];
2589 }
2590
2591 return returnArray;
2592 }
2593 case Axis::COL:
2594 {
2595 self_type returnArray(shape_);
2596 for (uint32 row = 0; row < shape_.rows; ++row)
2597 {
2598 returnArray(row, 0) = operator()(row, 0);
2599 for (uint32 col = 1; col < shape_.cols; ++col)
2600 {
2601 returnArray(row, col) = returnArray(row, col - 1) * operator()(row, col);
2602 }
2603 }
2604
2605 return returnArray;
2606 }
2607 case Axis::ROW:
2608 {
2609 return transpose().cumprod(Axis::COL).transpose();
2610 }
2611 default:
2612 {
2613 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2614 return {}; // get rid of compiler warning
2615 }
2616 }
2617 }
2618
2619 //============================================================================
2620 // Method Description:
2628 [[nodiscard]] self_type cumsum(Axis inAxis = Axis::NONE) const
2629 {
2631
2632 switch (inAxis)
2633 {
2634 case Axis::NONE:
2635 {
2636 self_type returnArray(1, size_);
2637 returnArray[0] = front();
2638 for (size_type i = 1; i < size_; ++i)
2639 {
2640 returnArray[i] = returnArray[i - 1] + array_[i];
2641 }
2642
2643 return returnArray;
2644 }
2645 case Axis::COL:
2646 {
2647 self_type returnArray(shape_);
2648 for (uint32 row = 0; row < shape_.rows; ++row)
2649 {
2650 returnArray(row, 0) = operator()(row, 0);
2651 for (uint32 col = 1; col < shape_.cols; ++col)
2652 {
2653 returnArray(row, col) = returnArray(row, col - 1) + operator()(row, col);
2654 }
2655 }
2656
2657 return returnArray;
2658 }
2659 case Axis::ROW:
2660 {
2661 return transpose().cumsum(Axis::COL).transpose();
2662 }
2663 default:
2664 {
2665 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2666 return {}; // get rid of compiler warning
2667 }
2668 }
2669 }
2670
2671 //============================================================================
2672 // Method Description:
2676 [[nodiscard]] pointer data() noexcept
2677 {
2678 return array_;
2679 }
2680
2681 //============================================================================
2682 // Method Description:
2686 [[nodiscard]] const_pointer data() const noexcept
2687 {
2688 return array_;
2689 }
2690
2691 //============================================================================
2692 // Method Description:
2698 [[nodiscard]] pointer dataRelease() noexcept
2699 {
2700 ownsPtr_ = false;
2701 return data();
2702 }
2703
2704 //============================================================================
2705 // Method Description:
2715 [[nodiscard]] self_type diagonal(index_type inOffset = 0, Axis inAxis = Axis::ROW) const
2716 {
2717 switch (inAxis)
2718 {
2719 case Axis::COL:
2720 {
2721 std::vector<dtype> diagnolValues;
2722 size_type col = 0;
2723 for (index_type row = inOffset; row < static_cast<index_type>(shape_.rows); ++row)
2724 {
2725 if (row < 0)
2726 {
2727 ++col;
2728 continue;
2729 }
2730 if (col >= shape_.cols)
2731 {
2732 break;
2733 }
2734
2735 diagnolValues.push_back(operator()(static_cast<size_type>(row), col));
2736 ++col;
2737 }
2738
2739 return self_type(diagnolValues);
2740 }
2741 case Axis::ROW:
2742 {
2743 return transpose().diagonal(inOffset, Axis::COL);
2744 }
2745 default:
2746 {
2747 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
2748 return {}; // get rid of compiler warning
2749 }
2750 }
2751 }
2752
2753 //============================================================================
2754 // Method Description:
2760 [[nodiscard]] size_type dimSize(Axis inAxis) const noexcept
2761 {
2762 switch (inAxis)
2763 {
2764 case Axis::NONE:
2765 {
2766 return size();
2767 }
2768 case Axis::ROW:
2769 {
2770 return numRows();
2771 }
2772 case Axis::COL:
2773 {
2774 return numCols();
2775 }
2776 default:
2777 {
2778 return {}; // get rid of compiler warning
2779 }
2780 }
2781 }
2782
2783 //============================================================================
2784 // Method Description:
2795 [[nodiscard]] self_type dot(const self_type& inOtherArray) const
2796 {
2798
2799 if (shape_ == inOtherArray.shape_ && (shape_.rows == 1 || shape_.cols == 1))
2800 {
2801 dtype dotProduct = std::inner_product(cbegin(), cend(), inOtherArray.cbegin(), dtype{ 0 });
2802 self_type returnArray = { dotProduct };
2803 return returnArray;
2804 }
2805 if (shape_.cols == inOtherArray.shape_.rows)
2806 {
2807 // 2D array, use matrix multiplication
2808 self_type returnArray(shape_.rows, inOtherArray.shape_.cols);
2809 auto otherArrayT = inOtherArray.transpose();
2810
2811 for (uint32 i = 0; i < shape_.rows; ++i)
2812 {
2813 for (uint32 j = 0; j < otherArrayT.shape_.rows; ++j)
2814 {
2815 returnArray(i, j) =
2816 std::inner_product(otherArrayT.cbegin(j), otherArrayT.cend(j), cbegin(i), dtype{ 0 });
2817 }
2818 }
2819
2820 return returnArray;
2821 }
2822
2823 std::string errStr = "shapes of [" + utils::num2str(shape_.rows) + ", " + utils::num2str(shape_.cols) + "]";
2824 errStr += " and [" + utils::num2str(inOtherArray.shape_.rows) + ", " +
2825 utils::num2str(inOtherArray.shape_.cols) + "]";
2826 errStr += " are not consistent.";
2828
2829 return self_type(); // get rid of compiler warning
2830 }
2831
2832 //============================================================================
2833 // Method Description:
2841 void dump(const std::string& inFilename) const
2842 {
2843 std::filesystem::path f(inFilename);
2844 if (!f.has_extension())
2845 {
2846 f.replace_extension("bin");
2847 }
2848
2849 std::ofstream ofile(f.c_str(), std::ios::binary);
2850 if (!ofile.good())
2851 {
2852 THROW_RUNTIME_ERROR("Unable to open the input file:\n\t" + inFilename);
2853 }
2854
2855 if (array_ != nullptr)
2856 {
2857 ofile.write(reinterpret_cast<const char*>(array_), size_ * sizeof(dtype));
2858 }
2859 ofile.close();
2860 }
2861
2862 //============================================================================
2863 // Method Description:
2868 [[nodiscard]] Endian endianess() const noexcept
2869 {
2871
2872 return endianess_;
2873 }
2874
2875 //============================================================================
2876 // Method Description:
2884 self_type& fill(value_type inFillValue) noexcept
2885 {
2886 stl_algorithms::fill(begin(), end(), inFillValue);
2887 return *this;
2888 }
2889
2890 //============================================================================
2891 // Method Description:
2897 [[nodiscard]] NdArray<size_type> flatnonzero() const
2898 {
2900
2901 std::vector<size_type> indices;
2902 size_type idx = 0;
2903 for (auto value : *this)
2904 {
2905 if (!utils::essentiallyEqual(value, dtype{ 0 }))
2906 {
2907 indices.push_back(idx);
2908 }
2909 ++idx;
2910 }
2911
2912 return NdArray<size_type>(indices); // NOLINT(modernize-return-braced-init-list)
2913 }
2914
2915 //============================================================================
2916 // Method Description:
2923 [[nodiscard]] self_type flatten() const
2924 {
2925 self_type outArray(1, size_);
2926 stl_algorithms::copy(cbegin(), cend(), outArray.begin());
2927 return outArray;
2928 }
2929
2930 //============================================================================
2931 // Method Description:
2936 [[nodiscard]] const_reference front() const noexcept
2937 {
2938 return *cbegin();
2939 }
2940
2941 //============================================================================
2942 // Method Description:
2947 reference front() noexcept
2948 {
2949 return *begin();
2950 }
2951
2952 //============================================================================
2953 // Method Description:
2958 [[nodiscard]] const_reference front(size_type row) const
2959 {
2960 return *cbegin(row);
2961 }
2962
2963 //============================================================================
2964 // Method Description:
2970 {
2971 return *begin(row);
2972 }
2973
2974 //============================================================================
2975 // Method Description:
2981 [[nodiscard]] self_type getByIndices(const NdArray<size_type>& inIndices) const
2982 {
2983 return operator[](inIndices);
2984 }
2985
2986 //============================================================================
2987 // Method Description:
2995 [[nodiscard]] self_type getByMask(const NdArray<bool>& inMask) const
2996 {
2997 return operator[](inMask);
2998 }
2999
3000 //============================================================================
3001 // Method Description:
3007 // NOLINTNEXTLINE(modernize-use-nodiscard)
3008 bool isempty() const noexcept
3009 {
3010 return size_ == 0;
3011 }
3012
3013 //============================================================================
3014 // Method Description:
3020 // NOLINTNEXTLINE(modernize-use-nodiscard)
3021 bool isflat() const noexcept
3022 {
3023 return !isscalar() && (shape_.rows == 1 || shape_.cols == 1);
3024 }
3025
3026 //============================================================================
3027 // Method Description:
3031 // NOLINTNEXTLINE(modernize-use-nodiscard)
3032 bool isscalar() const noexcept
3033 {
3034 return size_ == 1;
3035 }
3036
3037 //============================================================================
3038 // Method Description:
3044 [[nodiscard]] NdArray<bool> issorted(Axis inAxis = Axis::NONE) const
3045 {
3047
3048 const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
3049
3050 switch (inAxis)
3051 {
3052 case Axis::NONE:
3053 {
3054 return { stl_algorithms::is_sorted(cbegin(), cend(), comparitor) };
3055 }
3056 case Axis::COL:
3057 {
3058 NdArray<bool> returnArray(1, shape_.rows);
3059 for (uint32 row = 0; row < shape_.rows; ++row)
3060 {
3061 returnArray(0, row) = stl_algorithms::is_sorted(cbegin(row), cend(row), comparitor);
3062 }
3063
3064 return returnArray;
3065 }
3066 case Axis::ROW:
3067 {
3068 return transpose().issorted(Axis::COL);
3069 }
3070 default:
3071 {
3072 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3073 return {}; // get rid of compiler warning
3074 }
3075 }
3076 }
3077
3078 //============================================================================
3079 // Method Description:
3084 // NOLINTNEXTLINE(modernize-use-nodiscard)
3085 bool issquare() const noexcept
3086 {
3087 return shape_.issquare();
3088 }
3089
3090 //============================================================================
3091 // Method Description:
3098 [[nodiscard]] value_type item() const
3099 {
3100 if (!isscalar())
3101 {
3102 THROW_INVALID_ARGUMENT_ERROR("Can only convert an array of size 1 to a C++ scalar");
3103 }
3104
3105 return front();
3106 }
3107
3108 //============================================================================
3109 // Method Description:
3117 [[nodiscard]] self_type max(Axis inAxis = Axis::NONE) const
3118 {
3120
3121 const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
3122
3123 switch (inAxis)
3124 {
3125 case Axis::NONE:
3126 {
3127 self_type returnArray = { *stl_algorithms::max_element(cbegin(), cend(), comparitor) };
3128 return returnArray;
3129 }
3130 case Axis::COL:
3131 {
3132 self_type returnArray(1, shape_.rows);
3133 for (uint32 row = 0; row < shape_.rows; ++row)
3134 {
3135 returnArray(0, row) = *stl_algorithms::max_element(cbegin(row), cend(row), comparitor);
3136 }
3137
3138 return returnArray;
3139 }
3140 case Axis::ROW:
3141 {
3142 return transpose().max(Axis::COL);
3143 }
3144 default:
3145 {
3146 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3147 return {}; // get rid of compiler warning
3148 }
3149 }
3150 }
3151
3152 //============================================================================
3153 // Method Description:
3161 [[nodiscard]] self_type min(Axis inAxis = Axis::NONE) const
3162 {
3164
3165 const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
3166
3167 switch (inAxis)
3168 {
3169 case Axis::NONE:
3170 {
3171 self_type returnArray = { *stl_algorithms::min_element(cbegin(), cend(), comparitor) };
3172 return returnArray;
3173 }
3174 case Axis::COL:
3175 {
3176 self_type returnArray(1, shape_.rows);
3177 for (uint32 row = 0; row < shape_.rows; ++row)
3178 {
3179 returnArray(0, row) = *stl_algorithms::min_element(cbegin(row), cend(row), comparitor);
3180 }
3181
3182 return returnArray;
3183 }
3184 case Axis::ROW:
3185 {
3186 return transpose().min(Axis::COL);
3187 }
3188 default:
3189 {
3190 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3191 return {}; // get rid of compiler warning
3192 }
3193 }
3194 }
3195
3196 //============================================================================
3197 // Method Description:
3207 [[nodiscard]] self_type median(Axis inAxis = Axis::NONE) const
3208 {
3210
3211 const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
3212
3213 if (size_ == 0)
3214 {
3215 THROW_RUNTIME_ERROR("Median is undefined for an array of size = 0.");
3216 }
3217
3218 switch (inAxis)
3219 {
3220 case Axis::NONE:
3221 {
3222 self_type copyArray(*this);
3223
3224 const size_type middleIdx = size_ / 2; // integer division
3225 stl_algorithms::nth_element(copyArray.begin(),
3226 copyArray.begin() + middleIdx,
3227 copyArray.end(),
3228 comparitor);
3229
3230 dtype medianValue = copyArray.array_[middleIdx];
3231 if (size_ % 2 == 0)
3232 {
3233 const size_type lhsIndex = middleIdx - 1;
3234 stl_algorithms::nth_element(copyArray.begin(),
3235 copyArray.begin() + lhsIndex,
3236 copyArray.end(),
3237 comparitor);
3238 medianValue =
3239 (medianValue + copyArray.array_[lhsIndex]) / dtype{ 2 }; // potentially integer division, ok
3240 }
3241
3242 return { medianValue };
3243 }
3244 case Axis::COL:
3245 {
3246 self_type copyArray(*this);
3247 self_type returnArray(1, shape_.rows);
3248
3249 const bool isEven = shape_.cols % 2 == 0;
3250 for (uint32 row = 0; row < shape_.rows; ++row)
3251 {
3252 const uint32 middleIdx = shape_.cols / 2; // integer division
3253 stl_algorithms::nth_element(copyArray.begin(row),
3254 copyArray.begin(row) + middleIdx,
3255 copyArray.end(row),
3256 comparitor);
3257
3258 dtype medianValue = copyArray(row, middleIdx);
3259 if (isEven)
3260 {
3261 const size_type lhsIndex = middleIdx - 1;
3262 stl_algorithms::nth_element(copyArray.begin(row),
3263 copyArray.begin(row) + lhsIndex,
3264 copyArray.end(row),
3265 comparitor);
3266 medianValue = (medianValue + copyArray(row, lhsIndex)) /
3267 dtype{ 2 }; // potentially integer division, ok
3268 }
3269
3270 returnArray(0, row) = medianValue;
3271 }
3272
3273 return returnArray;
3274 }
3275 case Axis::ROW:
3276 {
3277 return transpose().median(Axis::COL);
3278 }
3279 default:
3280 {
3281 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3282 return {}; // get rid of compiler warning
3283 }
3284 }
3285 }
3286
3287 //============================================================================
3288 // Method Description:
3292 self_type& nans() noexcept
3293
3294 {
3295 STATIC_ASSERT_FLOAT(dtype);
3296
3297 fill(constants::nan);
3298 return *this;
3299 }
3300
3301 //============================================================================
3302 // Method Description:
3309 [[nodiscard]] uint64 nbytes() const noexcept
3310 {
3311 return static_cast<uint64>(sizeof(dtype) * size_);
3312 }
3313
3314 //============================================================================
3315 // Method Description:
3324 [[nodiscard]] self_type newbyteorder(Endian inEndianess) const
3325 {
3326 STATIC_ASSERT_INTEGER(dtype);
3327
3328 const bool nativeIsLittle = endian::isLittleEndian();
3329
3330 switch (endianess_)
3331 {
3332 case Endian::NATIVE:
3333 {
3334 switch (inEndianess)
3335 {
3336 case Endian::NATIVE:
3337 {
3338 return NdArray(*this);
3339 }
3340 case Endian::BIG:
3341 {
3342 if (nativeIsLittle)
3343 {
3344 self_type outArray(shape_);
3345
3346 stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3347
3348 outArray.endianess_ = Endian::BIG;
3349 return outArray;
3350 }
3351 else
3352 {
3353 auto outArray = NdArray(*this);
3354 outArray.endianess_ = Endian::BIG;
3355 return outArray;
3356 }
3357 }
3358 case Endian::LITTLE:
3359 {
3360 if (nativeIsLittle)
3361 {
3362 auto outArray = NdArray(*this);
3363 outArray.endianess_ = Endian::LITTLE;
3364 return outArray;
3365 }
3366 else
3367 {
3368 self_type outArray(shape_);
3369
3370 stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3371
3372 outArray.endianess_ = Endian::LITTLE;
3373 return outArray;
3374 }
3375 }
3376 default:
3377 {
3378 THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3379 return {}; // get rid of compiler warning
3380 }
3381 }
3382 break;
3383 }
3384 case Endian::BIG:
3385 {
3386 switch (inEndianess)
3387 {
3388 case Endian::NATIVE:
3389 {
3390 if (nativeIsLittle)
3391 {
3392 self_type outArray(shape_);
3393
3394 stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3395
3396 outArray.endianess_ = Endian::NATIVE;
3397 return outArray;
3398 }
3399 else
3400 {
3401 auto outArray = NdArray(*this);
3402 outArray.endianess_ = Endian::NATIVE;
3403 return outArray;
3404 }
3405 }
3406 case Endian::BIG:
3407 {
3408 return NdArray(*this);
3409 }
3410 case Endian::LITTLE:
3411 {
3412 self_type outArray(shape_);
3413
3414 stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3415
3416 outArray.endianess_ = Endian::LITTLE;
3417 return outArray;
3418 }
3419 default:
3420 {
3421 THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3422 return {}; // get rid of compiler warning
3423 }
3424 }
3425 break;
3426 }
3427 case Endian::LITTLE:
3428 {
3429 switch (inEndianess)
3430 {
3431 case Endian::NATIVE:
3432 {
3433 if (nativeIsLittle)
3434 {
3435 auto outArray = NdArray(*this);
3436 outArray.endianess_ = Endian::NATIVE;
3437 return outArray;
3438 }
3439 else
3440 {
3441 self_type outArray(shape_);
3442
3443 stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3444
3445 outArray.endianess_ = Endian::NATIVE;
3446 return outArray;
3447 }
3448 }
3449 case Endian::BIG:
3450 {
3451 self_type outArray(shape_);
3452
3453 stl_algorithms::transform(cbegin(), end(), outArray.begin(), endian::byteSwap<dtype>);
3454
3455 outArray.endianess_ = Endian::BIG;
3456 return outArray;
3457 }
3458 case Endian::LITTLE:
3459 {
3460 return NdArray(*this);
3461 }
3462 default:
3463 {
3464 THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3465 return {}; // get rid of compiler warning
3466 }
3467 }
3468 break;
3469 }
3470 default:
3471 {
3472 THROW_INVALID_ARGUMENT_ERROR("Unimplemented endian type.");
3473 return {}; // get rid of compiler warning
3474 }
3475 }
3476 }
3477
3478 //============================================================================
3479 // Method Description:
3487 [[nodiscard]] NdArray<bool> none(Axis inAxis = Axis::NONE) const
3488 {
3490
3491 const auto function = [](dtype i) -> bool { return !utils::essentiallyEqual(i, dtype{ 0 }); };
3492
3493 switch (inAxis)
3494 {
3495 case Axis::NONE:
3496 {
3497 NdArray<bool> returnArray = { stl_algorithms::none_of(cbegin(), cend(), function) };
3498 return returnArray;
3499 }
3500 case Axis::COL:
3501 {
3502 NdArray<bool> returnArray(1, shape_.rows);
3503 for (uint32 row = 0; row < shape_.rows; ++row)
3504 {
3505 returnArray(0, row) = stl_algorithms::none_of(cbegin(row), cend(row), function);
3506 }
3507
3508 return returnArray;
3509 }
3510 case Axis::ROW:
3511 {
3512 return transpose().none(Axis::COL);
3513 }
3514 default:
3515 {
3516 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3517 return {}; // get rid of compiler warning
3518 }
3519 }
3520 }
3521
3522 //============================================================================
3523 // Method Description:
3532 [[nodiscard]] std::pair<NdArray<size_type>, NdArray<size_type>> nonzero() const;
3533
3534 //============================================================================
3535 // Method Description:
3541 [[nodiscard]] size_type numCols() const noexcept
3542 {
3543 return shape_.cols;
3544 }
3545
3546 //============================================================================
3547 // Method Description:
3553 [[nodiscard]] size_type numRows() const noexcept
3554 {
3555 return shape_.rows;
3556 }
3557
3558 //============================================================================
3559 // Method Description:
3563 self_type& ones() noexcept
3564 {
3566
3567 fill(dtype{ 1 });
3568 return *this;
3569 }
3570
3571 //============================================================================
3572 // Method Description:
3577 bool ownsInternalData() noexcept
3578 {
3579 return ownsPtr_;
3580 }
3581
3582 //============================================================================
3583 // Method Description:
3597 self_type& partition(size_type inKth, Axis inAxis = Axis::NONE)
3598 {
3600
3601 const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
3602 { return lhs < rhs; }; // cppcheck-suppress returnTempReference
3603
3604 switch (inAxis)
3605 {
3606 case Axis::NONE:
3607 {
3608 if (inKth >= size_)
3609 {
3610 std::string errStr = "kth(=" + utils::num2str(inKth);
3611 errStr += ") out of bounds (" + utils::num2str(size_) + ")";
3613 }
3614
3615 stl_algorithms::nth_element(begin(), begin() + inKth, end(), comparitor);
3616 break;
3617 }
3618 case Axis::COL:
3619 {
3620 if (inKth >= shape_.cols)
3621 {
3622 std::string errStr = "kth(=" + utils::num2str(inKth);
3623 errStr += ") out of bounds (" + utils::num2str(shape_.cols) + ")";
3625 }
3626
3627 for (uint32 row = 0; row < shape_.rows; ++row)
3628 {
3629 stl_algorithms::nth_element(begin(row), begin(row) + inKth, end(row), comparitor);
3630 }
3631 break;
3632 }
3633 case Axis::ROW:
3634 {
3635 if (inKth >= shape_.rows)
3636 {
3637 std::string errStr = "kth(=" + utils::num2str(inKth);
3638 errStr += ") out of bounds (" + utils::num2str(shape_.rows) + ")";
3640 }
3641
3642 self_type transposedArray = transpose();
3643 for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
3644 {
3645 stl_algorithms::nth_element(transposedArray.begin(row),
3646 transposedArray.begin(row) + inKth,
3647 transposedArray.end(row),
3648 comparitor);
3649 }
3650 *this = transposedArray.transpose();
3651 break;
3652 }
3653 }
3654
3655 return *this;
3656 }
3657
3658 //============================================================================
3659 // Method Description:
3663 void print() const
3664 {
3666
3667 std::cout << *this;
3668 }
3669
3670 //============================================================================
3671 // Method Description:
3679 [[nodiscard]] self_type prod(Axis inAxis = Axis::NONE) const
3680 {
3682
3683 switch (inAxis)
3684 {
3685 case Axis::NONE:
3686 {
3687 dtype product = std::accumulate(cbegin(), cend(), dtype{ 1 }, std::multiplies<dtype>());
3688 self_type returnArray = { product };
3689 return returnArray;
3690 }
3691 case Axis::COL:
3692 {
3693 self_type returnArray(1, shape_.rows);
3694 for (uint32 row = 0; row < shape_.rows; ++row)
3695 {
3696 returnArray(0, row) =
3697 std::accumulate(cbegin(row), cend(row), dtype{ 1 }, std::multiplies<dtype>());
3698 }
3699
3700 return returnArray;
3701 }
3702 case Axis::ROW:
3703 {
3704 return transpose().prod(Axis::COL);
3705 }
3706 default:
3707 {
3708 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3709 return {}; // get rid of compiler warning
3710 }
3711 }
3712 }
3713
3714 //============================================================================
3715 // Method Description:
3723 [[nodiscard]] self_type ptp(Axis inAxis = Axis::NONE) const
3724 {
3726
3727 const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
3728
3729 switch (inAxis)
3730 {
3731 case Axis::NONE:
3732 {
3733 const auto result = stl_algorithms::minmax_element(cbegin(), cend(), comparitor);
3734 self_type returnArray = { *result.second - *result.first };
3735 return returnArray;
3736 }
3737 case Axis::COL:
3738 {
3739 self_type returnArray(1, shape_.rows);
3740 for (uint32 row = 0; row < shape_.rows; ++row)
3741 {
3742 const auto result = stl_algorithms::minmax_element(cbegin(row), cend(row), comparitor);
3743 returnArray(0, row) = *result.second - *result.first;
3744 }
3745
3746 return returnArray;
3747 }
3748 case Axis::ROW:
3749 {
3750 return transpose().ptp(Axis::COL);
3751 }
3752 default:
3753 {
3754 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
3755 return {}; // get rid of compiler warning
3756 }
3757 }
3758 }
3759
3760 //============================================================================
3761 // Method Description:
3769 self_type& put(index_type inIndex, const value_type& inValue)
3770 {
3771 at(inIndex) = inValue;
3772
3773 return *this;
3774 }
3775
3776 //============================================================================
3777 // Method Description:
3786 self_type& put(index_type inRow, index_type inCol, const value_type& inValue)
3787 {
3788 at(inRow, inCol) = inValue;
3789
3790 return *this;
3791 }
3792
3793 //============================================================================
3794 // Method Description:
3803 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
3804 self_type& put(const Indices& inIndices, const value_type& inValue)
3805 {
3806 for (auto index : inIndices)
3807 {
3808 put(index, inValue);
3809 }
3810
3811 return *this;
3812 }
3813
3814 //============================================================================
3815 // Method Description:
3824 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
3825 self_type& put(const Indices& inIndices, const self_type& inValues)
3826 {
3827 if (inValues.isscalar())
3828 {
3829 return put(inIndices, inValues.item());
3830 }
3831 else if (inIndices.size() != inValues.size())
3832 {
3833 THROW_INVALID_ARGUMENT_ERROR("Input indices do not match values dimensions.");
3834 }
3835
3836 size_type counter = 0;
3837 for (auto index : inIndices)
3838 {
3839 put(index, inValues[counter++]);
3840 }
3841
3842 return *this;
3843 }
3844
3845 //============================================================================
3846 // Method Description:
3855 self_type& put(const Slice& inSlice, const value_type& inValue)
3856 {
3857 return put(toIndices(inSlice, Axis::NONE), inValue);
3858 }
3859
3860 //============================================================================
3861 // Method Description:
3870 self_type& put(const Slice& inSlice, const self_type& inValues)
3871 {
3872 return put(toIndices(inSlice, Axis::NONE), inValues);
3873 }
3874
3875 //============================================================================
3876 // Method Description:
3886 template<typename RowIndices,
3887 typename ColIndices,
3890 self_type& put(const RowIndices& inRowIndices, const ColIndices& inColIndices, const value_type& inValue)
3891 {
3892 stl_algorithms::for_each(inRowIndices.begin(),
3893 inRowIndices.end(),
3894 [this, &inColIndices, &inValue](const auto row)
3895 {
3896 stl_algorithms::for_each(inColIndices.begin(),
3897 inColIndices.end(),
3898 [this, row, &inValue](const auto col)
3899 { this->put(row, col, inValue); });
3900 });
3901
3902 return *this;
3903 }
3904
3905 //============================================================================
3906 // Method Description:
3916 template<typename RowIndices, type_traits::ndarray_int_concept<RowIndices> = 0>
3917 self_type& put(const RowIndices& inRowIndices, const Slice& inColSlice, const value_type& inValue)
3918 {
3919 return put(inRowIndices, toIndices(inColSlice, Axis::COL), inValue);
3920 }
3921
3922 //============================================================================
3923 // Method Description:
3933 template<typename ColIndices, type_traits::ndarray_int_concept<ColIndices> = 0>
3934 self_type& put(const Slice& inRowSlice, const ColIndices& inColIndices, const value_type& inValue)
3935 {
3936 return put(toIndices(inRowSlice, Axis::ROW), inColIndices, inValue);
3937 }
3938
3939 //============================================================================
3940 // Method Description:
3950 self_type& put(const Slice& inRowSlice, const Slice& inColSlice, const value_type& inValue)
3951 {
3952 return put(toIndices(inRowSlice, Axis::ROW), toIndices(inColSlice, Axis::COL), inValue);
3953 }
3954
3955 //============================================================================
3956 // Method Description:
3966 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
3967 self_type& put(const Indices& inRowIndices, index_type inColIndex, const value_type& inValue)
3968 {
3969 const NdArray<index_type> colIndices = { inColIndex };
3970 return put(inRowIndices, colIndices, inValue);
3971 }
3972
3973 //============================================================================
3974 // Method Description:
3984 self_type& put(const Slice& inRowSlice, index_type inColIndex, const value_type& inValue)
3985 {
3986 const NdArray<index_type> colIndices = { inColIndex };
3987 return put(toIndices(inRowSlice, Axis::ROW), colIndices, inValue);
3988 }
3989
3990 //============================================================================
3991 // Method Description:
4001 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
4002 self_type& put(index_type inRowIndex, const Indices& inColIndices, const value_type& inValue)
4003 {
4004 const NdArray<index_type> rowIndices = { inRowIndex };
4005 return put(rowIndices, inColIndices, inValue);
4006 }
4007
4008 //============================================================================
4009 // Method Description:
4019 self_type& put(index_type inRowIndex, const Slice& inColSlice, const value_type& inValue)
4020 {
4021 const NdArray<index_type> rowIndices = { inRowIndex };
4022 return put(rowIndices, toIndices(inColSlice, Axis::COL), inValue);
4023 }
4024
4025 //============================================================================
4026 // Method Description:
4036 template<typename RowIndices,
4037 typename ColIndices,
4040 self_type& put(const RowIndices& inRowIndices, const ColIndices& inColIndices, const self_type& inValues)
4041 {
4042 std::vector<size_type> indices;
4043 indices.reserve(inRowIndices.size() * inColIndices.size());
4044 std::for_each(inRowIndices.begin(),
4045 inRowIndices.end(),
4046 [this, &inColIndices, &indices](auto row)
4047 {
4048 if constexpr (std::is_signed_v<decltype(row)>)
4049 {
4050 if (row < 0)
4051 {
4052 row += shape_.rows;
4053 }
4054 // still
4055 if (row < 0)
4056 {
4057 THROW_INVALID_ARGUMENT_ERROR("row index exceeds matrix dimensions");
4058 }
4059 }
4060 std::for_each(inColIndices.begin(),
4061 inColIndices.end(),
4062 [this, row, &indices](auto col)
4063 {
4064 if constexpr (std::is_signed_v<decltype(col)>)
4065 {
4066 if (col < 0)
4067 {
4068 col += shape_.cols;
4069 }
4070 // still
4071 if (col < 0)
4072 {
4073 THROW_INVALID_ARGUMENT_ERROR(
4074 "col index exceeds matrix dimensions");
4075 }
4076 }
4077 indices.push_back(row * shape_.cols + col);
4078 });
4079 });
4080
4081 return put(NdArray<size_type>(indices.data(), indices.size(), PointerPolicy::SHELL), inValues);
4082 }
4083
4084 //============================================================================
4085 // Method Description:
4095 template<typename RowIndices, type_traits::ndarray_int_concept<RowIndices> = 0>
4096 self_type& put(const RowIndices& inRowIndices, Slice inColSlice, const self_type& inValues)
4097 {
4098 return put(inRowIndices, toIndices(inColSlice, Axis::COL), inValues);
4099 }
4100
4101 //============================================================================
4102 // Method Description:
4112 template<typename ColIndices, type_traits::ndarray_int_concept<ColIndices> = 0>
4113 self_type& put(Slice inRowSlice, const ColIndices& inColIndices, const self_type& inValues)
4114 {
4115 return put(toIndices(inRowSlice, Axis::ROW), inColIndices, inValues);
4116 }
4117
4118 //============================================================================
4119 // Method Description:
4129 self_type& put(Slice inRowSlice, Slice inColSlice, const self_type& inValues)
4130 {
4131 return put(toIndices(inRowSlice, Axis::ROW), toIndices(inColSlice, Axis::COL), inValues);
4132 }
4133
4134 //============================================================================
4135 // Method Description:
4145 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
4146 self_type& put(const Indices& inRowIndices, index_type inColIndex, const self_type& inValues)
4147 {
4148 const NdArray<index_type> colIndices = { inColIndex };
4149 return put(inRowIndices, colIndices, inValues);
4150 }
4151
4152 //============================================================================
4153 // Method Description:
4163 self_type& put(const Slice& inRowSlice, index_type inColIndex, const self_type& inValues)
4164 {
4165 const NdArray<index_type> colIndices = { inColIndex };
4166 return put(toIndices(inRowSlice, Axis::ROW), colIndices, inValues);
4167 }
4168
4169 //============================================================================
4170 // Method Description:
4180 template<typename Indices, type_traits::ndarray_int_concept<Indices> = 0>
4181 self_type& put(index_type inRowIndex, const Indices& inColIndices, const self_type& inValues)
4182 {
4183 const NdArray<index_type> rowIndices = { inRowIndex };
4184 return put(rowIndices, inColIndices, inValues);
4185 }
4186
4187 //============================================================================
4188 // Method Description:
4198 self_type& put(index_type inRowIndex, const Slice& inColSlice, const self_type& inValues)
4199 {
4200 const NdArray<index_type> rowIndices = { inRowIndex };
4201 return put(rowIndices, toIndices(inColSlice, Axis::COL), inValues);
4202 }
4203
4204 //============================================================================
4205 // Method Description:
4211 self_type& putMask(const NdArray<bool>& inMask, const value_type& inValue)
4212 {
4213 if (inMask.shape() != shape_)
4214 {
4215 THROW_INVALID_ARGUMENT_ERROR("input inMask must be the same shape as the array it is masking.");
4216 }
4217
4218 return put(inMask.flatnonzero(), inValue);
4219 }
4220
4221 //============================================================================
4222 // Method Description:
4228 self_type& putMask(const NdArray<bool>& inMask, const self_type& inValues)
4229 {
4230 if (inMask.shape() != shape_)
4231 {
4232 THROW_INVALID_ARGUMENT_ERROR("input inMask must be the same shape as the array it is masking.");
4233 }
4234
4235 if (inValues.isscalar())
4236 {
4237 put(inMask.flatnonzero(), inValues.item());
4238 }
4239 else
4240 {
4241 put(inMask.flatnonzero(), inValues);
4242 }
4243
4244 return *this;
4245 }
4246
4247 //============================================================================
4248 // Method Description:
4256 {
4257 reshape(size_);
4258 return *this;
4259 }
4260
4261 //============================================================================
4262 // Method Description:
4271 [[nodiscard]] self_type repeat(size_type inNumRows, size_type inNumCols) const
4272 {
4273 self_type returnArray(shape_.rows * inNumRows, shape_.cols * inNumCols);
4274
4275 for (size_type row = 0; row < inNumRows; ++row)
4276 {
4277 for (size_type col = 0; col < inNumCols; ++col)
4278 {
4279 std::vector<size_type> indices(shape_.size());
4280
4281 const size_type rowStart = row * shape_.rows;
4282 const size_type colStart = col * shape_.cols;
4283
4284 const size_type rowEnd = (row + 1) * shape_.rows;
4285 const size_type colEnd = (col + 1) * shape_.cols;
4286
4287 size_type counter = 0;
4288 for (size_type rowIdx = rowStart; rowIdx < rowEnd; ++rowIdx)
4289 {
4290 for (size_type colIdx = colStart; colIdx < colEnd; ++colIdx)
4291 {
4292 indices[counter++] = rowIdx * returnArray.shape_.cols + colIdx;
4293 }
4294 }
4295
4296 returnArray.put(NdArray<size_type>(indices), *this);
4297 }
4298 }
4299
4300 return returnArray;
4301 }
4302
4303 //============================================================================
4304 // Method Description:
4312 [[nodiscard]] self_type repeat(const Shape& inRepeatShape) const
4313 {
4314 return repeat(inRepeatShape.rows, inRepeatShape.cols);
4315 }
4316
4317 //============================================================================
4318 // Method Description:
4325 {
4327
4328 stl_algorithms::replace(begin(), end(), oldValue, newValue);
4329 return *this;
4330 }
4331
4332 //============================================================================
4333 // Method Description:
4348 {
4349 if (inSize != size_)
4350 {
4351 std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into shape ";
4352 errStr += "[" + utils::num2str(1) + ", " + utils::num2str(inSize) + "]";
4353 THROW_RUNTIME_ERROR(errStr);
4354 }
4355
4356 shape_.rows = 1;
4357 shape_.cols = inSize;
4358
4359 return *this;
4360 }
4361
4362 //============================================================================
4363 // Method Description:
4379 {
4380 if (inNumRows < 0)
4381 {
4382 if (size_ % inNumCols == 0)
4383 {
4384 return reshape(size_ / inNumCols, inNumCols);
4385 }
4386
4387 std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into a shape ";
4388 errStr += "with " + utils::num2str(inNumCols) + " columns";
4390 }
4391
4392 if (inNumCols < 0)
4393 {
4394 if (size_ % inNumRows == 0)
4395 {
4396 return reshape(inNumRows, size_ / inNumRows);
4397 }
4398
4399 std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into a shape ";
4400 errStr += "with " + utils::num2str(inNumRows) + " rows";
4402 }
4403
4404 if (static_cast<size_type>(inNumRows * inNumCols) != size_)
4405 {
4406 std::string errStr = "Cannot reshape array of size " + utils::num2str(size_) + " into shape ";
4407 errStr += "[" + utils::num2str(inNumRows) + ", " + utils::num2str(inNumCols) + "]";
4409 }
4410
4411 shape_.rows = static_cast<size_type>(inNumRows);
4412 shape_.cols = static_cast<size_type>(inNumCols);
4413
4414 return *this;
4415 }
4416
4417 //============================================================================
4418 // Method Description:
4432 self_type& reshape(const Shape& inShape)
4433 {
4434 return reshape(inShape.rows, inShape.cols);
4435 }
4436
4437 //============================================================================
4438 // Method Description:
4448 {
4449 newArray(Shape(inNumRows, inNumCols));
4450 return *this;
4451 }
4452
4453 //============================================================================
4454 // Method Description:
4462 self_type& resizeFast(const Shape& inShape)
4463 {
4464 return resizeFast(inShape.rows, inShape.cols);
4465 }
4466
4467 //============================================================================
4468 // Method Description:
4480 {
4481 std::vector<dtype> oldData(size_);
4482 stl_algorithms::copy(begin(), end(), oldData.begin());
4483
4484 const Shape inShape(inNumRows, inNumCols);
4485 const Shape oldShape = shape_;
4486
4487 newArray(inShape);
4488
4489 for (uint32 row = 0; row < inShape.rows; ++row)
4490 {
4491 for (uint32 col = 0; col < inShape.cols; ++col)
4492 {
4493 if (row >= oldShape.rows || col >= oldShape.cols)
4494 {
4495 operator()(row, col) = dtype{ 0 }; // zero fill
4496 }
4497 else
4498 {
4499 operator()(row, col) = oldData[row * oldShape.cols + col];
4500 }
4501 }
4502 }
4503
4504 return *this;
4505 }
4506
4507 //============================================================================
4508 // Method Description:
4518 self_type& resizeSlow(const Shape& inShape)
4519 {
4520 return resizeSlow(inShape.rows, inShape.cols);
4521 }
4522
4523 //============================================================================
4524 // Method Description:
4533 [[nodiscard]] self_type round(uint8 inNumDecimals = 0) const
4534 {
4535 STATIC_ASSERT_FLOAT(dtype);
4536
4537 self_type returnArray(shape_);
4538 const double multFactor = utils::power(10., inNumDecimals);
4539 const auto function = [multFactor](dtype value) noexcept -> dtype
4540 { return static_cast<dtype>(std::nearbyint(static_cast<double>(value) * multFactor) / multFactor); };
4541
4542 stl_algorithms::transform(cbegin(), cend(), returnArray.begin(), function);
4543
4544 return returnArray;
4545 }
4546
4547 //============================================================================
4548 // Method Description:
4554 [[nodiscard]] self_type row(size_type inRow) const
4555 {
4556 return self_type(cbegin(inRow), cend(inRow));
4557 }
4558
4559 //============================================================================
4560 // Method Description:
4566 [[nodiscard]] self_type rows(const NdArray<size_type>& inRows) const
4567 {
4568 auto returnArray = self_type(inRows.size(), shape_.cols);
4569 const auto cSlice = returnArray.cSlice();
4570
4571 for (size_type i = 0; i < inRows.size(); ++i)
4572 {
4573 returnArray.put(i, cSlice, row(inRows[i]));
4574 }
4575
4576 return returnArray;
4577 }
4578
4579 //============================================================================
4580 // Method Description:
4587 [[nodiscard]] const Shape& shape() const noexcept
4588 {
4589 return shape_;
4590 }
4591
4592 //============================================================================
4593 // Method Description:
4600 [[nodiscard]] size_type size() const noexcept
4601 {
4602 return size_;
4603 }
4604
4605 //============================================================================
4606 // Method Description:
4614 self_type& sort(Axis inAxis = Axis::NONE)
4615 {
4617
4618 const auto comparitor = [](dtype lhs, dtype rhs) noexcept -> bool
4619 { return lhs < rhs; }; // cppcheck-suppress returnTempReference
4620
4621 switch (inAxis)
4622 {
4623 case Axis::NONE:
4624 {
4625 stl_algorithms::sort(begin(), end(), comparitor);
4626 break;
4627 }
4628 case Axis::COL:
4629 {
4630 for (uint32 row = 0; row < shape_.rows; ++row)
4631 {
4632 stl_algorithms::sort(begin(row), end(row), comparitor);
4633 }
4634 break;
4635 }
4636 case Axis::ROW:
4637 {
4638 self_type transposedArray = transpose();
4639 for (uint32 row = 0; row < transposedArray.shape_.rows; ++row)
4640 {
4641 stl_algorithms::sort(transposedArray.begin(row), transposedArray.end(row), comparitor);
4642 }
4643
4644 *this = transposedArray.transpose();
4645 break;
4646 }
4647 }
4648
4649 return *this;
4650 }
4651
4652 //============================================================================
4653 // Method Description:
4658 [[nodiscard]] std::string str() const
4659 {
4661
4662 std::string out;
4663 out += "[";
4664 for (uint32 row = 0; row < shape_.rows; ++row)
4665 {
4666 out += "[";
4667 for (uint32 col = 0; col < shape_.cols; ++col)
4668 {
4669 out += utils::value2str(operator()(row, col)) + ", ";
4670 }
4671
4672 if (row == shape_.rows - 1)
4673 {
4674 out += "]";
4675 }
4676 else
4677 {
4678 out += "]\n";
4679 }
4680 }
4681 out += "]\n";
4682 return out;
4683 }
4684
4685 //============================================================================
4686 // Method Description:
4694 [[nodiscard]] self_type sum(Axis inAxis = Axis::NONE) const
4695 {
4697
4698 switch (inAxis)
4699 {
4700 case Axis::NONE:
4701 {
4702 self_type returnArray = { std::accumulate(cbegin(), cend(), dtype{ 0 }) };
4703 return returnArray;
4704 }
4705 case Axis::COL:
4706 {
4707 self_type returnArray(1, shape_.rows);
4708 for (uint32 row = 0; row < shape_.rows; ++row)
4709 {
4710 returnArray(0, row) = std::accumulate(cbegin(row), cend(row), dtype{ 0 });
4711 }
4712
4713 return returnArray;
4714 }
4715 case Axis::ROW:
4716 {
4717 return transpose().sum(Axis::COL);
4718 }
4719 default:
4720 {
4721 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
4722 return {}; // get rid of compiler warning
4723 }
4724 }
4725 }
4726
4727 //============================================================================
4728 // Method Description:
4735 [[nodiscard]] self_type swapaxes() const
4736 {
4737 return transpose();
4738 }
4739
4740 //============================================================================
4741 // Method Description:
4748 self_type& swapCols(index_type colIdx1, index_type colIdx2) noexcept
4749 {
4750 for (index_type row = 0; row < static_cast<index_type>(shape_.rows); ++row)
4751 {
4752 std::swap(operator()(row, colIdx1), operator()(row, colIdx2));
4753 }
4754
4755 return *this;
4756 }
4757
4758 //============================================================================
4759 // Method Description:
4766 self_type& swapRows(index_type rowIdx1, index_type rowIdx2) noexcept
4767 {
4768 for (index_type col = 0; col < static_cast<index_type>(shape_.cols); ++col)
4769 {
4770 std::swap(operator()(rowIdx1, col), operator()(rowIdx2, col));
4771 }
4772
4773 return *this;
4774 }
4775
4776 //============================================================================
4777 // Method Description:
4786 void tofile(const std::string& inFilename) const
4787 {
4788 dump(inFilename);
4789 }
4790
4791 //============================================================================
4792 // Method Description:
4802 void tofile(const std::string& inFilename, const char inSep) const
4803 {
4805
4806 std::filesystem::path f(inFilename);
4807 if (!f.has_extension())
4808 {
4809 f.replace_extension("txt");
4810 }
4811
4812 std::ofstream ofile(f.c_str());
4813 if (!ofile.good())
4814 {
4815 THROW_RUNTIME_ERROR("Input file could not be opened:\n\t" + inFilename);
4816 }
4817
4818 size_type counter = 0;
4819 for (auto value : *this)
4820 {
4821 ofile << value;
4822 if (counter++ != size_ - 1)
4823 {
4824 ofile << inSep;
4825 }
4826 }
4827 ofile.close();
4828 }
4829
4830 //============================================================================
4831 // Method Description:
4839 [[nodiscard]] NdArray<size_type> toIndices(Slice inSlice, Axis inAxis = Axis::NONE) const
4840 {
4841 size_type numElements = 0;
4842 switch (inAxis)
4843 {
4844 case Axis::NONE:
4845 {
4846 numElements = inSlice.numElements(size_);
4847 break;
4848 }
4849 case Axis::ROW:
4850 {
4851 numElements = inSlice.numElements(shape_.rows);
4852 break;
4853 }
4854 case Axis::COL:
4855 {
4856 numElements = inSlice.numElements(shape_.cols);
4857 break;
4858 }
4859 default:
4860 {
4861 // not actually possible, getting rid of compiler warning
4862 THROW_INVALID_ARGUMENT_ERROR("Invalid 'inAxis' option");
4863 }
4864 }
4865
4866 if (numElements == 0)
4867 {
4868 return {};
4869 }
4870
4871 NdArray<size_type> indices(1, numElements);
4872 indices[0] = static_cast<size_type>(inSlice.start);
4873 for (size_type i = 1; i < indices.size(); ++i)
4874 {
4875 indices[static_cast<index_type>(i)] = static_cast<size_type>(
4876 indices[static_cast<index_type>(i - size_type{ 1 })] + static_cast<size_type>(inSlice.step));
4877 }
4878
4879 return indices;
4880 }
4881
4882 //============================================================================
4883 // Method Description:
4888 [[nodiscard]] std::vector<dtype> toStlVector() const
4889 {
4890 return std::vector<dtype>(cbegin(), cend());
4891 }
4892
4893 //============================================================================
4894 // Method Description:
4905 [[nodiscard]] value_type trace(size_type inOffset = 0, Axis inAxis = Axis::ROW) const noexcept
4906 {
4908
4909 size_type rowStart = 0;
4910 size_type colStart = 0;
4911 switch (inAxis)
4912 {
4913 case Axis::ROW:
4914 {
4915 rowStart += inOffset;
4916 break;
4917 }
4918 case Axis::COL:
4919 {
4920 colStart += inOffset;
4921 break;
4922 }
4923 default:
4924 {
4925 // if the user input NONE, override back to ROW
4926 inAxis = Axis::ROW;
4927 break;
4928 }
4929 }
4930
4931 if (rowStart >= shape_.rows || colStart >= shape_.cols)
4932 {
4933 return dtype{ 0 };
4934 }
4935
4936 size_type col = colStart;
4937 dtype sum = 0;
4938 for (size_type row = rowStart; row < shape_.rows; ++row)
4939 {
4940 if (col >= shape_.cols)
4941 {
4942 break;
4943 }
4944 sum += operator()(row, col++);
4945 }
4946
4947 return sum;
4948 }
4949
4950 //============================================================================
4951 // Method Description:
4958 [[nodiscard]] self_type transpose() const
4959 {
4960 self_type transArray(shape_.cols, shape_.rows);
4961 for (uint32 row = 0; row < shape_.rows; ++row)
4962 {
4963 for (uint32 col = 0; col < shape_.cols; ++col)
4964 {
4965 transArray(col, row) = operator()(row, col);
4966 }
4967 }
4968 return transArray;
4969 }
4970
4971 //============================================================================
4972 // Method Description:
4976 self_type& zeros() noexcept
4977 {
4979
4980 fill(dtype{ 0 });
4981 return *this;
4982 }
4983
4984 private:
4985 //====================================Attributes==============================
4986 allocator_type allocator_{};
4987 Shape shape_{ 0, 0 };
4988 size_type size_{ 0 };
4989 Endian endianess_{ Endian::NATIVE };
4990 pointer array_{ nullptr };
4991 bool ownsPtr_{ false };
4992
4993 //============================================================================
4994 // Method Description:
4997 void deleteArray() noexcept
4998 {
4999 if (ownsPtr_ && array_ != nullptr)
5000 {
5001 allocator_.deallocate(array_, size_);
5002 }
5003
5004 array_ = nullptr;
5005 shape_.rows = shape_.cols = 0;
5006 size_ = 0;
5007 ownsPtr_ = false;
5008 endianess_ = Endian::NATIVE;
5009 }
5010
5011 //============================================================================
5012 // Method Description:
5015 void newArray()
5016 {
5017 if (size_ > 0)
5018 {
5019 array_ = allocator_.allocate(size_);
5020 ownsPtr_ = true;
5021 }
5022 }
5023
5024 //============================================================================
5025 // Method Description:
5030 void newArray(const Shape& inShape)
5031 {
5032 deleteArray();
5033
5034 shape_ = inShape;
5035 size_ = inShape.size();
5036 newArray();
5037 }
5038 };
5039
5040 // NOTE: this needs to be defined outside of the class to get rid of a compiler
5041 // error in Visual Studio
5042 template<typename dtype, class Alloc_>
5043 [[nodiscard]] std::pair<NdArray<uint32>, NdArray<uint32>> NdArray<dtype, Alloc_>::nonzero() const
5044 {
5046
5047 std::vector<size_type> rowIndices;
5048 std::vector<size_type> colIndices;
5049
5050 for (uint32 row = 0; row < shape_.rows; ++row)
5051 {
5052 for (uint32 col = 0; col < shape_.cols; ++col)
5053 {
5054 if (!utils::essentiallyEqual(operator()(row, col), dtype{ 0 }))
5055 {
5056 rowIndices.push_back(row);
5057 colIndices.push_back(col);
5058 }
5059 }
5060 }
5061
5062 return std::make_pair(NdArray<size_type>(rowIndices), NdArray<size_type>(colIndices));
5063 }
5064} // namespace nc
#define THROW_RUNTIME_ERROR(msg)
Definition Error.hpp:40
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition Error.hpp:37
#define STATIC_ASSERT_VALID_DTYPE(dtype)
Definition StaticAsserts.hpp:35
#define STATIC_ASSERT_FLOAT(dtype)
Definition StaticAsserts.hpp:50
#define STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype)
Definition StaticAsserts.hpp:56
#define STATIC_ASSERT_INTEGER(dtype)
Definition StaticAsserts.hpp:43
#define STATIC_ASSERT_ARITHMETIC(dtype)
Definition StaticAsserts.hpp:39
Custom column iterator for NdArray.
Definition NdArrayIterators.hpp:813
Custom column const_iterator for NdArray.
Definition NdArrayIterators.hpp:487
Custom const_iterator for NdArray.
Definition NdArrayIterators.hpp:41
Holds 1D and 2D arrays, the main work horse of the NumCpp library.
Definition NdArrayCore.hpp:139
NdArray(pointer inPtr, UIntType size, PointerPolicy policy)
Definition NdArrayCore.hpp:580
const_reverse_column_iterator rcolbegin() const noexcept
Definition NdArrayCore.hpp:1573
size_type dimSize(Axis inAxis) const noexcept
Definition NdArrayCore.hpp:2760
NdArray< size_type > toIndices(Slice inSlice, Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:4839
self_type operator[](Slice inSlice) const
Definition NdArrayCore.hpp:823
self_type max(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:3117
size_type size() const noexcept
Definition NdArrayCore.hpp:4600
reverse_iterator rbegin() noexcept
Definition NdArrayCore.hpp:1469
self_type at(index_type inRowIndex, const Slice &inColSlice) const
Definition NdArrayCore.hpp:1197
self_type columns(const NdArray< size_type > &inCols) const
Definition NdArrayCore.hpp:2500
self_type & put(const RowIndices &inRowIndices, const ColIndices &inColIndices, const self_type &inValues)
Definition NdArrayCore.hpp:4040
self_type & resizeSlow(size_type inNumRows, size_type inNumCols)
Definition NdArrayCore.hpp:4479
self_type & put(const Slice &inRowSlice, const ColIndices &inColIndices, const value_type &inValue)
Definition NdArrayCore.hpp:3934
self_type & zeros() noexcept
Definition NdArrayCore.hpp:4976
self_type & ones() noexcept
Definition NdArrayCore.hpp:3563
const_iterator cbegin() const noexcept
Definition NdArrayCore.hpp:1365
self_type at(const RowIndices &rowIndices, const ColIndices &colIndices) const
Definition NdArrayCore.hpp:1273
const_column_iterator ccolbegin(size_type inCol) const
Definition NdArrayCore.hpp:1454
NdArray< bool > contains(value_type inValue, Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:2521
const_pointer data() const noexcept
Definition NdArrayCore.hpp:2686
iterator end() noexcept
Definition NdArrayCore.hpp:1623
self_type & swapCols(index_type colIdx1, index_type colIdx2) noexcept
Definition NdArrayCore.hpp:4748
NdArray(const std::initializer_list< std::initializer_list< dtype > > &inList)
Definition NdArrayCore.hpp:239
reference at(index_type inRowIndex, index_type inColIndex)
Definition NdArrayCore.hpp:1068
self_type & put(const RowIndices &inRowIndices, const ColIndices &inColIndices, const value_type &inValue)
Definition NdArrayCore.hpp:3890
self_type repeat(const Shape &inRepeatShape) const
Definition NdArrayCore.hpp:4312
self_type at(Slice rowSlice, const Indices &colIndices) const
Definition NdArrayCore.hpp:1256
reference back(size_type row)
Definition NdArrayCore.hpp:2396
iterator end(size_type inRow)
Definition NdArrayCore.hpp:1635
self_type operator()(const RowIndices &rowIndices, const ColIndices &colIndices) const
Definition NdArrayCore.hpp:980
void tofile(const std::string &inFilename, const char inSep) const
Definition NdArrayCore.hpp:4802
const_column_iterator ccolbegin() const noexcept
Definition NdArrayCore.hpp:1442
NdArray(std::array< dtype, ArraySize > &inArray, PointerPolicy policy=PointerPolicy::COPY)
Definition NdArrayCore.hpp:274
NdArray(const std::deque< std::deque< dtype > > &in2dDeque)
Definition NdArrayCore.hpp:469
self_type & reshape(size_type inSize)
Definition NdArrayCore.hpp:4347
typename AllocTraits::pointer pointer
Definition NdArrayCore.hpp:152
self_type transpose() const
Definition NdArrayCore.hpp:4958
reverse_iterator rbegin(size_type inRow)
Definition NdArrayCore.hpp:1481
NdArray(std::vector< dtype > &inVector, PointerPolicy policy=PointerPolicy::COPY)
Definition NdArrayCore.hpp:348
NdArray< size_type > argsort(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:2193
const_reverse_column_iterator rcolend() const noexcept
Definition NdArrayCore.hpp:1881
self_type rows(const NdArray< size_type > &inRows) const
Definition NdArrayCore.hpp:4566
const dtype & const_reference
Definition NdArrayCore.hpp:155
bool issquare() const noexcept
Definition NdArrayCore.hpp:3085
bool isflat() const noexcept
Definition NdArrayCore.hpp:3021
Endian endianess() const noexcept
Definition NdArrayCore.hpp:2868
self_type dot(const self_type &inOtherArray) const
Definition NdArrayCore.hpp:2795
void tofile(const std::string &inFilename) const
Definition NdArrayCore.hpp:4786
const_reverse_column_iterator crcolbegin() const noexcept
Definition NdArrayCore.hpp:1596
self_type & swapRows(index_type rowIdx1, index_type rowIdx2) noexcept
Definition NdArrayCore.hpp:4766
const_reverse_column_iterator crcolend(size_type inCol) const
Definition NdArrayCore.hpp:1916
size_type numCols() const noexcept
Definition NdArrayCore.hpp:3541
column_iterator colbegin(size_type inCol)
Definition NdArrayCore.hpp:1404
self_type median(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:3207
const_reference at(index_type inRowIndex, index_type inColIndex) const
Definition NdArrayCore.hpp:1081
self_type at(const Slice &inSlice) const
Definition NdArrayCore.hpp:1111
NdArray< bool > none(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:3487
pointer data() noexcept
Definition NdArrayCore.hpp:2676
bool isempty() const noexcept
Definition NdArrayCore.hpp:3008
column_iterator colbegin() noexcept
Definition NdArrayCore.hpp:1392
NdArray(std::vector< std::array< dtype, Dim1Size > > &in2dArray, PointerPolicy policy=PointerPolicy::COPY)
Definition NdArrayCore.hpp:416
const_reference front(size_type row) const
Definition NdArrayCore.hpp:2958
reverse_column_iterator rcolend(size_type inCol)
Definition NdArrayCore.hpp:1866
self_type column(size_type inColumn) const
Definition NdArrayCore.hpp:2488
self_type prod(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:3679
NdArray(Iterator inFirst, Iterator inLast)
Definition NdArrayCore.hpp:521
reference at(index_type inIndex)
Definition NdArrayCore.hpp:1034
const Shape & shape() const noexcept
Definition NdArrayCore.hpp:4587
reverse_column_iterator rcolbegin() noexcept
Definition NdArrayCore.hpp:1546
self_type at(const Indices &inIndices) const
Definition NdArrayCore.hpp:1141
const_iterator cbegin(size_type inRow) const
Definition NdArrayCore.hpp:1377
const_column_iterator ccolend(size_type inCol) const
Definition NdArrayCore.hpp:1839
self_type at(index_type rowIndex, const Indices &colIndices) const
Definition NdArrayCore.hpp:1241
self_type & resizeFast(size_type inNumRows, size_type inNumCols)
Definition NdArrayCore.hpp:4447
const_iterator cend(size_type inRow) const
Definition NdArrayCore.hpp:1685
NdArray< size_type > flatnonzero() const
Definition NdArrayCore.hpp:2897
self_type & byteswap() noexcept
Definition NdArrayCore.hpp:2409
self_type & ravel()
Definition NdArrayCore.hpp:4255
self_type getByIndices(const NdArray< size_type > &inIndices) const
Definition NdArrayCore.hpp:2981
const_reverse_column_iterator rcolend(size_type inCol) const
Definition NdArrayCore.hpp:1893
NdArray(const std::vector< std::vector< dtype > > &in2dVector)
Definition NdArrayCore.hpp:382
self_type & partition(size_type inKth, Axis inAxis=Axis::NONE)
Definition NdArrayCore.hpp:3597
self_type & put(const Indices &inRowIndices, index_type inColIndex, const value_type &inValue)
Definition NdArrayCore.hpp:3967
const_iterator end(size_type inRow) const
Definition NdArrayCore.hpp:1662
self_type flatten() const
Definition NdArrayCore.hpp:2923
self_type & replace(value_type oldValue, value_type newValue)
Definition NdArrayCore.hpp:4324
reference back() noexcept
Definition NdArrayCore.hpp:2374
const_reverse_column_iterator crcolend() const noexcept
Definition NdArrayCore.hpp:1904
const_reference back(size_type row) const
Definition NdArrayCore.hpp:2385
reverse_column_iterator rcolbegin(size_type inCol)
Definition NdArrayCore.hpp:1558
self_type & put(Slice inRowSlice, Slice inColSlice, const self_type &inValues)
Definition NdArrayCore.hpp:4129
iterator begin(size_type inRow)
Definition NdArrayCore.hpp:1327
const_reverse_iterator rend() const noexcept
Definition NdArrayCore.hpp:1727
self_type copy() const
Definition NdArrayCore.hpp:2562
self_type round(uint8 inNumDecimals=0) const
Definition NdArrayCore.hpp:4533
std::vector< dtype > toStlVector() const
Definition NdArrayCore.hpp:4888
self_type swapaxes() const
Definition NdArrayCore.hpp:4735
const_reverse_column_iterator rcolbegin(size_type inCol) const
Definition NdArrayCore.hpp:1585
typename AllocTraits::difference_type difference_type
Definition NdArrayCore.hpp:158
const_iterator end() const noexcept
Definition NdArrayCore.hpp:1650
NdArray< dtypeOut > astype() const
Definition NdArrayCore.hpp:2257
self_type & put(index_type inRowIndex, const Slice &inColSlice, const self_type &inValues)
Definition NdArrayCore.hpp:4198
bool ownsInternalData() noexcept
Definition NdArrayCore.hpp:3577
self_type operator[](const NdArray< bool > &inMask) const
Definition NdArrayCore.hpp:835
self_type & fill(value_type inFillValue) noexcept
Definition NdArrayCore.hpp:2884
column_iterator colend() noexcept
Definition NdArrayCore.hpp:1777
NdArray(std::initializer_list< dtype > inList)
Definition NdArrayCore.hpp:222
self_type at(const Indices &rowIndices, Slice colSlice) const
Definition NdArrayCore.hpp:1227
const_reference back() const noexcept
Definition NdArrayCore.hpp:2363
std::pair< NdArray< size_type >, NdArray< size_type > > nonzero() const
Definition NdArrayCore.hpp:5043
self_type diagonal(index_type inOffset=0, Axis inAxis=Axis::ROW) const
Definition NdArrayCore.hpp:2715
self_type & put(index_type inRowIndex, const Indices &inColIndices, const self_type &inValues)
Definition NdArrayCore.hpp:4181
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition NdArrayCore.hpp:163
self_type at(const Slice &inRowSlice, index_type inColIndex) const
Definition NdArrayCore.hpp:1183
NdArray(const_pointer inPtr, UIntType1 numRows, UIntType2 numCols)
Definition NdArrayCore.hpp:558
NdArray< bool > any(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:1979
NdArray(const self_type &inOtherArray)
Definition NdArrayCore.hpp:633
NdArray(self_type &&inOtherArray) noexcept
Definition NdArrayCore.hpp:651
uint64 nbytes() const noexcept
Definition NdArrayCore.hpp:3309
NdArray< size_type > argmax(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:2024
self_type at(const NdArray< bool > &inMask) const
Definition NdArrayCore.hpp:1123
NdArray(const std::list< dtype > &inList)
Definition NdArrayCore.hpp:501
NdArray()=default
self_type & put(const Indices &inRowIndices, index_type inColIndex, const self_type &inValues)
Definition NdArrayCore.hpp:4146
const_reference front() const noexcept
Definition NdArrayCore.hpp:2936
~NdArray() noexcept
Definition NdArrayCore.hpp:668
Slice rSlice(index_type inStartIdx=0, size_type inStepSize=1) const
Definition NdArrayCore.hpp:1022
reference front() noexcept
Definition NdArrayCore.hpp:2947
self_type & put(const Slice &inRowSlice, index_type inColIndex, const self_type &inValues)
Definition NdArrayCore.hpp:4163
self_type & put(Slice inRowSlice, const ColIndices &inColIndices, const self_type &inValues)
Definition NdArrayCore.hpp:4113
self_type & put(const Slice &inRowSlice, index_type inColIndex, const value_type &inValue)
Definition NdArrayCore.hpp:3984
NdArray(size_type inNumRows, size_type inNumCols)
Definition NdArrayCore.hpp:196
self_type & putMask(const NdArray< bool > &inMask, const value_type &inValue)
Definition NdArrayCore.hpp:4211
Allocator allocator_type
Definition NdArrayCore.hpp:151
self_type & nans() noexcept
Definition NdArrayCore.hpp:3292
NdArray(pointer inPtr, UIntType1 numRows, UIntType2 numCols, PointerPolicy policy)
Definition NdArrayCore.hpp:599
void print() const
Definition NdArrayCore.hpp:3663
const_reverse_column_iterator crcolbegin(size_type inCol) const
Definition NdArrayCore.hpp:1608
self_type & reshape(const Shape &inShape)
Definition NdArrayCore.hpp:4432
size_type numRows() const noexcept
Definition NdArrayCore.hpp:3553
reverse_iterator rend(size_type inRow)
Definition NdArrayCore.hpp:1712
NdArray(size_type inSquareSize)
Definition NdArrayCore.hpp:182
self_type at(const Indices &rowIndices, index_type colIndex) const
Definition NdArrayCore.hpp:1212
reverse_iterator rend() noexcept
Definition NdArrayCore.hpp:1700
const_reverse_iterator rend(size_type inRow) const
Definition NdArrayCore.hpp:1739
typename AllocTraits::const_pointer const_pointer
Definition NdArrayCore.hpp:153
self_type & put(const Indices &inIndices, const self_type &inValues)
Definition NdArrayCore.hpp:3825
self_type & operator=(value_type inValue) noexcept
Definition NdArrayCore.hpp:714
const_reverse_iterator crbegin() const noexcept
Definition NdArrayCore.hpp:1519
NdArray(const_pointer inPtr, UIntType size)
Definition NdArrayCore.hpp:541
const_column_iterator colend(size_type inCol) const
Definition NdArrayCore.hpp:1816
std::reverse_iterator< iterator > reverse_iterator
Definition NdArrayCore.hpp:162
const_reverse_iterator rbegin(size_type inRow) const
Definition NdArrayCore.hpp:1508
self_type operator[](const Indices &inIndices) const
Definition NdArrayCore.hpp:849
const_iterator cend() const noexcept
Definition NdArrayCore.hpp:1673
self_type & resizeSlow(const Shape &inShape)
Definition NdArrayCore.hpp:4518
self_type & operator=(self_type &&rhs) noexcept
Definition NdArrayCore.hpp:731
std::string str() const
Definition NdArrayCore.hpp:4658
std::reverse_iterator< const_column_iterator > const_reverse_column_iterator
Definition NdArrayCore.hpp:168
self_type cumsum(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:2628
NdArray< bool > all(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:1935
self_type & resizeFast(const Shape &inShape)
Definition NdArrayCore.hpp:4462
self_type & put(index_type inRowIndex, const Indices &inColIndices, const value_type &inValue)
Definition NdArrayCore.hpp:4002
reference front(size_type row)
Definition NdArrayCore.hpp:2969
self_type & put(const RowIndices &inRowIndices, Slice inColSlice, const self_type &inValues)
Definition NdArrayCore.hpp:4096
NdArray(std::array< std::array< dtype, Dim1Size >, Dim0Size > &in2dArray, PointerPolicy policy=PointerPolicy::COPY)
Definition NdArrayCore.hpp:310
self_type repeat(size_type inNumRows, size_type inNumCols) const
Definition NdArrayCore.hpp:4271
const_iterator begin(size_type inRow) const
Definition NdArrayCore.hpp:1354
iterator begin() noexcept
Definition NdArrayCore.hpp:1315
const_column_iterator colbegin() const noexcept
Definition NdArrayCore.hpp:1419
bool isscalar() const noexcept
Definition NdArrayCore.hpp:3032
std::reverse_iterator< column_iterator > reverse_column_iterator
Definition NdArrayCore.hpp:167
self_type operator()(Slice inRowSlice, Slice inColSlice) const
Definition NdArrayCore.hpp:870
self_type & put(const Slice &inSlice, const value_type &inValue)
Definition NdArrayCore.hpp:3855
self_type newbyteorder(Endian inEndianess) const
Definition NdArrayCore.hpp:3324
value_type item() const
Definition NdArrayCore.hpp:3098
const_reference at(index_type inIndex) const
Definition NdArrayCore.hpp:1046
self_type & reshape(index_type inNumRows, index_type inNumCols)
Definition NdArrayCore.hpp:4378
const_column_iterator colend() const noexcept
Definition NdArrayCore.hpp:1804
self_type row(size_type inRow) const
Definition NdArrayCore.hpp:4554
self_type operator()(const Indices &rowIndices, index_type colIndex) const
Definition NdArrayCore.hpp:915
self_type at(const Slice &inRowSlice, const Slice &inColSlice) const
Definition NdArrayCore.hpp:1170
self_type operator()(Slice inRowSlice, index_type inColIndex) const
Definition NdArrayCore.hpp:884
const_reverse_iterator crend() const noexcept
Definition NdArrayCore.hpp:1750
self_type operator()(index_type rowIndex, const Indices &colIndices) const
Definition NdArrayCore.hpp:946
NdArray< dtype, Allocator > self_type
Definition NdArrayCore.hpp:149
const_column_iterator colbegin(size_type inCol) const
Definition NdArrayCore.hpp:1431
self_type & put(const Slice &inSlice, const self_type &inValues)
Definition NdArrayCore.hpp:3870
self_type & put(const Indices &inIndices, const value_type &inValue)
Definition NdArrayCore.hpp:3804
self_type cumprod(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:2576
const_column_iterator ccolend() const noexcept
Definition NdArrayCore.hpp:1827
reference operator()(index_type inRowIndex, index_type inColIndex) noexcept
Definition NdArrayCore.hpp:787
self_type operator()(index_type inRowIndex, Slice inColSlice) const
Definition NdArrayCore.hpp:899
reverse_column_iterator rcolend() noexcept
Definition NdArrayCore.hpp:1854
const_reverse_iterator rbegin() const noexcept
Definition NdArrayCore.hpp:1496
NdArray(const std::deque< dtype > &inDeque)
Definition NdArrayCore.hpp:452
void dump(const std::string &inFilename) const
Definition NdArrayCore.hpp:2841
dtype & reference
Definition NdArrayCore.hpp:154
self_type & put(const RowIndices &inRowIndices, const Slice &inColSlice, const value_type &inValue)
Definition NdArrayCore.hpp:3917
self_type & put(index_type inRowIndex, const Slice &inColSlice, const value_type &inValue)
Definition NdArrayCore.hpp:4019
value_type trace(size_type inOffset=0, Axis inAxis=Axis::ROW) const noexcept
Definition NdArrayCore.hpp:4905
pointer dataRelease() noexcept
Definition NdArrayCore.hpp:2698
self_type ptp(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:3723
self_type clip(value_type inMin, value_type inMax) const
Definition NdArrayCore.hpp:2449
self_type getByMask(const NdArray< bool > &inMask) const
Definition NdArrayCore.hpp:2995
uint32 size_type
Definition NdArrayCore.hpp:156
NdArray< bool > issorted(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:3044
self_type & operator=(const self_type &rhs)
Definition NdArrayCore.hpp:690
const_iterator begin() const noexcept
Definition NdArrayCore.hpp:1342
NdArray< size_type > argpartition(size_type inKth, Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:2120
column_iterator colend(size_type inCol)
Definition NdArrayCore.hpp:1789
NdArray< size_type > argmin(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:2071
const_reference operator[](index_type inIndex) const noexcept
Definition NdArrayCore.hpp:769
self_type operator()(Slice rowSlice, const Indices &colIndices) const
Definition NdArrayCore.hpp:962
const_reference operator()(index_type inRowIndex, index_type inColIndex) const noexcept
Definition NdArrayCore.hpp:800
self_type min(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:3161
self_type & putMask(const NdArray< bool > &inMask, const self_type &inValues)
Definition NdArrayCore.hpp:4228
dtype value_type
Definition NdArrayCore.hpp:150
reference operator[](index_type inIndex) noexcept
Definition NdArrayCore.hpp:757
Slice cSlice(index_type inStartIdx=0, size_type inStepSize=1) const
Definition NdArrayCore.hpp:1008
self_type & sort(Axis inAxis=Axis::NONE)
Definition NdArrayCore.hpp:4614
self_type & put(const Slice &inRowSlice, const Slice &inColSlice, const value_type &inValue)
Definition NdArrayCore.hpp:3950
const_reverse_iterator crend(size_type inRow) const
Definition NdArrayCore.hpp:1762
const_reverse_iterator crbegin(size_type inRow) const
Definition NdArrayCore.hpp:1531
int32 index_type
Definition NdArrayCore.hpp:157
NdArray(const Shape &inShape)
Definition NdArrayCore.hpp:209
self_type sum(Axis inAxis=Axis::NONE) const
Definition NdArrayCore.hpp:4694
self_type operator()(const Indices &rowIndices, Slice colSlice) const
Definition NdArrayCore.hpp:931
self_type & put(index_type inRow, index_type inCol, const value_type &inValue)
Definition NdArrayCore.hpp:3786
self_type & put(index_type inIndex, const value_type &inValue)
Definition NdArrayCore.hpp:3769
Custom iterator for NdArray.
Definition NdArrayIterators.hpp:313
A Shape Class for NdArrays.
Definition Core/shape.hpp:41
uint32 rows
Definition Core/shape.hpp:44
uint32 cols
Definition Core/shape.hpp:45
uint32 size() const noexcept
Definition Core/shape.hpp:104
A Class for slicing into NdArrays.
Definition Slice.hpp:45
int32 step
Definition Slice.hpp:50
int32 start
Definition Slice.hpp:48
uint32 numElements(uint32 inArraySize)
Definition Slice.hpp:195
void for_each(InputIt first, InputIt last, UnaryFunction f)
Definition StlAlgorithms.hpp:225
OutputIt copy(InputIt first, InputIt last, OutputIt destination) noexcept
Definition StlAlgorithms.hpp:97
void fill(ForwardIt first, ForwardIt last, const T &value) noexcept
Definition StlAlgorithms.hpp:183
constexpr bool is_ndarray_signed_int_v
Definition NdArrayCore.hpp:124
std::enable_if_t< is_ndarray_int_v< T >, int > ndarray_int_concept
Definition NdArrayCore.hpp:131
constexpr bool is_ndarray_int_v
Definition NdArrayCore.hpp:97
std::string num2str(dtype inNumber)
Definition num2str.hpp:44
Definition Cartesian.hpp:40
uint32 size(const NdArray< dtype > &inArray) noexcept
Definition size.hpp:43
NdArray< dtype > & resizeSlow(NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition resizeSlow.hpp:52
Axis
Enum To describe an axis.
Definition Enums.hpp:36
std::int64_t int64
Definition Types.hpp:35
NdArray< dtype > & put(NdArray< dtype > &inArray, int32 inIndex, const dtype &inValue)
Definition put.hpp:46
std::uint64_t uint64
Definition Types.hpp:39
NdArray< dtype > & resizeFast(NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition resizeFast.hpp:50
Endian
Enum for endianess.
Definition Enums.hpp:46
NdArray< dtype > arange(dtype inStart, dtype inStop, dtype inStep=1)
Definition arange.hpp:59
std::int32_t int32
Definition Types.hpp:36
std::uint8_t uint8
Definition Types.hpp:42
NdArray< dtype > sum(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition sum.hpp:46
NdArray< dtype > & reshape(NdArray< dtype > &inArray, uint32 inSize)
Definition reshape.hpp:51
PointerPolicy
Policy for NdArray constructor that takes in a pointer to data.
Definition Enums.hpp:56
NdArray< dtype > repeat(const NdArray< dtype > &inArray, uint32 inNumRows, uint32 inNumCols)
Definition repeat.hpp:49
std::uint32_t uint32
Definition Types.hpp:40
NdArray< dtype > transpose(const NdArray< dtype > &inArray)
Definition transpose.hpp:45
void dump(const NdArray< dtype > &inArray, const std::string &inFilename)
Definition dump.hpp:45
Definition NdArrayCore.hpp:78
Definition NdArrayCore.hpp:105