NumCpp  2.9.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 
30 #include <algorithm>
31 #include <cmath>
32 #include <complex>
33 #include <functional>
34 
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(), rhs.cbegin(), lhs.begin(), std::plus<dtype>());
65 
66  return lhs;
67  }
68 
69  //============================================================================
70  // Method Description:
77  template<typename dtype>
78  NdArray<std::complex<dtype>>& operator+=(NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
79  {
81 
82  if (lhs.shape() != rhs.shape())
83  {
84  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
85  }
86 
87  const auto function = [](std::complex<dtype>& val1, dtype val2) -> std::complex<dtype> { return val1 + val2; };
88 
89  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), function);
90 
91  return lhs;
92  }
93 
94  //============================================================================
95  // Method Description:
102  template<typename dtype>
104  {
106 
107  const auto function = [rhs](dtype& value) -> dtype { return value += rhs; };
108 
109  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
110 
111  return lhs;
112  }
113 
114  //============================================================================
115  // Method Description:
122  template<typename dtype>
123  NdArray<std::complex<dtype>>& operator+=(NdArray<std::complex<dtype>>& lhs, dtype rhs)
124  {
126 
127  const auto function = [rhs](std::complex<dtype>& value) -> std::complex<dtype> { return value += rhs; };
128 
129  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
130 
131  return lhs;
132  }
133 
134  //============================================================================
135  // Method Description:
142  template<typename dtype>
144  {
146 
147  if (lhs.shape() != rhs.shape())
148  {
149  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
150  }
151 
152  NdArray<dtype> returnArray(lhs.shape());
153 
154  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), std::plus<dtype>());
155 
156  return returnArray;
157  }
158 
159  //============================================================================
160  // Method Description:
167  template<typename dtype>
168  NdArray<std::complex<dtype>> operator+(const NdArray<dtype>& lhs, const NdArray<std::complex<dtype>>& rhs)
169  {
171 
172  if (lhs.shape() != rhs.shape())
173  {
174  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
175  }
176 
177  const auto function = [](dtype val1, const std::complex<dtype>& val2) -> std::complex<dtype>
178  { return val1 + val2; };
179 
180  NdArray<std::complex<dtype>> returnArray(lhs.shape());
181 
182  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function);
183 
184  return returnArray;
185  }
186 
187  //============================================================================
188  // Method Description:
195  template<typename dtype>
196  NdArray<std::complex<dtype>> operator+(const NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
197  {
198  return rhs + lhs;
199  }
200 
201  //============================================================================
202  // Method Description:
209  template<typename dtype>
210  NdArray<dtype> operator+(const NdArray<dtype>& lhs, dtype rhs)
211  {
213 
214  const auto function = [rhs](dtype value) -> dtype { return value + rhs; };
215 
216  NdArray<dtype> returnArray(lhs.shape());
217 
218  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
219 
220  return returnArray;
221  }
222 
223  //============================================================================
224  // Method Description:
231  template<typename dtype>
232  NdArray<dtype> operator+(dtype lhs, const NdArray<dtype>& rhs)
233  {
234  return rhs + lhs;
235  }
236 
237  //============================================================================
238  // Method Description:
245  template<typename dtype>
246  NdArray<std::complex<dtype>> operator+(const NdArray<dtype>& lhs, const std::complex<dtype>& rhs)
247  {
249 
250  const auto function = [rhs](dtype value) -> std::complex<dtype> { return value + rhs; };
251 
252  NdArray<std::complex<dtype>> returnArray(lhs.shape());
253 
254  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
255 
256  return returnArray;
257  }
258 
259  //============================================================================
260  // Method Description:
267  template<typename dtype>
268  NdArray<std::complex<dtype>> operator+(const std::complex<dtype>& lhs, const NdArray<dtype>& rhs)
269  {
270  return rhs + lhs;
271  }
272 
273  //============================================================================
274  // Method Description:
281  template<typename dtype>
282  NdArray<std::complex<dtype>> operator+(const NdArray<std::complex<dtype>>& lhs, dtype rhs)
283  {
285 
286  const auto function = [rhs](std::complex<dtype> value) -> std::complex<dtype> { return value + rhs; };
287 
288  NdArray<std::complex<dtype>> returnArray(lhs.shape());
289 
290  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
291 
292  return returnArray;
293  }
294 
295  //============================================================================
296  // Method Description:
303  template<typename dtype>
304  NdArray<std::complex<dtype>> operator+(dtype lhs, const NdArray<std::complex<dtype>>& rhs)
305  {
306  return rhs + lhs;
307  }
308 
309  //============================================================================
310  // Method Description:
317  template<typename dtype>
319  {
321 
322  if (lhs.shape() != rhs.shape())
323  {
324  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
325  }
326 
327  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::minus<dtype>());
328 
329  return lhs;
330  }
331 
332  //============================================================================
333  // Method Description:
340  template<typename dtype>
341  NdArray<std::complex<dtype>>& operator-=(NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
342  {
344 
345  if (lhs.shape() != rhs.shape())
346  {
347  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
348  }
349 
350  const auto function = [](std::complex<dtype>& val1, dtype val2) -> std::complex<dtype> { return val1 - val2; };
351 
352  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), function);
353 
354  return lhs;
355  }
356 
357  //============================================================================
358  // Method Description:
365  template<typename dtype>
367  {
369 
370  const auto function = [rhs](dtype& value) -> dtype { return value -= rhs; };
371 
372  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
373 
374  return lhs;
375  }
376 
377  //============================================================================
378  // Method Description:
385  template<typename dtype>
386  NdArray<std::complex<dtype>>& operator-=(NdArray<std::complex<dtype>>& lhs, dtype rhs)
387  {
389 
390  const auto function = [rhs](std::complex<dtype>& value) -> std::complex<dtype> { return value -= rhs; };
391 
392  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
393 
394  return lhs;
395  }
396 
397  //============================================================================
398  // Method Description:
405  template<typename dtype>
407  {
409 
410  if (lhs.shape() != rhs.shape())
411  {
412  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
413  }
414 
415  NdArray<dtype> returnArray(lhs.shape());
416 
417  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), std::minus<dtype>());
418 
419  return returnArray;
420  }
421 
422  //============================================================================
423  // Method Description:
430  template<typename dtype>
431  NdArray<std::complex<dtype>> operator-(const NdArray<dtype>& lhs, const NdArray<std::complex<dtype>>& rhs)
432  {
434 
435  if (lhs.shape() != rhs.shape())
436  {
437  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
438  }
439 
440  const auto function = [](dtype val1, const std::complex<dtype>& val2) -> std::complex<dtype>
441  { return val1 - val2; };
442 
443  NdArray<std::complex<dtype>> returnArray(lhs.shape());
444 
445  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function);
446 
447  return returnArray;
448  }
449 
450  //============================================================================
451  // Method Description:
458  template<typename dtype>
459  NdArray<std::complex<dtype>> operator-(const NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
460  {
462 
463  if (lhs.shape() != rhs.shape())
464  {
465  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
466  }
467 
468  const auto function = [](const std::complex<dtype>& val1, dtype val2) -> std::complex<dtype>
469  { return val1 - val2; };
470 
471  NdArray<std::complex<dtype>> returnArray(lhs.shape());
472 
473  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function);
474 
475  return returnArray;
476  }
477 
478  //============================================================================
479  // Method Description:
486  template<typename dtype>
487  NdArray<dtype> operator-(const NdArray<dtype>& lhs, dtype rhs)
488  {
490 
491  const auto function = [rhs](dtype value) -> dtype { return value - rhs; };
492 
493  NdArray<dtype> returnArray(lhs.shape());
494 
495  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
496 
497  return returnArray;
498  }
499 
500  //============================================================================
501  // Method Description:
508  template<typename dtype>
509  NdArray<dtype> operator-(dtype lhs, const NdArray<dtype>& rhs)
510  {
512 
513  const auto function = [lhs](dtype value) -> dtype { return lhs - value; };
514 
515  NdArray<dtype> returnArray(rhs.shape());
516 
517  stl_algorithms::transform(rhs.cbegin(), rhs.cend(), returnArray.begin(), function);
518 
519  return returnArray;
520  }
521 
522  //============================================================================
523  // Method Description:
530  template<typename dtype>
531  NdArray<std::complex<dtype>> operator-(const NdArray<dtype>& lhs, const std::complex<dtype>& rhs)
532  {
534 
535  const auto function = [rhs](dtype value) -> std::complex<dtype> { return value - rhs; };
536 
537  NdArray<std::complex<dtype>> returnArray(lhs.shape());
538 
539  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
540 
541  return returnArray;
542  }
543 
544  //============================================================================
545  // Method Description:
552  template<typename dtype>
553  NdArray<std::complex<dtype>> operator-(const std::complex<dtype>& lhs, const NdArray<dtype>& rhs)
554  {
556 
557  const auto function = [lhs](dtype value) -> std::complex<dtype> { return lhs - value; };
558 
559  NdArray<std::complex<dtype>> returnArray(rhs.shape());
560 
561  stl_algorithms::transform(rhs.cbegin(), rhs.cend(), returnArray.begin(), function);
562 
563  return returnArray;
564  }
565 
566  //============================================================================
567  // Method Description:
574  template<typename dtype>
575  NdArray<std::complex<dtype>> operator-(const NdArray<std::complex<dtype>>& lhs, dtype rhs)
576  {
578 
579  const auto function = [rhs](std::complex<dtype> value) -> std::complex<dtype> { return value - rhs; };
580 
581  NdArray<std::complex<dtype>> returnArray(lhs.shape());
582 
583  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
584 
585  return returnArray;
586  }
587 
588  //============================================================================
589  // Method Description:
596  template<typename dtype>
597  NdArray<std::complex<dtype>> operator-(dtype lhs, const NdArray<std::complex<dtype>>& rhs)
598  {
600 
601  const auto function = [lhs](std::complex<dtype> value) -> std::complex<dtype> { return lhs - value; };
602 
603  NdArray<std::complex<dtype>> returnArray(rhs.shape());
604 
605  stl_algorithms::transform(rhs.cbegin(), rhs.cend(), returnArray.begin(), function);
606 
607  return returnArray;
608  }
609 
610  //============================================================================
611  // Method Description:
616  template<typename dtype>
618  {
619  const auto function = [](dtype value) -> dtype { return -value; };
620 
621  auto returnArray = NdArray<dtype>(inArray.shape());
622  stl_algorithms::transform(inArray.cbegin(), inArray.cend(), returnArray.begin(), function);
623  return returnArray;
624  }
625 
626  //============================================================================
627  // Method Description:
634  template<typename dtype>
636  {
638 
639  if (lhs.shape() != rhs.shape())
640  {
641  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
642  }
643 
644  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::multiplies<dtype>());
645 
646  return lhs;
647  }
648 
649  //============================================================================
650  // Method Description:
657  template<typename dtype>
658  NdArray<std::complex<dtype>>& operator*=(NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
659  {
661 
662  if (lhs.shape() != rhs.shape())
663  {
664  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
665  }
666 
667  const auto function = [](std::complex<dtype>& val1, dtype val2) -> std::complex<dtype> { return val1 * val2; };
668 
669  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), function);
670 
671  return lhs;
672  }
673 
674  //============================================================================
675  // Method Description:
682  template<typename dtype>
684  {
686 
687  const auto function = [rhs](dtype& value) -> dtype { return value *= rhs; };
688 
689  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
690 
691  return lhs;
692  }
693 
694  //============================================================================
695  // Method Description:
702  template<typename dtype>
703  NdArray<std::complex<dtype>>& operator*=(NdArray<std::complex<dtype>>& lhs, dtype rhs)
704  {
706 
707  const auto function = [rhs](std::complex<dtype>& value) -> std::complex<dtype> { return value *= rhs; };
708 
709  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
710 
711  return lhs;
712  }
713 
714  //============================================================================
715  // Method Description:
722  template<typename dtype>
724  {
726 
727  if (lhs.shape() != rhs.shape())
728  {
729  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
730  }
731 
732  NdArray<dtype> returnArray(lhs.shape());
733 
735  lhs.cend(),
736  rhs.cbegin(),
737  returnArray.begin(),
738  std::multiplies<dtype>());
739 
740  return returnArray;
741  }
742 
743  //============================================================================
744  // Method Description:
751  template<typename dtype>
752  NdArray<std::complex<dtype>> operator*(const NdArray<dtype>& lhs, const NdArray<std::complex<dtype>>& rhs)
753  {
755 
756  if (lhs.shape() != rhs.shape())
757  {
758  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
759  }
760 
761  const auto function = [](dtype val1, const std::complex<dtype>& val2) -> std::complex<dtype>
762  { return val1 * val2; };
763 
764  NdArray<std::complex<dtype>> returnArray(lhs.shape());
765 
766  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function);
767 
768  return returnArray;
769  }
770 
771  //============================================================================
772  // Method Description:
779  template<typename dtype>
780  NdArray<std::complex<dtype>> operator*(const NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
781  {
782  return rhs * lhs;
783  }
784 
785  //============================================================================
786  // Method Description:
793  template<typename dtype>
794  NdArray<dtype> operator*(const NdArray<dtype>& lhs, dtype rhs)
795  {
797 
798  const auto function = [rhs](dtype value) -> dtype { return value * rhs; };
799 
800  NdArray<dtype> returnArray(lhs.shape());
801 
802  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
803 
804  return returnArray;
805  }
806 
807  //============================================================================
808  // Method Description:
815  template<typename dtype>
816  NdArray<dtype> operator*(dtype lhs, const NdArray<dtype>& rhs)
817  {
818  return rhs * lhs;
819  }
820 
821  //============================================================================
822  // Method Description:
829  template<typename dtype>
830  NdArray<std::complex<dtype>> operator*(const NdArray<dtype>& lhs, const std::complex<dtype>& rhs)
831  {
833 
834  const auto function = [rhs](dtype value) -> std::complex<dtype> { return value * rhs; };
835 
836  NdArray<std::complex<dtype>> returnArray(lhs.shape());
837 
838  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
839 
840  return returnArray;
841  }
842 
843  //============================================================================
844  // Method Description:
851  template<typename dtype>
852  NdArray<std::complex<dtype>> operator*(const std::complex<dtype>& lhs, const NdArray<dtype>& rhs)
853  {
854  return rhs * lhs;
855  }
856 
857  //============================================================================
858  // Method Description:
865  template<typename dtype>
866  NdArray<std::complex<dtype>> operator*(const NdArray<std::complex<dtype>>& lhs, dtype rhs)
867  {
869 
870  const auto function = [rhs](std::complex<dtype> value) -> std::complex<dtype> { return value * rhs; };
871 
872  NdArray<std::complex<dtype>> returnArray(lhs.shape());
873 
874  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
875 
876  return returnArray;
877  }
878 
879  //============================================================================
880  // Method Description:
887  template<typename dtype>
888  NdArray<std::complex<dtype>> operator*(dtype lhs, const NdArray<std::complex<dtype>>& rhs)
889  {
890  return rhs * lhs;
891  }
892 
893  //============================================================================
894  // Method Description:
901  template<typename dtype>
903  {
905 
906  if (lhs.shape() != rhs.shape())
907  {
908  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
909  }
910 
911  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::divides<dtype>());
912 
913  return lhs;
914  }
915 
916  //============================================================================
917  // Method Description:
924  template<typename dtype>
925  NdArray<std::complex<dtype>>& operator/=(NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
926  {
928 
929  if (lhs.shape() != rhs.shape())
930  {
931  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
932  }
933 
934  const auto function = [](std::complex<dtype>& val1, dtype val2) -> std::complex<dtype> { return val1 / val2; };
935 
936  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), function);
937 
938  return lhs;
939  }
940 
941  //============================================================================
942  // Method Description:
949  template<typename dtype>
951  {
953 
954  const auto function = [rhs](dtype& value) -> dtype { return value /= rhs; };
955 
956  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
957 
958  return lhs;
959  }
960 
961  //============================================================================
962  // Method Description:
969  template<typename dtype>
970  NdArray<std::complex<dtype>>& operator/=(NdArray<std::complex<dtype>>& lhs, dtype rhs)
971  {
973 
974  const auto function = [rhs](std::complex<dtype>& value) -> std::complex<dtype> { return value /= rhs; };
975 
976  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
977 
978  return lhs;
979  }
980 
981  //============================================================================
982  // Method Description:
989  template<typename dtype>
991  {
993 
994  if (lhs.shape() != rhs.shape())
995  {
996  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
997  }
998 
999  NdArray<dtype> returnArray(lhs.shape());
1000 
1001  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), std::divides<dtype>());
1002 
1003  return returnArray;
1004  }
1005 
1006  //============================================================================
1007  // Method Description:
1014  template<typename dtype>
1015  NdArray<std::complex<dtype>> operator/(const NdArray<dtype>& lhs, const NdArray<std::complex<dtype>>& rhs)
1016  {
1017  STATIC_ASSERT_ARITHMETIC(dtype);
1018 
1019  if (lhs.shape() != rhs.shape())
1020  {
1021  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1022  }
1023 
1024  NdArray<std::complex<dtype>> returnArray(lhs.shape());
1025 
1026  const auto function = [](dtype val1, const std::complex<dtype>& val2) -> std::complex<dtype>
1027  { return val1 / val2; };
1028 
1029  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function);
1030 
1031  return returnArray;
1032  }
1033 
1034  //============================================================================
1035  // Method Description:
1042  template<typename dtype>
1043  NdArray<std::complex<dtype>> operator/(const NdArray<std::complex<dtype>>& lhs, const NdArray<dtype>& rhs)
1044  {
1045  STATIC_ASSERT_ARITHMETIC(dtype);
1046 
1047  if (lhs.shape() != rhs.shape())
1048  {
1049  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1050  }
1051 
1052  const auto function = [](const std::complex<dtype>& val1, dtype val2) -> std::complex<dtype>
1053  { return val1 / val2; };
1054 
1055  NdArray<std::complex<dtype>> returnArray(lhs.shape());
1056 
1057  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function);
1058 
1059  return returnArray;
1060  }
1061 
1062  //============================================================================
1063  // Method Description:
1070  template<typename dtype>
1071  NdArray<dtype> operator/(const NdArray<dtype>& lhs, dtype rhs)
1072  {
1074 
1075  const auto function = [rhs](dtype value) -> dtype { return value / rhs; };
1076 
1077  NdArray<dtype> returnArray(lhs.shape());
1078 
1079  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
1080 
1081  return returnArray;
1082  }
1083 
1084  //============================================================================
1085  // Method Description:
1092  template<typename dtype>
1093  NdArray<dtype> operator/(dtype lhs, const NdArray<dtype>& rhs)
1094  {
1096 
1097  const auto function = [lhs](dtype value) -> dtype { return lhs / value; };
1098 
1099  NdArray<dtype> returnArray(rhs.shape());
1100 
1101  stl_algorithms::transform(rhs.cbegin(), rhs.cend(), returnArray.begin(), function);
1102 
1103  return returnArray;
1104  }
1105 
1106  //============================================================================
1107  // Method Description:
1114  template<typename dtype>
1115  NdArray<std::complex<dtype>> operator/(const NdArray<dtype>& lhs, const std::complex<dtype>& rhs)
1116  {
1117  STATIC_ASSERT_ARITHMETIC(dtype);
1118 
1119  const auto function = [rhs](dtype value) -> std::complex<dtype> { return value / rhs; };
1120 
1121  NdArray<std::complex<dtype>> returnArray(lhs.shape());
1122 
1123  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
1124 
1125  return returnArray;
1126  }
1127 
1128  //============================================================================
1129  // Method Description:
1136  template<typename dtype>
1137  NdArray<std::complex<dtype>> operator/(const std::complex<dtype>& lhs, const NdArray<dtype>& rhs)
1138  {
1139  STATIC_ASSERT_ARITHMETIC(dtype);
1140 
1141  const auto function = [lhs](dtype value) -> std::complex<dtype> { return lhs / value; };
1142 
1143  NdArray<std::complex<dtype>> returnArray(rhs.shape());
1144 
1145  stl_algorithms::transform(rhs.cbegin(), rhs.cend(), returnArray.begin(), function);
1146 
1147  return returnArray;
1148  }
1149 
1150  //============================================================================
1151  // Method Description:
1158  template<typename dtype>
1159  NdArray<std::complex<dtype>> operator/(const NdArray<std::complex<dtype>>& lhs, dtype rhs)
1160  {
1161  STATIC_ASSERT_ARITHMETIC(dtype);
1162 
1163  const auto function = [rhs](std::complex<dtype> value) -> std::complex<dtype> { return value / rhs; };
1164 
1165  NdArray<std::complex<dtype>> returnArray(lhs.shape());
1166 
1167  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
1168 
1169  return returnArray;
1170  }
1171 
1172  //============================================================================
1173  // Method Description:
1180  template<typename dtype>
1181  NdArray<std::complex<dtype>> operator/(dtype lhs, const NdArray<std::complex<dtype>>& rhs)
1182  {
1183  STATIC_ASSERT_ARITHMETIC(dtype);
1184 
1185  const auto function = [lhs](std::complex<dtype> value) -> std::complex<dtype> { return lhs / value; };
1186 
1187  NdArray<std::complex<dtype>> returnArray(rhs.shape());
1188 
1189  stl_algorithms::transform(rhs.cbegin(), rhs.cend(), returnArray.begin(), function);
1190 
1191  return returnArray;
1192  }
1193 
1194  //============================================================================
1195  // Method Description:
1202  template<typename dtype, enable_if_t<std::is_integral<dtype>::value, int> = 0>
1204  {
1205  if (lhs.shape() != rhs.shape())
1206  {
1207  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1208  }
1209 
1210  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::modulus<dtype>());
1211 
1212  return lhs;
1213  }
1214 
1215  //============================================================================
1216  // Method Description:
1223  template<typename dtype, enable_if_t<std::is_floating_point<dtype>::value, int> = 0>
1224  NdArray<dtype>& operator%=(NdArray<dtype>& lhs, const NdArray<dtype>& rhs)
1225  {
1226  if (lhs.shape() != rhs.shape())
1227  {
1228  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1229  }
1230 
1231  const auto function = [](const dtype value1, const dtype value2) -> dtype { return std::fmod(value1, value2); };
1232 
1233  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), function);
1234 
1235  return lhs;
1236  }
1237 
1238  //============================================================================
1239  // Method Description:
1246  template<typename dtype, enable_if_t<std::is_integral<dtype>::value, int> = 0>
1248  {
1249  const auto function = [rhs](dtype& value) -> dtype { return value %= rhs; };
1250 
1251  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
1252 
1253  return lhs;
1254  }
1255 
1256  //============================================================================
1257  // Method Description:
1264  template<typename dtype, enable_if_t<std::is_floating_point<dtype>::value, int> = 0>
1265  NdArray<dtype>& operator%=(NdArray<dtype>& lhs, dtype rhs)
1266  {
1267  const auto function = [rhs](dtype& value) -> void { value = std::fmod(value, rhs); };
1268 
1269  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
1270 
1271  return lhs;
1272  }
1273 
1274  //============================================================================
1275  // Method Description:
1282  template<typename dtype>
1284  {
1285  auto returnArray = NdArray<dtype>(lhs);
1286  returnArray %= rhs;
1287  return returnArray;
1288  }
1289 
1290  //============================================================================
1291  // Method Description:
1298  template<typename dtype>
1299  NdArray<dtype> operator%(const NdArray<dtype>& lhs, dtype rhs)
1300  {
1301  auto returnArray = NdArray<dtype>(lhs);
1302  returnArray %= rhs;
1303  return returnArray;
1304  }
1305 
1306  //============================================================================
1307  // Method Description:
1314  template<typename dtype, enable_if_t<std::is_integral<dtype>::value, int> = 0>
1315  NdArray<dtype> operator%(dtype lhs, const NdArray<dtype>& rhs)
1316  {
1317  NdArray<dtype> returnArray(rhs.shape());
1319  rhs.end(),
1320  returnArray.begin(),
1321  [lhs](dtype value) -> dtype { return lhs % value; });
1322 
1323  return returnArray;
1324  }
1325 
1326  //============================================================================
1327  // Method Description:
1334  template<typename dtype, enable_if_t<std::is_floating_point<dtype>::value, int> = 0>
1335  NdArray<dtype> operator%(dtype lhs, const NdArray<dtype>& rhs)
1336  {
1337  NdArray<dtype> returnArray(rhs.shape());
1338  stl_algorithms::transform(rhs.begin(),
1339  rhs.end(),
1340  returnArray.begin(),
1341  [lhs](dtype value) -> dtype { return std::fmod(lhs, value); });
1342 
1343  return returnArray;
1344  }
1345 
1346  //============================================================================
1347  // Method Description:
1354  template<typename dtype>
1356  {
1357  STATIC_ASSERT_INTEGER(dtype);
1358 
1359  if (lhs.shape() != rhs.shape())
1360  {
1361  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1362  }
1363 
1364  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::bit_or<dtype>());
1365 
1366  return lhs;
1367  }
1368 
1369  //============================================================================
1370  // Method Description:
1377  template<typename dtype>
1379  {
1380  STATIC_ASSERT_INTEGER(dtype);
1381 
1382  const auto function = [rhs](dtype& value) -> dtype { return value |= rhs; };
1383 
1384  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
1385 
1386  return lhs;
1387  }
1388 
1389  //============================================================================
1390  // Method Description:
1397  template<typename dtype>
1399  {
1400  auto returnArray = NdArray<dtype>(lhs);
1401  returnArray |= rhs;
1402  return returnArray;
1403  }
1404 
1405  //============================================================================
1406  // Method Description:
1413  template<typename dtype>
1414  NdArray<dtype> operator|(const NdArray<dtype>& lhs, dtype rhs)
1415  {
1416  auto returnArray = NdArray<dtype>(lhs);
1417  returnArray |= rhs;
1418  return returnArray;
1419  }
1420 
1421  //============================================================================
1422  // Method Description:
1429  template<typename dtype>
1430  NdArray<dtype> operator|(dtype lhs, const NdArray<dtype>& rhs)
1431  {
1432  return rhs | lhs;
1433  }
1434 
1435  //============================================================================
1436  // Method Description:
1443  template<typename dtype>
1445  {
1446  STATIC_ASSERT_INTEGER(dtype);
1447 
1448  if (lhs.shape() != rhs.shape())
1449  {
1450  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1451  }
1452 
1453  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::bit_and<dtype>());
1454 
1455  return lhs;
1456  }
1457 
1458  //============================================================================
1459  // Method Description:
1466  template<typename dtype>
1468  {
1469  STATIC_ASSERT_INTEGER(dtype);
1470 
1471  const auto function = [rhs](dtype& value) -> dtype { return value &= rhs; };
1472 
1473  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
1474 
1475  return lhs;
1476  }
1477 
1478  //============================================================================
1479  // Method Description:
1486  template<typename dtype>
1488  {
1489  auto returnArray = NdArray<dtype>(lhs);
1490  returnArray &= rhs;
1491  return returnArray;
1492  }
1493 
1494  //============================================================================
1495  // Method Description:
1502  template<typename dtype>
1503  NdArray<dtype> operator&(const NdArray<dtype>& lhs, dtype rhs)
1504  {
1505  auto returnArray = NdArray<dtype>(lhs);
1506  returnArray &= rhs;
1507  return returnArray;
1508  }
1509 
1510  //============================================================================
1511  // Method Description:
1518  template<typename dtype>
1519  NdArray<dtype> operator&(dtype lhs, const NdArray<dtype>& rhs)
1520  {
1521  return rhs & lhs;
1522  }
1523 
1524  //============================================================================
1525  // Method Description:
1532  template<typename dtype>
1534  {
1535  STATIC_ASSERT_INTEGER(dtype);
1536 
1537  if (lhs.shape() != rhs.shape())
1538  {
1539  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1540  }
1541 
1542  stl_algorithms::transform(lhs.begin(), lhs.end(), rhs.cbegin(), lhs.begin(), std::bit_xor<dtype>());
1543 
1544  return lhs;
1545  }
1546 
1547  //============================================================================
1548  // Method Description:
1555  template<typename dtype>
1557  {
1558  STATIC_ASSERT_INTEGER(dtype);
1559 
1560  const auto function = [rhs](dtype& value) -> dtype { return value ^= rhs; };
1561 
1562  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
1563 
1564  return lhs;
1565  }
1566 
1567  //============================================================================
1568  // Method Description:
1575  template<typename dtype>
1577  {
1578  auto returnArray = NdArray<dtype>(lhs);
1579  returnArray ^= rhs;
1580  return returnArray;
1581  }
1582 
1583  //============================================================================
1584  // Method Description:
1591  template<typename dtype>
1592  NdArray<dtype> operator^(const NdArray<dtype>& lhs, dtype rhs)
1593  {
1594  auto returnArray = NdArray<dtype>(lhs);
1595  returnArray ^= rhs;
1596  return returnArray;
1597  }
1598 
1599  //============================================================================
1600  // Method Description:
1607  template<typename dtype>
1608  NdArray<dtype> operator^(dtype lhs, const NdArray<dtype>& rhs)
1609  {
1610  return rhs ^ lhs;
1611  }
1612 
1613  //============================================================================
1614  // Method Description:
1620  template<typename dtype>
1622  {
1623  STATIC_ASSERT_INTEGER(dtype);
1624 
1625  const auto function = [](dtype value) -> dtype { return ~value; };
1626 
1627  NdArray<dtype> returnArray(inArray.shape());
1628 
1629  stl_algorithms::transform(inArray.cbegin(), inArray.cend(), returnArray.begin(), function);
1630 
1631  return returnArray;
1632  }
1633 
1634  //============================================================================
1635  // Method Description:
1642  template<typename dtype>
1644  {
1645  STATIC_ASSERT_ARITHMETIC(dtype);
1646 
1647  if (lhs.shape() != rhs.shape())
1648  {
1649  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1650  }
1651 
1652  const auto function = [](dtype value1, dtype value2) -> bool { return value1 && value2; };
1653 
1654  NdArray<bool> returnArray(lhs.shape());
1655  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function);
1656 
1657  return returnArray;
1658  }
1659 
1660  //============================================================================
1661  // Method Description:
1668  template<typename dtype>
1669  NdArray<bool> operator&&(const NdArray<dtype>& lhs, dtype rhs)
1670  {
1671  STATIC_ASSERT_ARITHMETIC(dtype);
1672 
1673  NdArray<bool> returnArray(lhs.shape());
1674 
1675  const auto function = [rhs](dtype value) -> bool { return value && rhs; };
1676 
1677  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
1678 
1679  return returnArray;
1680  }
1681 
1682  //============================================================================
1683  // Method Description:
1690  template<typename dtype>
1691  NdArray<bool> operator&&(dtype lhs, const NdArray<dtype>& rhs)
1692  {
1693  return rhs && lhs;
1694  }
1695 
1696  //============================================================================
1697  // Method Description:
1704  template<typename dtype>
1706  {
1707  STATIC_ASSERT_ARITHMETIC(dtype);
1708 
1709  if (lhs.shape() != rhs.shape())
1710  {
1711  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1712  }
1713 
1714  const auto function = [](dtype value1, dtype value2) -> bool { return value1 || value2; };
1715 
1716  NdArray<bool> returnArray(lhs.shape());
1717  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function);
1718 
1719  return returnArray;
1720  }
1721 
1722  //============================================================================
1723  // Method Description:
1730  template<typename dtype>
1731  NdArray<bool> operator||(const NdArray<dtype>& lhs, dtype rhs)
1732  {
1733  STATIC_ASSERT_ARITHMETIC(dtype);
1734 
1735  NdArray<bool> returnArray(lhs.shape());
1736 
1737  const auto function = [rhs](dtype value) -> bool { return value || rhs; };
1738 
1739  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
1740 
1741  return returnArray;
1742  }
1743 
1744  //============================================================================
1745  // Method Description:
1752  template<typename dtype>
1753  NdArray<bool> operator||(dtype lhs, const NdArray<dtype>& rhs)
1754  {
1755  return rhs || lhs;
1756  }
1757 
1758  //============================================================================
1759  // Method Description:
1765  template<typename dtype>
1767  {
1768  STATIC_ASSERT_ARITHMETIC(dtype);
1769 
1770  NdArray<bool> returnArray(inArray.shape());
1771 
1772  const auto function = [](dtype value) -> dtype { return !value; };
1773 
1774  stl_algorithms::transform(inArray.cbegin(), inArray.cend(), returnArray.begin(), function);
1775 
1776  return returnArray;
1777  }
1778 
1779  //============================================================================
1780  // Method Description:
1788  template<typename dtype>
1790  {
1791  if (lhs.shape() != rhs.shape())
1792  {
1793  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1794  }
1795 
1796  const auto equalTo = [](dtype lhs, dtype rhs) noexcept -> bool { return utils::essentiallyEqual(lhs, rhs); };
1797 
1798  NdArray<bool> returnArray(lhs.shape());
1799 
1800  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), equalTo);
1801 
1802  return returnArray;
1803  }
1804 
1805  //============================================================================
1806  // Method Description:
1814  template<typename dtype>
1815  NdArray<bool> operator==(const NdArray<dtype>& lhs, dtype inValue)
1816  {
1817  NdArray<bool> returnArray(lhs.shape());
1818 
1819  const auto equalTo = [inValue](dtype value) noexcept -> bool
1820  { return utils::essentiallyEqual(inValue, value); };
1821 
1822  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), equalTo);
1823 
1824  return returnArray;
1825  }
1826 
1827  //============================================================================
1828  // Method Description:
1836  template<typename dtype>
1837  NdArray<bool> operator==(dtype inValue, const NdArray<dtype>& inArray)
1838  {
1839  return inArray == inValue;
1840  }
1841 
1842  //============================================================================
1843  // Method Description:
1851  template<typename dtype>
1853  {
1854  if (lhs.shape() != rhs.shape())
1855  {
1856  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1857  }
1858 
1859  const auto notEqualTo = [](dtype lhs, dtype rhs) noexcept -> bool
1860  { return !utils::essentiallyEqual(lhs, rhs); };
1861 
1862  NdArray<bool> returnArray(lhs.shape());
1863 
1864  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), notEqualTo);
1865 
1866  return returnArray;
1867  }
1868 
1869  //============================================================================
1870  // Method Description:
1878  template<typename dtype>
1879  NdArray<bool> operator!=(const NdArray<dtype>& lhs, dtype inValue)
1880  {
1881  NdArray<bool> returnArray(lhs.shape());
1882 
1883  const auto notEqualTo = [inValue](dtype value) noexcept -> bool
1884  { return !utils::essentiallyEqual(inValue, value); };
1885 
1886  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), notEqualTo);
1887 
1888  return returnArray;
1889  }
1890 
1891  //============================================================================
1892  // Method Description:
1900  template<typename dtype>
1901  NdArray<bool> operator!=(dtype inValue, const NdArray<dtype>& inArray)
1902  {
1903  return inArray != inValue;
1904  }
1905 
1906  //============================================================================
1907  // Method Description:
1915  template<typename dtype>
1916  NdArray<bool> operator<(const NdArray<dtype>& lhs, const NdArray<dtype>& rhs)
1917  {
1919 
1920  if (lhs.shape() != rhs.shape())
1921  {
1922  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1923  }
1924 
1925  NdArray<bool> returnArray(lhs.shape());
1926 
1927  const auto function = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs < rhs; };
1928 
1929  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function);
1930 
1931  return returnArray;
1932  }
1933 
1934  //============================================================================
1935  // Method Description:
1943  template<typename dtype>
1944  NdArray<bool> operator<(const NdArray<dtype>& lhs, dtype inValue)
1945  {
1947 
1948  NdArray<bool> returnArray(lhs.shape());
1949 
1950  const auto function = [inValue](dtype value) noexcept -> bool { return value < inValue; };
1951 
1952  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
1953 
1954  return returnArray;
1955  }
1956 
1957  //============================================================================
1958  // Method Description:
1966  template<typename dtype>
1967  NdArray<bool> operator<(dtype inValue, const NdArray<dtype>& inArray)
1968  {
1970 
1971  NdArray<bool> returnArray(inArray.shape());
1972 
1973  const auto function = [inValue](dtype value) noexcept -> bool { return inValue < value; };
1974 
1975  stl_algorithms::transform(inArray.cbegin(), inArray.cend(), returnArray.begin(), function);
1976 
1977  return returnArray;
1978  }
1979 
1980  //============================================================================
1981  // Method Description:
1989  template<typename dtype>
1991  {
1993 
1994  if (lhs.shape() != rhs.shape())
1995  {
1996  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
1997  }
1998 
1999  NdArray<bool> returnArray(lhs.shape());
2000 
2001  const auto function = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs > rhs; };
2002 
2003  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function);
2004 
2005  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function);
2006 
2007  return returnArray;
2008  }
2009 
2010  //============================================================================
2011  // Method Description:
2019  template<typename dtype>
2020  NdArray<bool> operator>(const NdArray<dtype>& lhs, dtype inValue)
2021  {
2023 
2024  NdArray<bool> returnArray(lhs.shape());
2025 
2026  const auto function = [inValue](dtype value) noexcept -> bool { return value > inValue; };
2027 
2028  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
2029 
2030  return returnArray;
2031  }
2032 
2033  //============================================================================
2034  // Method Description:
2042  template<typename dtype>
2043  NdArray<bool> operator>(dtype inValue, const NdArray<dtype>& inArray)
2044  {
2046 
2047  NdArray<bool> returnArray(inArray.shape());
2048 
2049  const auto function = [inValue](dtype value) noexcept -> bool { return inValue > value; };
2050 
2051  stl_algorithms::transform(inArray.cbegin(), inArray.cend(), returnArray.begin(), function);
2052 
2053  return returnArray;
2054  }
2055 
2056  //============================================================================
2057  // Method Description:
2065  template<typename dtype>
2066  NdArray<bool> operator<=(const NdArray<dtype>& lhs, const NdArray<dtype>& rhs)
2067  {
2069 
2070  if (lhs.shape() != rhs.shape())
2071  {
2072  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
2073  }
2074 
2075  NdArray<bool> returnArray(lhs.shape());
2076 
2077  const auto function = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs <= rhs; };
2078 
2079  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function);
2080 
2081  return returnArray;
2082  }
2083 
2084  //============================================================================
2085  // Method Description:
2093  template<typename dtype>
2094  NdArray<bool> operator<=(const NdArray<dtype>& lhs, dtype inValue)
2095  {
2097 
2098  NdArray<bool> returnArray(lhs.shape());
2099 
2100  const auto function = [inValue](dtype value) noexcept -> bool { return value <= inValue; };
2101 
2102  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
2103 
2104  return returnArray;
2105  }
2106 
2107  //============================================================================
2108  // Method Description:
2116  template<typename dtype>
2117  NdArray<bool> operator<=(dtype inValue, const NdArray<dtype>& inArray)
2118  {
2120 
2121  NdArray<bool> returnArray(inArray.shape());
2122 
2123  const auto function = [inValue](dtype value) noexcept -> bool { return inValue <= value; };
2124 
2125  stl_algorithms::transform(inArray.cbegin(), inArray.cend(), returnArray.begin(), function);
2126 
2127  return returnArray;
2128  }
2129 
2130  //============================================================================
2131  // Method Description:
2139  template<typename dtype>
2141  {
2143 
2144  if (lhs.shape() != rhs.shape())
2145  {
2146  THROW_INVALID_ARGUMENT_ERROR("Array dimensions do not match.");
2147  }
2148 
2149  NdArray<bool> returnArray(lhs.shape());
2150 
2151  const auto function = [](dtype lhs, dtype rhs) noexcept -> bool { return lhs >= rhs; };
2152 
2153  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), rhs.cbegin(), returnArray.begin(), function);
2154 
2155  return returnArray;
2156  }
2157 
2158  //============================================================================
2159  // Method Description:
2167  template<typename dtype>
2168  NdArray<bool> operator>=(const NdArray<dtype>& lhs, dtype inValue)
2169  {
2171 
2172  NdArray<bool> returnArray(lhs.shape());
2173 
2174  const auto function = [inValue](dtype value) noexcept -> bool { return value >= inValue; };
2175 
2176  stl_algorithms::transform(lhs.cbegin(), lhs.cend(), returnArray.begin(), function);
2177 
2178  return returnArray;
2179  }
2180 
2181  //============================================================================
2182  // Method Description:
2190  template<typename dtype>
2191  NdArray<bool> operator>=(dtype inValue, const NdArray<dtype>& inArray)
2192  {
2194 
2195  NdArray<bool> returnArray(inArray.shape());
2196 
2197  const auto function = [inValue](dtype value) noexcept -> bool { return inValue >= value; };
2198 
2199  stl_algorithms::transform(inArray.cbegin(), inArray.cend(), returnArray.begin(), function);
2200 
2201  return returnArray;
2202  }
2203 
2204  //============================================================================
2205  // Method Description:
2212  template<typename dtype>
2213  NdArray<dtype>& operator<<=(NdArray<dtype>& lhs, uint8 inNumBits)
2214  {
2215  STATIC_ASSERT_INTEGER(dtype);
2216 
2217  const auto function = [inNumBits](dtype& value) -> void { value <<= inNumBits; };
2218 
2219  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
2220 
2221  return lhs;
2222  }
2223 
2224  //============================================================================
2225  // Method Description:
2232  template<typename dtype>
2233  NdArray<dtype> operator<<(const NdArray<dtype>& lhs, uint8 inNumBits)
2234  {
2235  STATIC_ASSERT_INTEGER(dtype);
2236 
2237  NdArray<dtype> returnArray(lhs);
2238  returnArray <<= inNumBits;
2239  return returnArray;
2240  }
2241 
2242  //============================================================================
2243  // Method Description:
2250  template<typename dtype>
2252  {
2253  STATIC_ASSERT_INTEGER(dtype);
2254 
2255  const auto function = [inNumBits](dtype& value) -> void { value >>= inNumBits; };
2256 
2257  stl_algorithms::for_each(lhs.begin(), lhs.end(), function);
2258 
2259  return lhs;
2260  }
2261 
2262  //============================================================================
2263  // Method Description:
2270  template<typename dtype>
2272  {
2273  STATIC_ASSERT_INTEGER(dtype);
2274 
2275  NdArray<dtype> returnArray(lhs);
2276  returnArray >>= inNumBits;
2277  return returnArray;
2278  }
2279 
2280  //============================================================================
2281  // Method Description:
2286  template<typename dtype>
2288  {
2289  STATIC_ASSERT_ARITHMETIC(dtype);
2290 
2291  const auto function = [](dtype& value) -> void { ++value; };
2292 
2293  stl_algorithms::for_each(rhs.begin(), rhs.end(), function);
2294 
2295  return rhs;
2296  }
2297 
2298  //============================================================================
2299  // Method Description:
2305  template<typename dtype>
2307  {
2308  auto copy = NdArray<dtype>(lhs);
2309  ++lhs;
2310  return copy;
2311  }
2312 
2313  //============================================================================
2314  // Method Description:
2319  template<typename dtype>
2321  {
2322  STATIC_ASSERT_ARITHMETIC(dtype);
2323 
2324  const auto function = [](dtype& value) -> void { --value; };
2325 
2326  stl_algorithms::for_each(rhs.begin(), rhs.end(), function);
2327 
2328  return rhs;
2329  }
2330 
2331  //============================================================================
2332  // Method Description:
2338  template<typename dtype>
2340  {
2341  auto copy = NdArray<dtype>(lhs);
2342  --lhs;
2343  return copy;
2344  }
2345 
2346  //============================================================================
2347  // Method Description:
2354  template<typename dtype>
2355  std::ostream& operator<<(std::ostream& inOStream, const NdArray<dtype>& inArray)
2356  {
2358 
2359  inOStream << inArray.str();
2360  return inOStream;
2361  }
2362 } // namespace nc
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:36
#define STATIC_ASSERT_ARITHMETIC_OR_COMPLEX(dtype)
Definition: StaticAsserts.hpp:49
#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:1221
iterator end() noexcept
Definition: NdArrayCore.hpp:1479
Shape shape() const noexcept
Definition: NdArrayCore.hpp:4092
const_iterator cend() const noexcept
Definition: NdArrayCore.hpp:1529
std::string str() const
Definition: NdArrayCore.hpp:4162
iterator begin() noexcept
Definition: NdArrayCore.hpp:1171
OutputIt transform(InputIt first, InputIt last, OutputIt destination, UnaryOperation unaryFunction)
Definition: StlAlgorithms.hpp:784
void for_each(InputIt first, InputIt last, UnaryFunction f)
Definition: StlAlgorithms.hpp:227
bool essentiallyEqual(dtype inValue1, dtype inValue2) noexcept
Definition: essentiallyEqual.hpp:51
Definition: Coordinate.hpp:45
NdArray< dtype > operator&(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1487
bool operator==(const DateTime &lhs, const DateTime &rhs) noexcept
Equality operator for DateTime.
Definition: DateTime/DateTime.hpp:473
NdArray< dtype > & operator%=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1203
bool operator>=(const std::complex< T > &lhs, const std::complex< T > &rhs) noexcept
Definition: StdComplexOperators.hpp:97
Duration operator-(const DateTime &lhs, const DateTime &rhs) noexcept
Subtraction operator.
Definition: DateTime/DateTime.hpp:551
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:1705
NdArray< dtype > operator|(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1398
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:1283
NdArrayConstIterator< dtype, PointerType, DifferenceType > operator+(typename NdArrayConstIterator< dtype, PointerType, DifferenceType >::difference_type offset, NdArrayConstIterator< dtype, PointerType, DifferenceType > next) noexcept
Definition: NdArrayIterators.hpp:307
NdArray< bool > operator!(const NdArray< dtype > &inArray)
Definition: NdArrayOperators.hpp:1766
bool operator!=(const DateTime &lhs, const DateTime &rhs) noexcept
Non Equality operator for DateTime.
Definition: DateTime/DateTime.hpp:486
dtype fmod(dtype inValue1, dtype inValue2) noexcept
Definition: fmod.hpp:52
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:2251
NdArray< dtype > operator>>(const NdArray< dtype > &lhs, uint8 inNumBits)
Definition: NdArrayOperators.hpp:2271
NdArray< dtype > & operator-=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:318
NdArray< dtype > & operator^=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1533
NdArray< dtype > operator*(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:723
NdArray< dtype > & operator|=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1355
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:2213
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:2320
NdArray< bool > operator&&(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1643
NdArray< dtype > & operator++(NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:2287
std::ostream & operator<<(std::ostream &os, Duration duration)
Output stream operator for the Duration type.
Definition: Clock.hpp:30
NdArray< dtype > operator/(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:990
NdArray< dtype > & operator/=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:902
NdArray< dtype > operator^(const NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1576
NdArray< dtype > operator~(const NdArray< dtype > &inArray)
Definition: NdArrayOperators.hpp:1621
NdArray< dtype > & operator&=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:1444
NdArray< dtype > & operator*=(NdArray< dtype > &lhs, const NdArray< dtype > &rhs)
Definition: NdArrayOperators.hpp:635