NumCpp  2.7.0
A Templatized Header Only C++ Implementation of the Python NumPy Library
NdArrayOperators.hpp
Go to the documentation of this file.
1 #pragma once
29 
38 
39 #include <algorithm>
40 #include <cmath>
41 #include <complex>
42 #include <functional>
43 
44 namespace nc
45 {
46  //============================================================================
47  // Method Description:
54  template<typename dtype>
56  {
58 
59  if (lhs.shape() != rhs.shape())
60  {
61  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
62  }
63 
64  stl_algorithms::transform(lhs.begin(), lhs.end(),
65  rhs.cbegin(), lhs.begin(), std::plus<dtype>());
66 
67  return lhs;
68  }
69 
70  //============================================================================
71  // Method Description:
78  template<typename dtype>
79  NdArray<std::complex<dtype>>& operator+=(NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
80  {
82 
83  if (lhs.shape() != rhs.shape())
84  {
85  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
86  }
87 
88  const auto function = [](std::complex<dtype>& val1, dtype val2) -> std::complex<dtype>
89  {
90  return val1 + val2;
91  };
92 
93  stl_algorithms::transform(lhs.begin(), lhs.end(),
94  rhs.cbegin(), lhs.begin(), function);
95 
96  return lhs;
97  }
98 
99  //============================================================================
100  // Method Description:
107  template<typename dtype>
109  {
111 
112  const auto function = [rhs](dtype& value) -> dtype
113  {
114  return value += rhs;
115  };
116 
117  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
118 
119  return lhs;
120  }
121 
122  //============================================================================
123  // Method Description:
130  template<typename dtype>
131  NdArray<std::complex<dtype>>& operator+=(NdArray<std::complex<dtype>>& lhs, dtype rhs)
132  {
134 
135  const auto function = [rhs](std::complex<dtype>& value) -> std::complex<dtype>
136  {
137  return value += rhs;
138  };
139 
140  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
141 
142  return lhs;
143  }
144 
145  //============================================================================
146  // Method Description:
153  template<typename dtype>
155  {
157 
158  if (lhs.shape() != rhs.shape())
159  {
160  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
161  }
162 
163  NdArray<dtype> returnArray(lhs.shape());
164 
165  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
166  rhs.cbegin(), returnArray.begin(), std::plus<dtype>());
167 
168  return returnArray;
169  }
170 
171  //============================================================================
172  // Method Description:
179  template<typename dtype>
180  NdArray<std::complex<dtype>> operator+(const NdArray<dtype>& lhs, const NdArray<std::complex<dtype>>& rhs)
181  {
183 
184  if (lhs.shape() != rhs.shape())
185  {
186  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
187  }
188 
189  const auto function = [](dtype val1, const std::complex<dtype>& val2) -> std::complex<dtype>
190  {
191  return val1 + val2;
192  };
193 
194  NdArray<std::complex<dtype>> returnArray(lhs.shape());
195 
196  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
197  rhs.cbegin(), returnArray.begin(), function);
198 
199  return returnArray;
200  }
201 
202  //============================================================================
203  // Method Description:
210  template<typename dtype>
211  NdArray<std::complex<dtype>> operator+(const NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
212  {
213  return rhs + lhs;
214  }
215 
216  //============================================================================
217  // Method Description:
224  template<typename dtype>
225  NdArray<dtype> operator+(const NdArray<dtype>& lhs, dtype rhs)
226  {
228 
229  const auto function = [rhs](dtype value) -> dtype
230  {
231  return value + rhs;
232  };
233 
234  NdArray<dtype> returnArray(lhs.shape());
235 
236  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
237 
238  return returnArray;
239  }
240 
241  //============================================================================
242  // Method Description:
249  template<typename dtype>
250  NdArray<dtype> operator+(dtype lhs, const NdArray<dtype>& rhs)
251  {
252  return rhs + lhs;
253  }
254 
255  //============================================================================
256  // Method Description:
263  template<typename dtype>
264  NdArray<std::complex<dtype>> operator+(const NdArray<dtype>& lhs, const std::complex<dtype>& rhs)
265  {
267 
268  const auto function = [rhs](dtype value) -> std::complex<dtype>
269  {
270  return value + rhs;
271  };
272 
273  NdArray<std::complex<dtype>> returnArray(lhs.shape());
274 
275  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
276 
277  return returnArray;
278  }
279 
280  //============================================================================
281  // Method Description:
288  template<typename dtype>
289  NdArray<std::complex<dtype>> operator+(const std::complex<dtype>& lhs, const NdArray<dtype>& rhs)
290  {
291  return rhs + lhs;
292  }
293 
294  //============================================================================
295  // Method Description:
302  template<typename dtype>
303  NdArray<std::complex<dtype>> operator+(const NdArray<std::complex<dtype>>& lhs, dtype rhs)
304  {
306 
307  const auto function = [rhs](std::complex<dtype> value) -> std::complex<dtype>
308  {
309  return value + rhs;
310  };
311 
312  NdArray<std::complex<dtype>> returnArray(lhs.shape());
313 
314  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
315 
316  return returnArray;
317  }
318 
319  //============================================================================
320  // Method Description:
327  template<typename dtype>
328  NdArray<std::complex<dtype>> operator+(dtype lhs, const NdArray<std::complex<dtype>>& rhs)
329  {
330  return rhs + lhs;
331  }
332 
333  //============================================================================
334  // Method Description:
341  template<typename dtype>
343  {
345 
346  if (lhs.shape() != rhs.shape())
347  {
348  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
349  }
350 
351  stl_algorithms::transform(lhs.begin(), lhs.end(),
352  rhs.cbegin(), lhs.begin(), std::minus<dtype>());
353 
354  return lhs;
355  }
356 
357  //============================================================================
358  // Method Description:
365  template<typename dtype>
366  NdArray<std::complex<dtype>>& operator-=(NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
367  {
369 
370  if (lhs.shape() != rhs.shape())
371  {
372  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
373  }
374 
375  const auto function = [](std::complex<dtype>& val1, dtype val2) -> std::complex<dtype>
376  {
377  return val1 - val2;
378  };
379 
380  stl_algorithms::transform(lhs.begin(), lhs.end(),
381  rhs.cbegin(), lhs.begin(), function);
382 
383  return lhs;
384  }
385 
386  //============================================================================
387  // Method Description:
394  template<typename dtype>
396  {
398 
399  const auto function = [rhs](dtype& value) -> dtype
400  {
401  return value -= rhs;
402  };
403 
404  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
405 
406  return lhs;
407  }
408 
409  //============================================================================
410  // Method Description:
417  template<typename dtype>
418  NdArray<std::complex<dtype>>& operator-=(NdArray<std::complex<dtype>>& lhs, dtype rhs)
419  {
421 
422  const auto function = [rhs](std::complex<dtype>& value) -> std::complex<dtype>
423  {
424  return value -= rhs;
425  };
426 
427  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
428 
429  return lhs;
430  }
431 
432  //============================================================================
433  // Method Description:
440  template<typename dtype>
442  {
444 
445  if (lhs.shape() != rhs.shape())
446  {
447  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
448  }
449 
450  NdArray<dtype> returnArray(lhs.shape());
451 
452  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
453  rhs.cbegin(), returnArray.begin(), std::minus<dtype>());
454 
455  return returnArray;
456  }
457 
458  //============================================================================
459  // Method Description:
466  template<typename dtype>
467  NdArray<std::complex<dtype>> operator-(const NdArray<dtype>& lhs, const NdArray<std::complex<dtype>>& rhs)
468  {
470 
471  if (lhs.shape() != rhs.shape())
472  {
473  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
474  }
475 
476  const auto function = [](dtype val1, const std::complex<dtype>& val2) -> std::complex<dtype>
477  {
478  return val1 - val2;
479  };
480 
481  NdArray<std::complex<dtype>> returnArray(lhs.shape());
482 
483  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
484  rhs.cbegin(), returnArray.begin(), function);
485 
486  return returnArray;
487  }
488 
489  //============================================================================
490  // Method Description:
497  template<typename dtype>
498  NdArray<std::complex<dtype>> operator-(const NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
499  {
501 
502  if (lhs.shape() != rhs.shape())
503  {
504  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
505  }
506 
507  const auto function = [](const std::complex<dtype>&val1, dtype val2) -> std::complex<dtype>
508  {
509  return val1 - val2;
510  };
511 
512  NdArray<std::complex<dtype>> returnArray(lhs.shape());
513 
514  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
515  rhs.cbegin(), returnArray.begin(), function);
516 
517  return returnArray;
518  }
519 
520  //============================================================================
521  // Method Description:
528  template<typename dtype>
529  NdArray<dtype> operator-(const NdArray<dtype>& lhs, dtype rhs)
530  {
532 
533  const auto function = [rhs](dtype value) -> dtype
534  {
535  return value - rhs;
536  };
537 
538  NdArray<dtype> returnArray(lhs.shape());
539 
540  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
541 
542  return returnArray;
543  }
544 
545  //============================================================================
546  // Method Description:
553  template<typename dtype>
554  NdArray<dtype> operator-(dtype lhs, const NdArray<dtype>& rhs)
555  {
557 
558  const auto function = [lhs](dtype value) -> dtype
559  {
560  return lhs - value;
561  };
562 
563  NdArray<dtype> returnArray(rhs.shape());
564 
565  stl_algorithms::transform(rhs.cbegin(), rhs.cend(), returnArray.begin(), function);
566 
567  return returnArray;
568  }
569 
570  //============================================================================
571  // Method Description:
578  template<typename dtype>
579  NdArray<std::complex<dtype>> operator-(const NdArray<dtype>& lhs, const std::complex<dtype>& rhs)
580  {
582 
583  const auto function = [rhs](dtype value) -> std::complex<dtype>
584  {
585  return value - rhs;
586  };
587 
588  NdArray<std::complex<dtype>> returnArray(lhs.shape());
589 
590  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
591 
592  return returnArray;
593  }
594 
595  //============================================================================
596  // Method Description:
603  template<typename dtype>
604  NdArray<std::complex<dtype>> operator-(const std::complex<dtype>& lhs, const NdArray<dtype>& rhs)
605  {
607 
608  const auto function = [lhs](dtype value) -> std::complex<dtype>
609  {
610  return lhs - value;
611  };
612 
613  NdArray<std::complex<dtype>> returnArray(rhs.shape());
614 
615  stl_algorithms::transform(rhs.cbegin(), rhs.cend(), returnArray.begin(), function);
616 
617  return returnArray;
618  }
619 
620  //============================================================================
621  // Method Description:
628  template<typename dtype>
629  NdArray<std::complex<dtype>> operator-(const NdArray<std::complex<dtype>>& lhs, dtype rhs)
630  {
632 
633  const auto function = [rhs](std::complex<dtype> value) -> std::complex<dtype>
634  {
635  return value - rhs;
636  };
637 
638  NdArray<std::complex<dtype>> returnArray(lhs.shape());
639 
640  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
641 
642  return returnArray;
643  }
644 
645  //============================================================================
646  // Method Description:
653  template<typename dtype>
654  NdArray<std::complex<dtype>> operator-(dtype lhs, const NdArray<std::complex<dtype>>& rhs)
655  {
657 
658  const auto function = [lhs](std::complex<dtype> value) -> std::complex<dtype>
659  {
660  return lhs - value;
661  };
662 
663  NdArray<std::complex<dtype>> returnArray(rhs.shape());
664 
665  stl_algorithms::transform(rhs.cbegin(), rhs.cend(), returnArray.begin(), function);
666 
667  return returnArray;
668  }
669 
670  //============================================================================
671  // Method Description:
676  template<typename dtype>
678  {
679  const auto function = [](dtype value) -> dtype
680  {
681  return -value;
682  };
683 
684  auto returnArray = NdArray<dtype>(inArray.shape());
685  stl_algorithms::transform(inArray.cbegin(), inArray.cend(), returnArray.begin(), function);
686  return returnArray;
687  }
688 
689  //============================================================================
690  // Method Description:
697  template<typename dtype>
699  {
701 
702  if (lhs.shape() != rhs.shape())
703  {
704  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
705  }
706 
707  stl_algorithms::transform(lhs.begin(), lhs.end(),
708  rhs.cbegin(), lhs.begin(), std::multiplies<dtype>());
709 
710  return lhs;
711  }
712 
713  //============================================================================
714  // Method Description:
721  template<typename dtype>
722  NdArray<std::complex<dtype>>& operator*=(NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
723  {
725 
726  if (lhs.shape() != rhs.shape())
727  {
728  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
729  }
730 
731  const auto function = [](std::complex<dtype>& val1, dtype val2) -> std::complex<dtype>
732  {
733  return val1 * val2;
734  };
735 
736  stl_algorithms::transform(lhs.begin(), lhs.end(),
737  rhs.cbegin(), lhs.begin(), function);
738 
739  return lhs;
740  }
741 
742  //============================================================================
743  // Method Description:
750  template<typename dtype>
752  {
754 
755  const auto function = [rhs](dtype& value) -> dtype
756  {
757  return value *= rhs;
758  };
759 
760  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
761 
762  return lhs;
763  }
764 
765  //============================================================================
766  // Method Description:
773  template<typename dtype>
774  NdArray<std::complex<dtype>>& operator*=(NdArray<std::complex<dtype>>& lhs, dtype rhs)
775  {
777 
778  const auto function = [rhs](std::complex<dtype>& value) -> std::complex<dtype>
779  {
780  return value *= rhs;
781  };
782 
783  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
784 
785  return lhs;
786  }
787 
788  //============================================================================
789  // Method Description:
796  template<typename dtype>
798  {
800 
801  if (lhs.shape() != rhs.shape())
802  {
803  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
804  }
805 
806  NdArray<dtype> returnArray(lhs.shape());
807 
808  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
809  rhs.cbegin(), returnArray.begin(), std::multiplies<dtype>());
810 
811  return returnArray;
812  }
813 
814  //============================================================================
815  // Method Description:
822  template<typename dtype>
823  NdArray<std::complex<dtype>> operator*(const NdArray<dtype>& lhs, const NdArray<std::complex<dtype>>& rhs)
824  {
826 
827  if (lhs.shape() != rhs.shape())
828  {
829  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
830  }
831 
832  const auto function = [](dtype val1, const std::complex<dtype>& val2) -> std::complex<dtype>
833  {
834  return val1 * val2;
835  };
836 
837  NdArray<std::complex<dtype>> returnArray(lhs.shape());
838 
839  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
840  rhs.cbegin(), returnArray.begin(), function);
841 
842  return returnArray;
843  }
844 
845  //============================================================================
846  // Method Description:
853  template<typename dtype>
854  NdArray<std::complex<dtype>> operator*(const NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
855  {
856  return rhs * lhs;
857  }
858 
859  //============================================================================
860  // Method Description:
867  template<typename dtype>
868  NdArray<dtype> operator*(const NdArray<dtype>& lhs, dtype rhs)
869  {
871 
872  const auto function = [rhs](dtype value) -> dtype
873  {
874  return value * rhs;
875  };
876 
877  NdArray<dtype> returnArray(lhs.shape());
878 
879  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
880 
881  return returnArray;
882  }
883 
884  //============================================================================
885  // Method Description:
892  template<typename dtype>
893  NdArray<dtype> operator*(dtype lhs, const NdArray<dtype>& rhs)
894  {
895  return rhs * lhs;
896  }
897 
898  //============================================================================
899  // Method Description:
906  template<typename dtype>
907  NdArray<std::complex<dtype>> operator*(const NdArray<dtype>& lhs, const std::complex<dtype>& rhs)
908  {
910 
911  const auto function = [rhs](dtype value) -> std::complex<dtype>
912  {
913  return value * rhs;
914  };
915 
916  NdArray<std::complex<dtype>> returnArray(lhs.shape());
917 
918  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
919 
920  return returnArray;
921  }
922 
923  //============================================================================
924  // Method Description:
931  template<typename dtype>
932  NdArray<std::complex<dtype>> operator*(const std::complex<dtype>& lhs, const NdArray<dtype>& rhs)
933  {
934  return rhs * lhs;
935  }
936 
937  //============================================================================
938  // Method Description:
945  template<typename dtype>
946  NdArray<std::complex<dtype>> operator*(const NdArray<std::complex<dtype>>& lhs, dtype rhs)
947  {
949 
950  const auto function = [rhs](std::complex<dtype> value) -> std::complex<dtype>
951  {
952  return value * rhs;
953  };
954 
955  NdArray<std::complex<dtype>> returnArray(lhs.shape());
956 
957  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
958 
959  return returnArray;
960  }
961 
962  //============================================================================
963  // Method Description:
970  template<typename dtype>
971  NdArray<std::complex<dtype>> operator*(dtype lhs, const NdArray<std::complex<dtype>>& rhs)
972  {
973  return rhs * lhs;
974  }
975 
976  //============================================================================
977  // Method Description:
984  template<typename dtype>
986  {
988 
989  if (lhs.shape() != rhs.shape())
990  {
991  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
992  }
993 
994  stl_algorithms::transform(lhs.begin(), lhs.end(),
995  rhs.cbegin(), lhs.begin(), std::divides<dtype>());
996 
997  return lhs;
998  }
999 
1000  //============================================================================
1001  // Method Description:
1008  template<typename dtype>
1009  NdArray<std::complex<dtype>>& operator/=(NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
1010  {
1011  STATIC_ASSERT_ARITHMETIC(dtype);
1012 
1013  if (lhs.shape() != rhs.shape())
1014  {
1015  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1016  }
1017 
1018  const auto function = [](std::complex<dtype>& val1, dtype val2) -> std::complex<dtype>
1019  {
1020  return val1 / val2;
1021  };
1022 
1023  stl_algorithms::transform(lhs.begin(), lhs.end(),
1024  rhs.cbegin(), lhs.begin(), function);
1025 
1026  return lhs;
1027  }
1028 
1029  //============================================================================
1030  // Method Description:
1037  template<typename dtype>
1039  {
1041 
1042  const auto function = [rhs](dtype& value) -> dtype
1043  {
1044  return value /= rhs;
1045  };
1046 
1047  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
1048 
1049  return lhs;
1050  }
1051 
1052  //============================================================================
1053  // Method Description:
1060  template<typename dtype>
1061  NdArray<std::complex<dtype>>& operator/=(NdArray<std::complex<dtype>>& lhs, dtype rhs)
1062  {
1063  STATIC_ASSERT_ARITHMETIC(dtype);
1064 
1065  const auto function = [rhs](std::complex<dtype>& value) -> std::complex<dtype>
1066  {
1067  return value /= rhs;
1068  };
1069 
1070  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
1071 
1072  return lhs;
1073  }
1074 
1075  //============================================================================
1076  // Method Description:
1083  template<typename dtype>
1085  {
1087 
1088  if (lhs.shape() != rhs.shape())
1089  {
1090  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1091  }
1092 
1093  NdArray<dtype> returnArray(lhs.shape());
1094 
1095  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
1096  rhs.cbegin(), returnArray.begin(), std::divides<dtype>());
1097 
1098  return returnArray;
1099  }
1100 
1101  //============================================================================
1102  // Method Description:
1109  template<typename dtype>
1110  NdArray<std::complex<dtype>> operator/(const NdArray<dtype>& lhs, const NdArray<std::complex<dtype>>& rhs)
1111  {
1112  STATIC_ASSERT_ARITHMETIC(dtype);
1113 
1114  if (lhs.shape() != rhs.shape())
1115  {
1116  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1117  }
1118 
1119  NdArray<std::complex<dtype>> returnArray(lhs.shape());
1120 
1121  const auto function = [](dtype val1, const std::complex<dtype>& val2) -> std::complex<dtype>
1122  {
1123  return val1 / val2;
1124  };
1125 
1126  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
1127  rhs.cbegin(), returnArray.begin(), function);
1128 
1129  return returnArray;
1130  }
1131 
1132  //============================================================================
1133  // Method Description:
1140  template<typename dtype>
1141  NdArray<std::complex<dtype>> operator/(const NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
1142  {
1143  STATIC_ASSERT_ARITHMETIC(dtype);
1144 
1145  if (lhs.shape() != rhs.shape())
1146  {
1147  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1148  }
1149 
1150  const auto function = [](const std::complex<dtype>&val1, dtype val2) -> std::complex<dtype>
1151  {
1152  return val1 / val2;
1153  };
1154 
1155  NdArray<std::complex<dtype>> returnArray(lhs.shape());
1156 
1157  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
1158  rhs.cbegin(), returnArray.begin(), function);
1159 
1160  return returnArray;
1161  }
1162 
1163  //============================================================================
1164  // Method Description:
1171  template<typename dtype>
1172  NdArray<dtype> operator/(const NdArray<dtype>& lhs, dtype rhs)
1173  {
1175 
1176  const auto function = [rhs](dtype value) -> dtype
1177  {
1178  return value / rhs;
1179  };
1180 
1181  NdArray<dtype> returnArray(lhs.shape());
1182 
1183  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
1184 
1185  return returnArray;
1186  }
1187 
1188  //============================================================================
1189  // Method Description:
1196  template<typename dtype>
1197  NdArray<dtype> operator/(dtype lhs, const NdArray<dtype>& rhs)
1198  {
1200 
1201  const auto function = [lhs](dtype value) -> dtype
1202  {
1203  return lhs / value;
1204  };
1205 
1206  NdArray<dtype> returnArray(rhs.shape());
1207 
1208  stl_algorithms::transform(rhs.cbegin(), rhs.cend(), returnArray.begin(), function);
1209 
1210  return returnArray;
1211  }
1212 
1213  //============================================================================
1214  // Method Description:
1221  template<typename dtype>
1222  NdArray<std::complex<dtype>> operator/(const NdArray<dtype>& lhs, const std::complex<dtype>& rhs)
1223  {
1224  STATIC_ASSERT_ARITHMETIC(dtype);
1225 
1226  const auto function = [rhs](dtype value) -> std::complex<dtype>
1227  {
1228  return value / rhs;
1229  };
1230 
1231  NdArray<std::complex<dtype>> returnArray(lhs.shape());
1232 
1233  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
1234 
1235  return returnArray;
1236  }
1237 
1238  //============================================================================
1239  // Method Description:
1246  template<typename dtype>
1247  NdArray<std::complex<dtype>> operator/(const std::complex<dtype>& lhs, const NdArray<dtype>& rhs)
1248  {
1249  STATIC_ASSERT_ARITHMETIC(dtype);
1250 
1251  const auto function = [lhs](dtype value) -> std::complex<dtype>
1252  {
1253  return lhs / value;
1254  };
1255 
1256  NdArray<std::complex<dtype>> returnArray(rhs.shape());
1257 
1258  stl_algorithms::transform(rhs.cbegin(), rhs.cend(), returnArray.begin(), function);
1259 
1260  return returnArray;
1261  }
1262 
1263  //============================================================================
1264  // Method Description:
1271  template<typename dtype>
1272  NdArray<std::complex<dtype>> operator/(const NdArray<std::complex<dtype>>& lhs, dtype rhs)
1273  {
1274  STATIC_ASSERT_ARITHMETIC(dtype);
1275 
1276  const auto function = [rhs](std::complex<dtype> value) -> std::complex<dtype>
1277  {
1278  return value / rhs;
1279  };
1280 
1281  NdArray<std::complex<dtype>> returnArray(lhs.shape());
1282 
1283  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
1284 
1285  return returnArray;
1286  }
1287 
1288  //============================================================================
1289  // Method Description:
1296  template<typename dtype>
1297  NdArray<std::complex<dtype>> operator/(dtype lhs, const NdArray<std::complex<dtype>>& rhs)
1298  {
1299  STATIC_ASSERT_ARITHMETIC(dtype);
1300 
1301  const auto function = [lhs](std::complex<dtype> value) -> std::complex<dtype>
1302  {
1303  return lhs / value;
1304  };
1305 
1306  NdArray<std::complex<dtype>> returnArray(rhs.shape());
1307 
1308  stl_algorithms::transform(rhs.cbegin(), rhs.cend(), returnArray.begin(), function);
1309 
1310  return returnArray;
1311  }
1312 
1313  //============================================================================
1314  // Method Description:
1321  template<typename dtype,
1322  enable_if_t<std::is_integral<dtype>::value, int> = 0>
1324  {
1325  if (lhs.shape() != rhs.shape())
1326  {
1327  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1328  }
1329 
1330  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::modulus<dtype>());
1331 
1332  return lhs;
1333  }
1334 
1335  //============================================================================
1336  // Method Description:
1343  template<typename dtype,
1344  enable_if_t<std::is_floating_point<dtype>::value, int> = 0>
1345  NdArray<dtype>& operator%=(NdArray<dtype>& lhs, const NdArray<dtype>& rhs)
1346  {
1347  if (lhs.shape() != rhs.shape())
1348  {
1349  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1350  }
1351 
1352  const auto function = [](const dtype value1, const dtype value2) -> dtype
1353  {
1354  return std::fmod(value1, value2);
1355  };
1356 
1357  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), function);
1358 
1359  return lhs;
1360  }
1361 
1362  //============================================================================
1363  // Method Description:
1370  template<typename dtype,
1371  enable_if_t<std::is_integral<dtype>::value, int> = 0>
1373  {
1374  const auto function = [rhs](dtype& value) -> dtype
1375  {
1376  return value %= rhs;
1377  };
1378 
1379  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
1380 
1381  return lhs;
1382  }
1383 
1384  //============================================================================
1385  // Method Description:
1392  template<typename dtype,
1393  enable_if_t<std::is_floating_point<dtype>::value, int> = 0>
1394  NdArray<dtype>& operator%=(NdArray<dtype>& lhs, dtype rhs)
1395  {
1396  const auto function = [rhs](dtype& value) -> void
1397  {
1398  value = std::fmod(value, rhs);
1399  };
1400 
1401  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
1402 
1403  return lhs;
1404  }
1405 
1406  //============================================================================
1407  // Method Description:
1414  template<typename dtype>
1416  {
1417  auto returnArray = NdArray<dtype>(lhs);
1418  returnArray %= rhs;
1419  return returnArray;
1420  }
1421 
1422  //============================================================================
1423  // Method Description:
1430  template<typename dtype>
1431  NdArray<dtype> operator%(const NdArray<dtype>& lhs, dtype rhs)
1432  {
1433  auto returnArray = NdArray<dtype>(lhs);
1434  returnArray %= rhs;
1435  return returnArray;
1436  }
1437 
1438  //============================================================================
1439  // Method Description:
1446  template<typename dtype,
1447  enable_if_t<std::is_integral<dtype>::value, int> = 0>
1448  NdArray<dtype> operator%(dtype lhs, const NdArray<dtype>& rhs)
1449  {
1450  NdArray<dtype> returnArray(rhs.shape());
1451  stl_algorithms::transform(rhs.begin(), rhs.end(), returnArray.begin(),
1452  [lhs](dtype value) -> dtype
1453  {
1454  return lhs % value;
1455  });
1456 
1457  return returnArray;
1458  }
1459 
1460  //============================================================================
1461  // Method Description:
1468  template<typename dtype,
1469  enable_if_t<std::is_floating_point<dtype>::value, int> = 0>
1470  NdArray<dtype> operator%(dtype lhs, const NdArray<dtype>& rhs)
1471  {
1472  NdArray<dtype> returnArray(rhs.shape());
1473  stl_algorithms::transform(rhs.begin(), rhs.end(), returnArray.begin(),
1474  [lhs](dtype value) -> dtype
1475  {
1476  return std::fmod(lhs, value);
1477  });
1478 
1479  return returnArray;
1480  }
1481 
1482  //============================================================================
1483  // Method Description:
1490  template<typename dtype>
1492  {
1493  STATIC_ASSERT_INTEGER(dtype);
1494 
1495  if (lhs.shape() != rhs.shape())
1496  {
1497  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1498  }
1499 
1500  stl_algorithms::transform(lhs.begin(), lhs.end(),
1501  rhs.cbegin(), lhs.begin(), std::bit_or<dtype>());
1502 
1503  return lhs;
1504  }
1505 
1506  //============================================================================
1507  // Method Description:
1514  template<typename dtype>
1516  {
1517  STATIC_ASSERT_INTEGER(dtype);
1518 
1519  const auto function = [rhs](dtype& value) -> dtype
1520  {
1521  return value |= rhs;
1522  };
1523 
1524  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
1525 
1526  return lhs;
1527  }
1528 
1529  //============================================================================
1530  // Method Description:
1537  template<typename dtype>
1539  {
1540  auto returnArray = NdArray<dtype>(lhs);
1541  returnArray |= rhs;
1542  return returnArray;
1543  }
1544 
1545  //============================================================================
1546  // Method Description:
1553  template<typename dtype>
1554  NdArray<dtype> operator|(const NdArray<dtype>& lhs, dtype rhs)
1555  {
1556  auto returnArray = NdArray<dtype>(lhs);
1557  returnArray |= rhs;
1558  return returnArray;
1559  }
1560 
1561  //============================================================================
1562  // Method Description:
1569  template<typename dtype>
1570  NdArray<dtype> operator|(dtype lhs, const NdArray<dtype>& rhs)
1571  {
1572  return rhs | lhs;
1573  }
1574 
1575  //============================================================================
1576  // Method Description:
1583  template<typename dtype>
1585  {
1586  STATIC_ASSERT_INTEGER(dtype);
1587 
1588  if (lhs.shape() != rhs.shape())
1589  {
1590  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1591  }
1592 
1593  stl_algorithms::transform(lhs.begin(), lhs.end(),
1594  rhs.cbegin(), lhs.begin(), std::bit_and<dtype>());
1595 
1596  return lhs;
1597  }
1598 
1599  //============================================================================
1600  // Method Description:
1607  template<typename dtype>
1609  {
1610  STATIC_ASSERT_INTEGER(dtype);
1611 
1612  const auto function = [rhs](dtype& value) -> dtype
1613  {
1614  return value &= rhs;
1615  };
1616 
1617  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
1618 
1619  return lhs;
1620  }
1621 
1622  //============================================================================
1623  // Method Description:
1630  template<typename dtype>
1632  {
1633  auto returnArray = NdArray<dtype>(lhs);
1634  returnArray &= rhs;
1635  return returnArray;
1636  }
1637 
1638  //============================================================================
1639  // Method Description:
1646  template<typename dtype>
1647  NdArray<dtype> operator&(const NdArray<dtype>& lhs, dtype rhs)
1648  {
1649  auto returnArray = NdArray<dtype>(lhs);
1650  returnArray &= rhs;
1651  return returnArray;
1652  }
1653 
1654  //============================================================================
1655  // Method Description:
1662  template<typename dtype>
1663  NdArray<dtype> operator&(dtype lhs, const NdArray<dtype>& rhs)
1664  {
1665  return rhs & lhs;
1666  }
1667 
1668  //============================================================================
1669  // Method Description:
1676  template<typename dtype>
1678  {
1679  STATIC_ASSERT_INTEGER(dtype);
1680 
1681  if (lhs.shape() != rhs.shape())
1682  {
1683  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1684  }
1685 
1686  stl_algorithms::transform(lhs.begin(), lhs.end(),
1687  rhs.cbegin(), lhs.begin(), std::bit_xor<dtype>());
1688 
1689  return lhs;
1690  }
1691 
1692  //============================================================================
1693  // Method Description:
1700  template<typename dtype>
1702  {
1703  STATIC_ASSERT_INTEGER(dtype);
1704 
1705  const auto function = [rhs](dtype& value) -> dtype
1706  {
1707  return value ^= rhs;
1708  };
1709 
1710  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
1711 
1712  return lhs;
1713  }
1714 
1715  //============================================================================
1716  // Method Description:
1723  template<typename dtype>
1725  {
1726  auto returnArray = NdArray<dtype>(lhs);
1727  returnArray ^= rhs;
1728  return returnArray;
1729  }
1730 
1731  //============================================================================
1732  // Method Description:
1739  template<typename dtype>
1740  NdArray<dtype> operator^(const NdArray<dtype>& lhs, dtype rhs)
1741  {
1742  auto returnArray = NdArray<dtype>(lhs);
1743  returnArray ^= rhs;
1744  return returnArray;
1745  }
1746 
1747  //============================================================================
1748  // Method Description:
1755  template<typename dtype>
1756  NdArray<dtype> operator^(dtype lhs, const NdArray<dtype>& rhs)
1757  {
1758  return rhs ^ lhs;
1759  }
1760 
1761  //============================================================================
1762  // Method Description:
1768  template<typename dtype>
1770  {
1771  STATIC_ASSERT_INTEGER(dtype);
1772 
1773  const auto function = [](dtype value) -> dtype
1774  {
1775  return ~value;
1776  };
1777 
1778  NdArray<dtype> returnArray(inArray.shape());
1779 
1780  stl_algorithms::transform(inArray.cbegin(), inArray.cend(),
1781  returnArray.begin(), function);
1782 
1783  return returnArray;
1784  }
1785 
1786  //============================================================================
1787  // Method Description:
1794  template<typename dtype>
1796  {
1797  STATIC_ASSERT_ARITHMETIC(dtype);
1798 
1799  if (lhs.shape() != rhs.shape())
1800  {
1801  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1802  }
1803 
1804  const auto function = [](dtype value1, dtype value2) -> bool
1805  {
1806  return value1 && value2;
1807  };
1808 
1809  NdArray<bool> returnArray(lhs.shape());
1810  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
1811  rhs.cbegin(), returnArray.begin(), function);
1812 
1813  return returnArray;
1814  }
1815 
1816  //============================================================================
1817  // Method Description:
1824  template<typename dtype>
1825  NdArray<bool> operator&&(const NdArray<dtype>& lhs, dtype rhs)
1826  {
1827  STATIC_ASSERT_ARITHMETIC(dtype);
1828 
1829  NdArray<bool> returnArray(lhs.shape());
1830 
1831  const auto function = [rhs](dtype value) -> bool
1832  {
1833  return value && rhs;
1834  };
1835 
1836  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
1837  returnArray.begin(), function);
1838 
1839  return returnArray;
1840  }
1841 
1842  //============================================================================
1843  // Method Description:
1850  template<typename dtype>
1851  NdArray<bool> operator&&(dtype lhs, const NdArray<dtype>& rhs)
1852  {
1853  return rhs && lhs;
1854  }
1855 
1856  //============================================================================
1857  // Method Description:
1864  template<typename dtype>
1866  {
1867  STATIC_ASSERT_ARITHMETIC(dtype);
1868 
1869  if (lhs.shape() != rhs.shape())
1870  {
1871  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1872  }
1873 
1874  const auto function = [](dtype value1, dtype value2) -> bool
1875  {
1876  return value1 || value2;
1877  };
1878 
1879  NdArray<bool> returnArray(lhs.shape());
1880  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
1881  rhs.cbegin(), returnArray.begin(), function);
1882 
1883  return returnArray;
1884  }
1885 
1886  //============================================================================
1887  // Method Description:
1894  template<typename dtype>
1895  NdArray<bool> operator||(const NdArray<dtype>& lhs, dtype rhs)
1896  {
1897  STATIC_ASSERT_ARITHMETIC(dtype);
1898 
1899  NdArray<bool> returnArray(lhs.shape());
1900 
1901  const auto function = [rhs](dtype value) -> bool
1902  {
1903  return value || rhs;
1904  };
1905 
1906  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
1907  returnArray.begin(), function);
1908 
1909  return returnArray;
1910  }
1911 
1912  //============================================================================
1913  // Method Description:
1920  template<typename dtype>
1921  NdArray<bool> operator||(dtype lhs, const NdArray<dtype>& rhs)
1922  {
1923  return rhs || lhs;
1924  }
1925 
1926  //============================================================================
1927  // Method Description:
1933  template<typename dtype>
1935  {
1936  STATIC_ASSERT_ARITHMETIC(dtype);
1937 
1938  NdArray<bool> returnArray(inArray.shape());
1939 
1940  const auto function = [](dtype value) -> dtype
1941  {
1942  return !value;
1943  };
1944 
1945  stl_algorithms::transform(inArray.cbegin(), inArray.cend(),
1946  returnArray.begin(), function);
1947 
1948  return returnArray;
1949  }
1950 
1951  //============================================================================
1952  // Method Description:
1960  template<typename dtype>
1962  {
1963  if (lhs.shape() != rhs.shape())
1964  {
1965  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1966  }
1967 
1968  const auto equalTo = [](dtype lhs, dtype rhs) noexcept -> bool
1969  {
1970  return utils::essentiallyEqual(lhs, rhs);
1971  };
1972 
1973  NdArray<bool> returnArray(lhs.shape());
1974 
1975  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
1976  rhs.cbegin(), returnArray.begin(), equalTo);
1977 
1978  return returnArray;
1979  }
1980 
1981  //============================================================================
1982  // Method Description:
1990  template<typename dtype>
1991  NdArray<bool> operator==(const NdArray<dtype>& lhs, dtype inValue)
1992  {
1993  NdArray<bool> returnArray(lhs.shape());
1994 
1995  const auto equalTo = [inValue](dtype value) noexcept -> bool
1996  {
1997  return utils::essentiallyEqual(inValue, value);
1998  };
1999 
2000  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
2001  returnArray.begin(), equalTo);
2002 
2003  return returnArray;
2004  }
2005 
2006  //============================================================================
2007  // Method Description:
2015  template<typename dtype>
2016  NdArray<bool> operator==(dtype inValue, const NdArray<dtype>& inArray)
2017  {
2018  return inArray == inValue;
2019  }
2020 
2021  //============================================================================
2022  // Method Description:
2030  template<typename dtype>
2032  {
2033  if (lhs.shape() != rhs.shape())
2034  {
2035  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
2036  }
2037 
2038  const auto notEqualTo = [](dtype lhs, dtype rhs) noexcept -> bool
2039  {
2040  return !utils::essentiallyEqual(lhs, rhs);
2041  };
2042 
2043  NdArray<bool> returnArray(lhs.shape());
2044 
2045  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
2046  rhs.cbegin(), returnArray.begin(), notEqualTo);
2047 
2048  return returnArray;
2049  }
2050 
2051  //============================================================================
2052  // Method Description:
2060  template<typename dtype>
2061  NdArray<bool> operator!=(const NdArray<dtype>& lhs, dtype inValue)
2062  {
2063  NdArray<bool> returnArray(lhs.shape());
2064 
2065  const auto notEqualTo = [inValue](dtype value) noexcept -> bool
2066  {
2067  return !utils::essentiallyEqual(inValue, value);
2068  };
2069 
2070  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
2071  returnArray.begin(), notEqualTo);
2072 
2073  return returnArray;
2074  }
2075 
2076  //============================================================================
2077  // Method Description:
2085  template<typename dtype>
2086  NdArray<bool> operator!=(dtype inValue, const NdArray<dtype>& inArray)
2087  {
2088  return inArray != inValue;
2089  }
2090 
2091  //============================================================================
2092  // Method Description:
2100  template<typename dtype>
2101  NdArray<bool> operator<(const NdArray<dtype>& lhs, const NdArray<dtype>& rhs)
2102  {
2104 
2105  if (lhs.shape() != rhs.shape())
2106  {
2107  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
2108  }
2109 
2110  NdArray<bool> returnArray(lhs.shape());
2111 
2112  const auto function = [](dtype lhs, dtype rhs) noexcept -> bool
2113  {
2114  return lhs < rhs;
2115  };
2116 
2117  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
2118  rhs.cbegin(), returnArray.begin(), function);
2119 
2120  return returnArray;
2121  }
2122 
2123  //============================================================================
2124  // Method Description:
2132  template<typename dtype>
2133  NdArray<bool> operator<(const NdArray<dtype>& lhs, dtype inValue)
2134  {
2136 
2137  NdArray<bool> returnArray(lhs.shape());
2138 
2139  const auto function = [inValue](dtype value) noexcept -> bool
2140  {
2141  return value < inValue;
2142  };
2143 
2144  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
2145  returnArray.begin(), function);
2146 
2147  return returnArray;
2148  }
2149 
2150  //============================================================================
2151  // Method Description:
2159  template<typename dtype>
2160  NdArray<bool> operator<(dtype inValue, const NdArray<dtype>& inArray)
2161  {
2163 
2164  NdArray<bool> returnArray(inArray.shape());
2165 
2166  const auto function = [inValue](dtype value) noexcept -> bool
2167  {
2168  return inValue < value;
2169  };
2170 
2171  stl_algorithms::transform(inArray.cbegin(), inArray.cend(),
2172  returnArray.begin(), function);
2173 
2174  return returnArray;
2175  }
2176 
2177  //============================================================================
2178  // Method Description:
2186  template<typename dtype>
2188  {
2190 
2191  if (lhs.shape() != rhs.shape())
2192  {
2193  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
2194  }
2195 
2196  NdArray<bool> returnArray(lhs.shape());
2197 
2198  const auto function = [](dtype lhs, dtype rhs) noexcept -> bool
2199  {
2200  return lhs > rhs;
2201  };
2202 
2203  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
2204  rhs.cbegin(), returnArray.begin(), function);
2205 
2206  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
2207  rhs.cbegin(), returnArray.begin(), function);
2208 
2209  return returnArray;
2210  }
2211 
2212  //============================================================================
2213  // Method Description:
2221  template<typename dtype>
2222  NdArray<bool> operator>(const NdArray<dtype>& lhs, dtype inValue)
2223  {
2225 
2226  NdArray<bool> returnArray(lhs.shape());
2227 
2228  const auto function = [inValue](dtype value) noexcept -> bool
2229  {
2230  return value > inValue;
2231  };
2232 
2233  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
2234  returnArray.begin(), function);
2235 
2236  return returnArray;
2237  }
2238 
2239  //============================================================================
2240  // Method Description:
2248  template<typename dtype>
2249  NdArray<bool> operator>(dtype inValue, const NdArray<dtype>& inArray)
2250  {
2252 
2253  NdArray<bool> returnArray(inArray.shape());
2254 
2255  const auto function = [inValue](dtype value) noexcept -> bool
2256  {
2257  return inValue > value;
2258  };
2259 
2260  stl_algorithms::transform(inArray.cbegin(), inArray.cend(),
2261  returnArray.begin(), function);
2262 
2263  return returnArray;
2264  }
2265 
2266  //============================================================================
2267  // Method Description:
2275  template<typename dtype>
2276  NdArray<bool> operator<=(const NdArray<dtype>& lhs, const NdArray<dtype>& rhs)
2277  {
2279 
2280  if (lhs.shape() != rhs.shape())
2281  {
2282  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
2283  }
2284 
2285  NdArray<bool> returnArray(lhs.shape());
2286 
2287  const auto function = [](dtype lhs, dtype rhs) noexcept -> bool
2288  {
2289  return lhs <= rhs;
2290  };
2291 
2292  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
2293  rhs.cbegin(), returnArray.begin(), function);
2294 
2295  return returnArray;
2296  }
2297 
2298  //============================================================================
2299  // Method Description:
2307  template<typename dtype>
2308  NdArray<bool> operator<=(const NdArray<dtype>& lhs, dtype inValue)
2309  {
2311 
2312  NdArray<bool> returnArray(lhs.shape());
2313 
2314  const auto function = [inValue](dtype value) noexcept -> bool
2315  {
2316  return value <= inValue;
2317  };
2318 
2319  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
2320  returnArray.begin(), function);
2321 
2322  return returnArray;
2323  }
2324 
2325  //============================================================================
2326  // Method Description:
2334  template<typename dtype>
2335  NdArray<bool> operator<=(dtype inValue, const NdArray<dtype>& inArray)
2336  {
2338 
2339  NdArray<bool> returnArray(inArray.shape());
2340 
2341  const auto function = [inValue](dtype value) noexcept -> bool
2342  {
2343  return inValue <= value;
2344  };
2345 
2346  stl_algorithms::transform(inArray.cbegin(), inArray.cend(),
2347  returnArray.begin(), function);
2348 
2349  return returnArray;
2350  }
2351 
2352  //============================================================================
2353  // Method Description:
2361  template<typename dtype>
2363  {
2365 
2366  if (lhs.shape() != rhs.shape())
2367  {
2368  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
2369  }
2370 
2371  NdArray<bool> returnArray(lhs.shape());
2372 
2373  const auto function = [](dtype lhs, dtype rhs) noexcept -> bool
2374  {
2375  return lhs >= rhs;
2376  };
2377 
2378  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
2379  rhs.cbegin(), returnArray.begin(), function);
2380 
2381  return returnArray;
2382  }
2383 
2384  //============================================================================
2385  // Method Description:
2393  template<typename dtype>
2394  NdArray<bool> operator>=(const NdArray<dtype>& lhs, dtype inValue)
2395  {
2397 
2398  NdArray<bool> returnArray(lhs.shape());
2399 
2400  const auto function = [inValue](dtype value) noexcept -> bool
2401  {
2402  return value >= inValue;
2403  };
2404 
2405  stl_algorithms::transform(lhs.cbegin(), lhs.cend(),
2406  returnArray.begin(), function);
2407 
2408  return returnArray;
2409  }
2410 
2411  //============================================================================
2412  // Method Description:
2420  template<typename dtype>
2421  NdArray<bool> operator>=(dtype inValue, const NdArray<dtype>& inArray)
2422  {
2424 
2425  NdArray<bool> returnArray(inArray.shape());
2426 
2427  const auto function = [inValue](dtype value) noexcept -> bool
2428  {
2429  return inValue >= value;
2430  };
2431 
2432  stl_algorithms::transform(inArray.cbegin(), inArray.cend(),
2433  returnArray.begin(), function);
2434 
2435  return returnArray;
2436  }
2437 
2438  //============================================================================
2439  // Method Description:
2446  template<typename dtype>
2447  NdArray<dtype>& operator<<=(NdArray<dtype>& lhs, uint8 inNumBits)
2448  {
2449  STATIC_ASSERT_INTEGER(dtype);
2450 
2451  const auto function = [inNumBits](dtype& value) -> void
2452  {
2453  value <<= inNumBits;
2454  };
2455 
2456  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
2457 
2458  return lhs;
2459  }
2460 
2461  //============================================================================
2462  // Method Description:
2469  template<typename dtype>
2470  NdArray<dtype> operator<<(const NdArray<dtype>& lhs, uint8 inNumBits)
2471  {
2472  STATIC_ASSERT_INTEGER(dtype);
2473 
2474  NdArray<dtype> returnArray(lhs);
2475  returnArray <<= inNumBits;
2476  return returnArray;
2477  }
2478 
2479  //============================================================================
2480  // Method Description:
2487  template<typename dtype>
2489  {
2490  STATIC_ASSERT_INTEGER(dtype);
2491 
2492  const auto function = [inNumBits](dtype& value) -> void
2493  {
2494  value >>= inNumBits;
2495  };
2496 
2497  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
2498 
2499  return lhs;
2500  }
2501 
2502  //============================================================================
2503  // Method Description:
2510  template<typename dtype>
2512  {
2513  STATIC_ASSERT_INTEGER(dtype);
2514 
2515  NdArray<dtype> returnArray(lhs);
2516  returnArray >>= inNumBits;
2517  return returnArray;
2518  }
2519 
2520  //============================================================================
2521  // Method Description:
2526  template<typename dtype>
2528  {
2529  STATIC_ASSERT_ARITHMETIC(dtype);
2530 
2531  const auto function = [](dtype& value) -> void
2532  {
2533  ++value;
2534  };
2535 
2536  stl_algorithms::for_each(rhs.begin(), rhs.end(), function);
2537 
2538  return rhs;
2539  }
2540 
2541  //============================================================================
2542  // Method Description:
2548  template<typename dtype>
2550  {
2551  auto copy = NdArray<dtype>(lhs);
2552  ++lhs;
2553  return copy;
2554  }
2555 
2556  //============================================================================
2557  // Method Description:
2562  template<typename dtype>
2564  {
2565  STATIC_ASSERT_ARITHMETIC(dtype);
2566 
2567  const auto function = [](dtype& value) -> void
2568  {
2569  --value;
2570  };
2571 
2572  stl_algorithms::for_each(rhs.begin(), rhs.end(), function);
2573 
2574  return rhs;
2575  }
2576 
2577  //============================================================================
2578  // Method Description:
2584  template<typename dtype>
2586  {
2587  auto copy = NdArray<dtype>(lhs);
2588  --lhs;
2589  return copy;
2590  }
2591 
2592  //============================================================================
2593  // Method Description:
2600  template<typename dtype>
2601  std::ostream& operator<<(std::ostream& inOStream, const NdArray<dtype>& inArray)
2602  {
2604 
2605  inOStream << inArray.str();
2606  return inOStream;
2607  }
2608 } // namespace nc
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:36
#define STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype)
Definition: StaticAsserts.hpp:50
#define STATIC_ASSERT_INTEGER(dtype)
Definition: StaticAsserts.hpp:40
#define STATIC_ASSERT_ARITHMETIC(dtype)
Definition: StaticAsserts.hpp:37
Holds 1D and 2D arrays, the main work horse of the NumCpp library.
Definition: NdArrayCore.hpp:72
const_iterator cbegin() const noexcept
Definition: NdArrayCore.hpp:1216
iterator end() noexcept
Definition: NdArrayCore.hpp:1474
Shape shape() const noexcept
Definition: NdArrayCore.hpp:4283
const_iterator cend() const noexcept
Definition: NdArrayCore.hpp:1524
std::string str() const
Definition: NdArrayCore.hpp:4356
iterator begin() noexcept
Definition: NdArrayCore.hpp:1166
OutputIt transform(InputIt first, InputIt last, OutputIt destination, UnaryOperation unaryFunction)
Definition: StlAlgorithms.hpp:702
void for_each(InputIt first, InputIt last, UnaryFunction f)
Definition: StlAlgorithms.hpp:213
bool essentiallyEqual(dtype inValue1, dtype inValue2) noexcept
Definition: essentiallyEqual.hpp:52
Definition: Coordinate.hpp:45
NdArray< dtype > operator&(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1631
NdArray< dtype > & operator%=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1323
bool operator>=(const std::complex< T > &lhs, const std::complex< T > &rhs) noexcept
Definition: StdComplexOperators.hpp:97
bool operator>(const std::complex< T > &lhs, const std::complex< T > &rhs) noexcept
Definition: StdComplexOperators.hpp:83
NdArray< bool > operator||(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1865
NdArray< bool > operator==(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1961
NdArray< dtype > operator|(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1538
NdArray< bool > operator!=(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:2031
NdArray< dtype > operator<<(const NdArray< dtype > &lhs, uint8 inNumBits)
Definition: NdArrayOperators.hpp:2470
NdArray< dtype > & operator+=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:55
NdArray< dtype > operator%(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1415
NdArrayConstIterator< dtype, PointerType, DifferenceType > operator+(typename NdArrayConstIterator< dtype, PointerType, DifferenceType >::difference_type offset, NdArrayConstIterator< dtype, PointerType, DifferenceType > next) noexcept
Definition: NdArrayIterators.hpp:310
NdArray< bool > operator!(const NdArray< dtype > &inArray)
Definition: NdArrayOperators.hpp:1934
dtype fmod(dtype inValue1, dtype inValue2) noexcept
Definition: fmod.hpp:53
bool operator<(const std::complex< T > &lhs, const std::complex< T > &rhs) noexcept
Definition: StdComplexOperators.hpp:45
NdArray< dtype > & operator>>=(NdArray< dtype > &lhs, uint8 inNumBits)
Definition: NdArrayOperators.hpp:2488
NdArray< dtype > operator>>(const NdArray< dtype > &lhs, uint8 inNumBits)
Definition: NdArrayOperators.hpp:2511
NdArray< dtype > & operator-=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:342
NdArray< dtype > & operator^=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1677
NdArray< dtype > operator*(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:797
NdArray< dtype > & operator|=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1491
std::uint8_t uint8
Definition: Types.hpp:42
NdArray< dtype > copy(const NdArray< dtype > &inArray)
Definition: copy.hpp:44
NdArray< dtype > & operator<<=(NdArray< dtype > &lhs, uint8 inNumBits)
Definition: NdArrayOperators.hpp:2447
bool operator<=(const std::complex< T > &lhs, const std::complex< T > &rhs) noexcept
Definition: StdComplexOperators.hpp:64
NdArray< dtype > & operator--(NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:2563
NdArray< bool > operator&&(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1795
NdArray< dtype > operator-(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:441
NdArray< dtype > & operator++(NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:2527
NdArray< dtype > operator/(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1084
NdArray< dtype > & operator/=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:985
NdArray< dtype > operator^(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1724
NdArray< dtype > operator~(const NdArray< dtype > &inArray)
Definition: NdArrayOperators.hpp:1769
NdArray< dtype > & operator&=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1584
NdArray< dtype > & operator*=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:698