Console Library 4.7.0
A header-only library that makes C++ simple
Loading...
Searching...
No Matches
multiarray.h
Go to the documentation of this file.
1
10
11/*
12Copyright (c) 2026 MrXie1109
13
14Permission is hereby granted, free of charge, to any person obtaining a copy
15of this software and associated documentation files (the "Software"), to deal
16in the Software without restriction, including without limitation the rights
17to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18copies of the Software, and to permit persons to whom the Software is
19furnished to do so, subject to the following conditions:
20
21The above copyright notice and this permission notice shall be included in all
22copies or substantial portions of the Software.
23
24THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30SOFTWARE.
31*/
32
33#pragma once
34#include <iostream>
35#include <array>
36#include <cstddef>
37#include <stdexcept>
38#include <type_traits>
39#include <initializer_list>
40#include <algorithm>
41#include <cstring>
42#include "csexc.h"
43#include "repr.h"
44
45namespace console
46{
56 template <class T, size_t... Dims>
58
64 template <class T, size_t D>
65 class MultiArray<T, D> : public std::array<T, D>
66 {
67 using base_type = std::array<T, D>;
68
69 public:
70 using value_type = T;
71 using reference = T &;
72 using const_reference = const T &;
73
75 MultiArray() = default;
76
81 explicit MultiArray(const T &value)
82 {
83 fill(value);
84 }
85
87 MultiArray(const base_type &other) : base_type(other) {}
88
93 MultiArray(std::initializer_list<T> init)
94 {
95 std::copy(init.begin(), init.end(), this->begin());
96 }
97
99 static constexpr size_t rank() { return 1; }
100
102 static constexpr size_t fsize() { return D; }
103
105 void fill(const T &value)
106 {
107 for (auto &item : *this)
108 item = value;
109 }
110
116 template <class F>
117 void for_each(F &&visit)
118 {
119 for (auto &item : *this)
120 visit(item);
121 }
122
128 template <class F>
129 void for_each(F &&visit) const
130 {
131 for (const auto &item : *this)
132 visit(item);
133 }
134
142 {
143 if (i >= D)
144 throw multiarray_error(
145 "index " +
146 std::to_string(i) +
147 " out of range [0, " +
148 std::to_string(D) +
149 ')');
150 return (*this)[i];
151 }
152
155 {
156 if (i >= D)
157 throw multiarray_error(
158 "index " +
159 std::to_string(i) +
160 " out of range [0, " +
161 std::to_string(D) +
162 ')');
163 return (*this)[i];
164 }
165
167 friend std::ostream &operator<<(std::ostream &os, const MultiArray &ma)
168 {
169 if (ma.begin() == ma.end())
170 return os << "[]";
171 auto it = ma.begin();
172 os << '[';
173 repr(*it, os);
174 while (++it != ma.end())
175 {
176 os << ", ";
177 repr(*it, os);
178 }
179 return os << ']';
180 }
181
183 T *fbegin() { return this->data(); }
184
186 const T *fbegin() const { return this->data(); }
187
189 T *fend() { return this->data() + fsize(); }
190
192 const T *fend() const { return this->data() + fsize(); }
193
199 {
200 return *this;
201 }
202
207 const MultiArray &flatten() const
208 {
209 return *this;
210 }
211
216 static constexpr std::array<size_t, 1> dims()
217 {
218 return {D};
219 }
220 };
221
228 template <class T, size_t First, size_t... Rest>
229 class MultiArray<T, First, Rest...>
230 : public std::array<MultiArray<T, Rest...>, First>
231 {
232 using base_type = std::array<MultiArray<T, Rest...>, First>;
233
234 public:
235 using value_type = T;
236 using reference = MultiArray<T, Rest...> &;
237 using const_reference = const MultiArray<T, Rest...> &;
238
240 MultiArray() = default;
241
246 explicit MultiArray(const T &value)
247 {
248 fill(value);
249 }
250
252 MultiArray(const base_type &other) : base_type(other) {}
253
258 MultiArray(std::initializer_list<MultiArray<T, Rest...>> init)
259 {
260 std::copy(init.begin(), init.end(), this->begin());
261 }
262
264 static constexpr size_t rank() { return 1 + sizeof...(Rest); }
265
267 static constexpr size_t fsize()
268 {
269 return First * MultiArray<T, Rest...>::fsize();
270 }
271
273 void fill(const T &value)
274 {
275 for (auto &sub : *this)
276 sub.fill(value);
277 }
278
283 template <class F>
284 void for_each(F &&visit)
285 {
286 for (auto &sub : *this)
287 sub.for_each(visit);
288 }
289
294 template <class F>
295 void for_each(F &&visit) const
296 {
297 for (const auto &sub : *this)
298 sub.for_each(visit);
299 }
300
308 {
309 if (idx >= First)
310 throw multiarray_error(
311 "index " +
312 std::to_string(idx) +
313 " out of range [0, " +
314 std::to_string(First) +
315 ')');
316 return base_type::operator[](idx);
317 }
318
320 const_reference operator()(size_t idx) const
321 {
322 if (idx >= First)
323 throw multiarray_error(
324 "index " +
325 std::to_string(idx) +
326 " out of range [0, " +
327 std::to_string(First) +
328 ')');
329 return base_type::operator[](idx);
330 }
331
339 template <class... Indices>
340 auto operator()(size_t idx, Indices... rest)
341 -> decltype(base_type::operator[](idx)(rest...))
342 {
343 static_assert(sizeof...(Indices) < rank(),
344 "Too Many Arguments!");
345 if (idx >= First)
346 throw multiarray_error(
347 "index " +
348 std::to_string(idx) +
349 " out of range [0, " +
350 std::to_string(First) +
351 ')');
352 return base_type::operator[](idx)(rest...);
353 }
354
356 template <class... Indices>
357 auto operator()(size_t idx, Indices... rest) const
358 -> decltype(base_type::operator[](idx)(rest...))
359 {
360 static_assert(sizeof...(Indices) < rank(),
361 "Too Many Arguments!");
362 if (idx >= First)
363 throw multiarray_error(
364 "index " +
365 std::to_string(idx) +
366 " out of range [0, " +
367 std::to_string(First) +
368 ')');
369 return base_type::operator[](idx)(rest...);
370 }
371
373 friend std::ostream &operator<<(std::ostream &os, const MultiArray &ma)
374 {
375 if (ma.begin() == ma.end())
376 return os << "[]";
377 auto it = ma.begin();
378 os << '[' << *it;
379 while (++it != ma.end())
380 {
381 os << ", " << *it;
382 }
383 return os << ']';
384 }
385
387 T *fbegin() { return this->data()->fbegin(); }
388
390 const T *fbegin() const { return this->data()->fbegin(); }
391
393 T *fend() { return this->fbegin() + this->fsize(); }
394
396 const T *fend() const { return this->fbegin() + this->fsize(); }
397
403 {
404 return *(MultiArray<T, fsize()> *)this;
405 }
406
411 const MultiArray<T, fsize()> &flatten() const
412 {
413 return *(const MultiArray<T, fsize()> *)this;
414 }
415
420 static constexpr std::array<size_t, rank()> dims()
421 {
422 return {First, Rest...};
423 }
424 };
425
426 // ========================== 运算符重载(数组与数组) ==========================
432
441 template <class T, size_t... Dims>
443 const MultiArray<T, Dims...> &b)
444 {
445 MultiArray<T, Dims...> c;
446 auto ai = a.fbegin();
447 auto bi = b.fbegin();
448 auto ci = c.fbegin();
449 while (ci != c.fend())
450 *ci++ = *ai++ + *bi++;
451 return c;
452 }
453
457 template <class T, size_t... Dims>
459 const MultiArray<T, Dims...> &b)
460 {
461 MultiArray<T, Dims...> c;
462 auto ai = a.fbegin();
463 auto bi = b.fbegin();
464 auto ci = c.fbegin();
465 while (ci != c.fend())
466 *ci++ = *ai++ - *bi++;
467 return c;
468 }
469
473 template <class T, size_t... Dims>
475 const MultiArray<T, Dims...> &b)
476 {
477 MultiArray<T, Dims...> c;
478 auto ai = a.fbegin();
479 auto bi = b.fbegin();
480 auto ci = c.fbegin();
481 while (ci != c.fend())
482 *ci++ = *ai++ * *bi++;
483 return c;
484 }
485
489 template <class T, size_t... Dims>
491 const MultiArray<T, Dims...> &b)
492 {
493 MultiArray<T, Dims...> c;
494 auto ai = a.fbegin();
495 auto bi = b.fbegin();
496 auto ci = c.fbegin();
497 while (ci != c.fend())
498 *ci++ = *ai++ / *bi++;
499 return c;
500 }
501
505 template <class T, size_t... Dims>
507 const MultiArray<T, Dims...> &b)
508 {
509 MultiArray<T, Dims...> c;
510 auto ai = a.fbegin();
511 auto bi = b.fbegin();
512 auto ci = c.fbegin();
513 while (ci != c.fend())
514 *ci++ = *ai++ % *bi++;
515 return c;
516 }
517
521 template <class T, size_t... Dims>
523 const MultiArray<T, Dims...> &b)
524 {
525 auto ai = a.fbegin();
526 auto bi = b.fbegin();
527 while (ai != a.fend())
528 *ai++ += *bi++;
529 return a;
530 }
531
535 template <class T, size_t... Dims>
537 const MultiArray<T, Dims...> &b)
538 {
539 auto ai = a.fbegin();
540 auto bi = b.fbegin();
541 while (ai != a.fend())
542 *ai++ -= *bi++;
543 return a;
544 }
545
549 template <class T, size_t... Dims>
551 const MultiArray<T, Dims...> &b)
552 {
553 auto ai = a.fbegin();
554 auto bi = b.fbegin();
555 while (ai != a.fend())
556 *ai++ *= *bi++;
557 return a;
558 }
559
563 template <class T, size_t... Dims>
565 const MultiArray<T, Dims...> &b)
566 {
567 auto ai = a.fbegin();
568 auto bi = b.fbegin();
569 while (ai != a.fend())
570 *ai++ /= *bi++;
571 return a;
572 }
573
577 template <class T, size_t... Dims>
579 const MultiArray<T, Dims...> &b)
580 {
581 auto ai = a.fbegin();
582 auto bi = b.fbegin();
583 while (ai != a.fend())
584 *ai++ %= *bi++;
585 return a;
586 }
587
591 template <class T, size_t... Dims>
593 const MultiArray<T, Dims...> &b)
594 {
595 MultiArray<bool, Dims...> c;
596 auto ai = a.fbegin();
597 auto bi = b.fbegin();
598 auto ci = c.fbegin();
599 while (ci != c.fend())
600 *ci++ = *ai++ == *bi++;
601 return c;
602 }
603
607 template <class T, size_t... Dims>
609 const MultiArray<T, Dims...> &b)
610 {
611 MultiArray<bool, Dims...> c;
612 auto ai = a.fbegin();
613 auto bi = b.fbegin();
614 auto ci = c.fbegin();
615 while (ci != c.fend())
616 *ci++ = *ai++ != *bi++;
617 return c;
618 }
619
623 template <class T, size_t... Dims>
624 MultiArray<bool, Dims...> operator<(const MultiArray<T, Dims...> &a,
625 const MultiArray<T, Dims...> &b)
626 {
627 MultiArray<bool, Dims...> c;
628 auto ai = a.fbegin();
629 auto bi = b.fbegin();
630 auto ci = c.fbegin();
631 while (ci != c.fend())
632 *ci++ = *ai++ < *bi++;
633 return c;
634 }
635
639 template <class T, size_t... Dims>
641 const MultiArray<T, Dims...> &b)
642 {
643 MultiArray<bool, Dims...> c;
644 auto ai = a.fbegin();
645 auto bi = b.fbegin();
646 auto ci = c.fbegin();
647 while (ci != c.fend())
648 *ci++ = *ai++ > *bi++;
649 return c;
650 }
651
655 template <class T, size_t... Dims>
656 MultiArray<bool, Dims...> operator<=(const MultiArray<T, Dims...> &a,
657 const MultiArray<T, Dims...> &b)
658 {
659 MultiArray<bool, Dims...> c;
660 auto ai = a.fbegin();
661 auto bi = b.fbegin();
662 auto ci = c.fbegin();
663 while (ci != c.fend())
664 *ci++ = *ai++ <= *bi++;
665 return c;
666 }
667
671 template <class T, size_t... Dims>
673 const MultiArray<T, Dims...> &b)
674 {
675 MultiArray<bool, Dims...> c;
676 auto ai = a.fbegin();
677 auto bi = b.fbegin();
678 auto ci = c.fbegin();
679 while (ci != c.fend())
680 *ci++ = *ai++ >= *bi++;
681 return c;
682 }
683
684 // 算术运算符(数组与标量)
688 template <class T, size_t... Dims, class U>
690 const U &value)
691 {
692 MultiArray<T, Dims...> b;
693 auto ai = a.fbegin();
694 auto bi = b.fbegin();
695 while (bi != b.fend())
696 *bi++ = *ai++ + value;
697 return b;
698 }
699
703 template <class T, size_t... Dims, class U>
705 const U &value)
706 {
707 MultiArray<T, Dims...> b;
708 auto ai = a.fbegin();
709 auto bi = b.fbegin();
710 while (bi != b.fend())
711 *bi++ = *ai++ - value;
712 return b;
713 }
714
718 template <class T, size_t... Dims, class U>
720 const U &value)
721 {
722 MultiArray<T, Dims...> b;
723 auto ai = a.fbegin();
724 auto bi = b.fbegin();
725 while (bi != b.fend())
726 *bi++ = *ai++ * value;
727 return b;
728 }
729
733 template <class T, size_t... Dims, class U>
735 const U &value)
736 {
737 MultiArray<T, Dims...> b;
738 auto ai = a.fbegin();
739 auto bi = b.fbegin();
740 while (bi != b.fend())
741 *bi++ = *ai++ / value;
742 return b;
743 }
744
748 template <class T, size_t... Dims, class U>
750 const U &value)
751 {
752 MultiArray<T, Dims...> b;
753 auto ai = a.fbegin();
754 auto bi = b.fbegin();
755 while (bi != b.fend())
756 *bi++ = *ai++ % value;
757 return b;
758 }
759
763 template <class T, size_t... Dims, class U>
765 const U &value)
766 {
767 a.for_each([&](T &ref)
768 { ref += value; });
769 return a;
770 }
771
775 template <class T, size_t... Dims, class U>
777 const U &value)
778 {
779 a.for_each([&](T &ref)
780 { ref -= value; });
781 return a;
782 }
783
787 template <class T, size_t... Dims, class U>
789 const U &value)
790 {
791 a.for_each([&](T &ref)
792 { ref *= value; });
793 return a;
794 }
795
799 template <class T, size_t... Dims, class U>
801 const U &value)
802 {
803 a.for_each([&](T &ref)
804 { ref /= value; });
805 return a;
806 }
807
811 template <class T, size_t... Dims, class U>
813 const U &value)
814 {
815 a.for_each([&](T &ref)
816 { ref %= value; });
817 return a;
818 }
819
820 // 算术运算符(标量与数组)
824 template <class T, size_t... Dims, class U>
825 MultiArray<T, Dims...> operator+(const U &value,
826 const MultiArray<T, Dims...> &a)
827 {
828 return a + value;
829 }
830
834 template <class T, size_t... Dims, class U>
835 MultiArray<T, Dims...> operator-(const U &value,
836 const MultiArray<T, Dims...> &a)
837 {
838 MultiArray<T, Dims...> b;
839 auto ai = a.fbegin();
840 auto bi = b.fbegin();
841 while (bi != b.fend())
842 *bi++ = value - *ai++;
843 return b;
844 }
845
849 template <class T, size_t... Dims, class U>
850 MultiArray<T, Dims...> operator*(const U &value,
851 const MultiArray<T, Dims...> &a)
852 {
853 return a * value;
854 }
855
859 template <class T, size_t... Dims, class U>
860 MultiArray<T, Dims...> operator/(const U &value,
861 const MultiArray<T, Dims...> &a)
862 {
863 MultiArray<T, Dims...> b;
864 auto ai = a.fbegin();
865 auto bi = b.fbegin();
866 while (bi != b.fend())
867 *bi++ = value / *ai++;
868 return b;
869 }
870
874 template <class T, size_t... Dims, class U>
875 MultiArray<T, Dims...> operator%(const U &value,
876 const MultiArray<T, Dims...> &a)
877 {
878 MultiArray<T, Dims...> b;
879 auto ai = a.fbegin();
880 auto bi = b.fbegin();
881 while (bi != b.fend())
882 *bi++ = value % *ai++;
883 return b;
884 }
885
886 // 一元运算符
890 template <class T, size_t... Dims>
892 {
893 return a;
894 }
895
899 template <class T, size_t... Dims>
901 {
902 MultiArray<T, Dims...> b;
903 auto ai = a.fbegin();
904 auto bi = b.fbegin();
905 while (bi != b.fend())
906 *bi++ = -*ai++;
907 return b;
908 }
909
913 template <class T, size_t... Dims>
915 {
916 MultiArray<bool, Dims...> b;
917 auto ai = a.fbegin();
918 auto bi = b.fbegin();
919 while (bi != b.fend())
920 *bi++ = !*ai++;
921 return b;
922 }
923
927 template <class T, size_t... Dims>
929 {
930 MultiArray<T, Dims...> b;
931 auto ai = a.fbegin();
932 auto bi = b.fbegin();
933 while (bi != b.fend())
934 *bi++ = ~*ai++;
935 return b;
936 }
937
938 // 比较运算符(数组与标量)
942 template <class T, size_t... Dims, class U>
944 const U &value)
945 {
946 MultiArray<bool, Dims...> b;
947 auto ai = a.fbegin();
948 auto bi = b.fbegin();
949 while (bi != b.fend())
950 *bi++ = *ai++ == value;
951 return b;
952 }
953
957 template <class T, size_t... Dims, class U>
959 const U &value)
960 {
961 MultiArray<bool, Dims...> b;
962 auto ai = a.fbegin();
963 auto bi = b.fbegin();
964 while (bi != b.fend())
965 *bi++ = *ai++ != value;
966 return b;
967 }
968
972 template <class T, size_t... Dims, class U>
973 MultiArray<bool, Dims...> operator<(const MultiArray<T, Dims...> &a,
974 const U &value)
975 {
976 MultiArray<bool, Dims...> b;
977 auto ai = a.fbegin();
978 auto bi = b.fbegin();
979 while (bi != b.fend())
980 *bi++ = *ai++ < value;
981 return b;
982 }
983
987 template <class T, size_t... Dims, class U>
989 const U &value)
990 {
991 MultiArray<bool, Dims...> b;
992 auto ai = a.fbegin();
993 auto bi = b.fbegin();
994 while (bi != b.fend())
995 *bi++ = *ai++ > value;
996 return b;
997 }
998
1002 template <class T, size_t... Dims, class U>
1003 MultiArray<bool, Dims...> operator<=(const MultiArray<T, Dims...> &a,
1004 const U &value)
1005 {
1006 MultiArray<bool, Dims...> b;
1007 auto ai = a.fbegin();
1008 auto bi = b.fbegin();
1009 while (bi != b.fend())
1010 *bi++ = *ai++ <= value;
1011 return b;
1012 }
1013
1017 template <class T, size_t... Dims, class U>
1019 const U &value)
1020 {
1021 MultiArray<bool, Dims...> b;
1022 auto ai = a.fbegin();
1023 auto bi = b.fbegin();
1024 while (bi != b.fend())
1025 *bi++ = *ai++ >= value;
1026 return b;
1027 }
1028
1029 // 比较运算符(标量与数组)
1033 template <class T, size_t... Dims, class U>
1034 MultiArray<bool, Dims...> operator==(const U &value,
1035 const MultiArray<T, Dims...> &a)
1036 {
1037 return a == value;
1038 }
1039
1043 template <class T, size_t... Dims, class U>
1044 MultiArray<bool, Dims...> operator!=(const U &value,
1045 const MultiArray<T, Dims...> &a)
1046 {
1047 return a != value;
1048 }
1049
1053 template <class T, size_t... Dims, class U>
1054 MultiArray<bool, Dims...> operator<(const U &value,
1055 const MultiArray<T, Dims...> &a)
1056 {
1057 return a > value;
1058 }
1059
1063 template <class T, size_t... Dims, class U>
1064 MultiArray<bool, Dims...> operator>(const U &value,
1065 const MultiArray<T, Dims...> &a)
1066 {
1067 return a < value;
1068 }
1069
1073 template <class T, size_t... Dims, class U>
1074 MultiArray<bool, Dims...> operator<=(const U &value,
1075 const MultiArray<T, Dims...> &a)
1076 {
1077 return a >= value;
1078 }
1079
1083 template <class T, size_t... Dims, class U>
1084 MultiArray<bool, Dims...> operator>=(const U &value,
1085 const MultiArray<T, Dims...> &a)
1086 {
1087 return a <= value;
1088 }
1089
1090 // 逻辑运算符(数组与数组)
1094 template <class T, size_t... Dims>
1096 const MultiArray<T, Dims...> &b)
1097 {
1098 MultiArray<bool, Dims...> c;
1099 auto ai = a.fbegin();
1100 auto bi = b.fbegin();
1101 auto ci = c.fbegin();
1102 while (ci != c.fend())
1103 *ci++ = *ai++ && *bi++;
1104 return c;
1105 }
1106
1110 template <class T, size_t... Dims>
1112 const MultiArray<T, Dims...> &b)
1113 {
1114 MultiArray<bool, Dims...> c;
1115 auto ai = a.fbegin();
1116 auto bi = b.fbegin();
1117 auto ci = c.fbegin();
1118 while (ci != c.fend())
1119 *ci++ = *ai++ || *bi++;
1120 return c;
1121 }
1122
1123 // 逻辑运算符(数组与标量)
1127 template <class T, size_t... Dims, class U>
1129 const U &value)
1130 {
1131 MultiArray<bool, Dims...> b;
1132 auto ai = a.fbegin();
1133 auto bi = b.fbegin();
1134 while (bi != b.fend())
1135 *bi++ = *ai++ && value;
1136 return b;
1137 }
1138
1142 template <class T, size_t... Dims, class U>
1144 const U &value)
1145 {
1146 MultiArray<bool, Dims...> b;
1147 auto ai = a.fbegin();
1148 auto bi = b.fbegin();
1149 while (bi != b.fend())
1150 *bi++ = *ai++ || value;
1151 return b;
1152 }
1153
1157 template <class T, size_t... Dims, class U>
1158 MultiArray<bool, Dims...> operator&&(const U &value,
1159 const MultiArray<T, Dims...> &a)
1160 {
1161 return a && value;
1162 }
1163
1167 template <class T, size_t... Dims, class U>
1168 MultiArray<bool, Dims...> operator||(const U &value,
1169 const MultiArray<T, Dims...> &a)
1170 {
1171 return a || value;
1172 }
1173
1174 // 位运算符(数组与数组)
1178 template <class T, size_t... Dims>
1180 const MultiArray<T, Dims...> &b)
1181 {
1182 MultiArray<T, Dims...> c;
1183 auto ai = a.fbegin();
1184 auto bi = b.fbegin();
1185 auto ci = c.fbegin();
1186 while (ci != c.fend())
1187 *ci++ = *ai++ & *bi++;
1188 return c;
1189 }
1190
1194 template <class T, size_t... Dims>
1196 const MultiArray<T, Dims...> &b)
1197 {
1198 MultiArray<T, Dims...> c;
1199 auto ai = a.fbegin();
1200 auto bi = b.fbegin();
1201 auto ci = c.fbegin();
1202 while (ci != c.fend())
1203 *ci++ = *ai++ | *bi++;
1204 return c;
1205 }
1206
1210 template <class T, size_t... Dims>
1212 const MultiArray<T, Dims...> &b)
1213 {
1214 MultiArray<T, Dims...> c;
1215 auto ai = a.fbegin();
1216 auto bi = b.fbegin();
1217 auto ci = c.fbegin();
1218 while (ci != c.fend())
1219 *ci++ = *ai++ ^ *bi++;
1220 return c;
1221 }
1222
1226 template <class T, size_t... Dims>
1227 MultiArray<T, Dims...> operator<<(const MultiArray<T, Dims...> &a,
1228 const MultiArray<T, Dims...> &b)
1229 {
1230 MultiArray<T, Dims...> c;
1231 auto ai = a.fbegin();
1232 auto bi = b.fbegin();
1233 auto ci = c.fbegin();
1234 while (ci != c.fend())
1235 *ci++ = *ai++ << *bi++;
1236 return c;
1237 }
1238
1242 template <class T, size_t... Dims>
1244 const MultiArray<T, Dims...> &b)
1245 {
1246 MultiArray<T, Dims...> c;
1247 auto ai = a.fbegin();
1248 auto bi = b.fbegin();
1249 auto ci = c.fbegin();
1250 while (ci != c.fend())
1251 *ci++ = *ai++ >> *bi++;
1252 return c;
1253 }
1254
1258 template <class T, size_t... Dims>
1260 const MultiArray<T, Dims...> &b)
1261 {
1262 auto ai = a.fbegin();
1263 auto bi = b.fbegin();
1264 while (ai != a.fend())
1265 *ai++ &= *bi++;
1266 return a;
1267 }
1268
1272 template <class T, size_t... Dims>
1274 const MultiArray<T, Dims...> &b)
1275 {
1276 auto ai = a.fbegin();
1277 auto bi = b.fbegin();
1278 while (ai != a.fend())
1279 *ai++ |= *bi++;
1280 return a;
1281 }
1282
1286 template <class T, size_t... Dims>
1288 const MultiArray<T, Dims...> &b)
1289 {
1290 auto ai = a.fbegin();
1291 auto bi = b.fbegin();
1292 while (ai != a.fend())
1293 *ai++ ^= *bi++;
1294 return a;
1295 }
1296
1300 template <class T, size_t... Dims>
1301 MultiArray<T, Dims...> &operator<<=(MultiArray<T, Dims...> &a,
1302 const MultiArray<T, Dims...> &b)
1303 {
1304 auto ai = a.fbegin();
1305 auto bi = b.fbegin();
1306 while (ai != a.fend())
1307 *ai++ <<= *bi++;
1308 return a;
1309 }
1310
1314 template <class T, size_t... Dims>
1316 const MultiArray<T, Dims...> &b)
1317 {
1318 auto ai = a.fbegin();
1319 auto bi = b.fbegin();
1320 while (ai != a.fend())
1321 *ai++ >>= *bi++;
1322 return a;
1323 }
1324
1325 // 位运算符(数组与标量)
1329 template <class T, size_t... Dims, class U>
1331 const U &value)
1332 {
1333 MultiArray<T, Dims...> b;
1334 auto ai = a.fbegin();
1335 auto bi = b.fbegin();
1336 while (bi != b.fend())
1337 *bi++ = *ai++ & value;
1338 return b;
1339 }
1340
1344 template <class T, size_t... Dims, class U>
1346 const U &value)
1347 {
1348 MultiArray<T, Dims...> b;
1349 auto ai = a.fbegin();
1350 auto bi = b.fbegin();
1351 while (bi != b.fend())
1352 *bi++ = *ai++ | value;
1353 return b;
1354 }
1355
1359 template <class T, size_t... Dims, class U>
1361 const U &value)
1362 {
1363 MultiArray<T, Dims...> b;
1364 auto ai = a.fbegin();
1365 auto bi = b.fbegin();
1366 while (bi != b.fend())
1367 *bi++ = *ai++ ^ value;
1368 return b;
1369 }
1370
1374 template <class T, size_t... Dims, class U>
1375 MultiArray<T, Dims...> operator<<(const MultiArray<T, Dims...> &a,
1376 const U &value)
1377 {
1378 MultiArray<T, Dims...> b;
1379 auto ai = a.fbegin();
1380 auto bi = b.fbegin();
1381 while (bi != b.fend())
1382 *bi++ = *ai++ << value;
1383 return b;
1384 }
1385
1389 template <class T, size_t... Dims, class U>
1391 const U &value)
1392 {
1393 MultiArray<T, Dims...> b;
1394 auto ai = a.fbegin();
1395 auto bi = b.fbegin();
1396 while (bi != b.fend())
1397 *bi++ = *ai++ >> value;
1398 return b;
1399 }
1400
1404 template <class T, size_t... Dims, class U>
1405 MultiArray<T, Dims...> operator&(const U &value,
1406 const MultiArray<T, Dims...> &a)
1407 {
1408 return a & value;
1409 }
1410
1414 template <class T, size_t... Dims, class U>
1415 MultiArray<T, Dims...> operator|(const U &value,
1416 const MultiArray<T, Dims...> &a)
1417 {
1418 return a | value;
1419 }
1420
1424 template <class T, size_t... Dims, class U>
1425 MultiArray<T, Dims...> operator^(const U &value,
1426 const MultiArray<T, Dims...> &a)
1427 {
1428 return a ^ value;
1429 }
1430
1434 template <class T, size_t... Dims, class U>
1435 MultiArray<T, Dims...> operator<<(const U &value,
1436 const MultiArray<T, Dims...> &a)
1437 {
1438 MultiArray<T, Dims...> b;
1439 auto ai = a.fbegin();
1440 auto bi = b.fbegin();
1441 while (bi != b.fend())
1442 *bi++ = value << *ai++;
1443 return b;
1444 }
1445
1449 template <class T, size_t... Dims, class U>
1450 MultiArray<T, Dims...> operator>>(const U &value,
1451 const MultiArray<T, Dims...> &a)
1452 {
1453 MultiArray<T, Dims...> b;
1454 auto ai = a.fbegin();
1455 auto bi = b.fbegin();
1456 while (bi != b.fend())
1457 *bi++ = value >> *ai++;
1458 return b;
1459 }
1460
1464 template <class T, size_t... Dims, class U>
1466 const U &value)
1467 {
1468 a.for_each([&](T &ref)
1469 { ref &= value; });
1470 return a;
1471 }
1472
1476 template <class T, size_t... Dims, class U>
1478 const U &value)
1479 {
1480 a.for_each([&](T &ref)
1481 { ref |= value; });
1482 return a;
1483 }
1484
1488 template <class T, size_t... Dims, class U>
1490 const U &value)
1491 {
1492 a.for_each([&](T &ref)
1493 { ref ^= value; });
1494 return a;
1495 }
1496
1500 template <class T, size_t... Dims, class U>
1501 MultiArray<T, Dims...> &operator<<=(MultiArray<T, Dims...> &a,
1502 const U &value)
1503 {
1504 a.for_each([&](T &ref)
1505 { ref <<= value; });
1506 return a;
1507 }
1508
1512 template <class T, size_t... Dims, class U>
1514 const U &value)
1515 {
1516 a.for_each([&](T &ref)
1517 { ref >>= value; });
1518 return a;
1519 }
1520 // end of multiarray_ops
1522
1523 // ========================== 统计函数 ==========================
1529
1537 template <class T, size_t... Dims>
1539 {
1540 T result{};
1541 a.for_each([&](const T &ref)
1542 { result += ref; });
1543 return result;
1544 }
1545
1550 template <class T, size_t... Dims>
1552 {
1553 return *std::min_element(a.fbegin(), a.fend());
1554 }
1555
1560 template <class T, size_t... Dims>
1562 {
1563 return *std::max_element(a.fbegin(), a.fend());
1564 }
1565
1570 template <class T, size_t... Dims>
1572 {
1573 for (auto it = a.fbegin(); it != a.fend(); ++it)
1574 if (!*it)
1575 return false;
1576 return true;
1577 }
1578
1583 template <class T, size_t... Dims>
1585 {
1586 for (auto it = a.fbegin(); it != a.fend(); ++it)
1587 if (*it)
1588 return true;
1589 return false;
1590 }
1591 // end of multiarray_stats
1593
1594 // ========================== 类型转换 ==========================
1600
1610 template <size_t... OutArrDims, class VarType, size_t... InArrDims>
1611 MultiArray<VarType, OutArrDims...> multiarray_cast(
1612 const MultiArray<VarType, InArrDims...> &inputArr)
1613 {
1616 "Bad multiarray_cast: Mismatch Size");
1617 MultiArray<VarType, OutArrDims...> outputArr;
1618 std::copy(inputArr.fbegin(), inputArr.fend(), outputArr.fbegin());
1619 return outputArr;
1620 }
1621
1633 template <class OutType, size_t... OutArrDims,
1634 class InType, size_t... InArrDims>
1635 MultiArray<OutType, OutArrDims...> unsafe_multiarray_cast(
1636 const MultiArray<InType, InArrDims...> &inputArr)
1637 {
1638 MultiArray<OutType, OutArrDims...> outputArr;
1639 memcpy(&outputArr, &inputArr, sizeof(outputArr));
1640 return outputArr;
1641 }
1642
1652 template <size_t... OutArrDims, class VarType, size_t... InArrDims>
1653 MultiArray<VarType, OutArrDims...> &inplace_multiarray_cast(
1655 {
1658 "Bad inplace_multiarray_cast: Mismatch Size");
1659 auto p = (MultiArray<VarType, OutArrDims...> *)&inputArr;
1660 return *p;
1661 }
1662
1672 template <size_t... OutArrDims, class VarType, size_t... InArrDims>
1673 const MultiArray<VarType, OutArrDims...> &inplace_multiarray_cast(
1674 const MultiArray<VarType, InArrDims...> &inputArr)
1675 {
1678 "Bad inplace_multiarray_cast: Mismatch Size");
1679 auto p = (const MultiArray<VarType, OutArrDims...> *)&inputArr;
1680 return *p;
1681 }
1682 // end of multiarray_cast
1684}
const T * fend() const
常量版本。
Definition multiarray.h:192
const T * fbegin() const
常量版本。
Definition multiarray.h:186
void for_each(F &&visit) const
遍历所有元素并应用函数(常量版本)。
Definition multiarray.h:129
MultiArray(const T &value)
用相同值填充所有元素。
Definition multiarray.h:81
reference operator()(size_t i)
带边界检查的下标访问(一维)。
Definition multiarray.h:141
friend std::ostream & operator<<(std::ostream &os, const MultiArray &ma)
输出 MultiArray 到流,格式为嵌套的方括号。
Definition multiarray.h:167
MultiArray()=default
默认构造,元素未初始化(基本类型为随机值)。
T & reference
Definition multiarray.h:71
const T & const_reference
Definition multiarray.h:72
T * fend()
返回指向扁平化数据末尾的指针(非常量)。
Definition multiarray.h:189
void fill(const T &value)
用给定值填充所有元素。
Definition multiarray.h:105
MultiArray(const base_type &other)
从 std::array 拷贝构造。
Definition multiarray.h:87
const_reference operator()(size_t i) const
常量版本。
Definition multiarray.h:154
T * fbegin()
返回指向扁平化数据起始的指针(非常量)。
Definition multiarray.h:183
MultiArray(std::initializer_list< T > init)
从初始化列表构造(仅一维)。
Definition multiarray.h:93
static constexpr std::array< size_t, 1 > dims()
返回包含维度信息的数组。
Definition multiarray.h:216
static constexpr size_t rank()
返回数组的维数(一维时为 1)。
Definition multiarray.h:99
void for_each(F &&visit)
遍历所有元素并应用函数(非常量版本)。
Definition multiarray.h:117
static constexpr size_t fsize()
返回元素总数。
Definition multiarray.h:102
const MultiArray & flatten() const
扁平化视图(常量)。
Definition multiarray.h:207
T value_type
Definition multiarray.h:70
MultiArray & flatten()
扁平化视图(可变)。
Definition multiarray.h:198
auto operator()(size_t idx, Indices... rest) const -> decltype(base_type::operator[](idx)(rest...))
常量版本。
Definition multiarray.h:357
reference operator()(size_t idx)
单下标访问,返回子数组引用。
Definition multiarray.h:307
void for_each(F &&visit) const
遍历所有元素(常量版本)。
Definition multiarray.h:295
const MultiArray< T, Rest... > & const_reference
Definition multiarray.h:237
const MultiArray< T, fsize()> & flatten() const
扁平化视图(常量)。
Definition multiarray.h:411
MultiArray< T, Rest... > & reference
Definition multiarray.h:236
const T * fend() const
常量版本。
Definition multiarray.h:396
void for_each(F &&visit)
遍历所有元素(非常量版本)。
Definition multiarray.h:284
MultiArray(std::initializer_list< MultiArray< T, Rest... > > init)
从初始化列表构造(多维)。
Definition multiarray.h:258
const T * fbegin() const
常量版本。
Definition multiarray.h:390
friend std::ostream & operator<<(std::ostream &os, const MultiArray &ma)
输出 MultiArray 到流,递归输出嵌套方括号。
Definition multiarray.h:373
MultiArray< T, fsize()> & flatten()
扁平化视图(可变)。
Definition multiarray.h:402
static constexpr size_t fsize()
返回元素总数。
Definition multiarray.h:267
MultiArray()=default
默认构造。
T * fbegin()
扁平化起始迭代器(非常量)。
Definition multiarray.h:387
void fill(const T &value)
递归填充所有元素。
Definition multiarray.h:273
auto operator()(size_t idx, Indices... rest) -> decltype(base_type::operator[](idx)(rest...))
多维下标访问。
Definition multiarray.h:340
T * fend()
扁平化结束迭代器(非常量)。
Definition multiarray.h:393
const_reference operator()(size_t idx) const
常量版本。
Definition multiarray.h:320
static constexpr size_t rank()
返回数组维数。
Definition multiarray.h:264
static constexpr std::array< size_t, rank()> dims()
返回包含维度信息的数组。
Definition multiarray.h:420
MultiArray(const T &value)
用相同值递归填充所有元素。
Definition multiarray.h:246
T value_type
Definition multiarray.h:235
MultiArray(const base_type &other)
从 std::array 拷贝构造。
Definition multiarray.h:252
编译期固定维度的多维数组。
Definition multiarray.h:57
表示 MultiArray 多维数组操作中的错误,如维度不匹配。
Definition csexc.h:120
定义 console 库使用的自定义异常类层次结构。
MultiArray< VarType, OutArrDims... > multiarray_cast(const MultiArray< VarType, InArrDims... > &inputArr)
改变 MultiArray 的维度形状(元素类型不变),要求总元素数相同。
Definition multiarray.h:1611
MultiArray< OutType, OutArrDims... > unsafe_multiarray_cast(const MultiArray< InType, InArrDims... > &inputArr)
不安全地改变 MultiArray 的元素类型和维度(内存拷贝)。
Definition multiarray.h:1635
MultiArray< VarType, OutArrDims... > & inplace_multiarray_cast(MultiArray< VarType, InArrDims... > &inputArr)
就地版本的 multiarray_cast,仅视图,不拷贝(可变版本)
Definition multiarray.h:1653
MultiArray< T, Dims... > operator<<(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
左移(数组 << 数组)。
Definition multiarray.h:1227
MultiArray< bool, Dims... > operator>=(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素大于等于比较(数组 >= 数组)。
Definition multiarray.h:672
MultiArray< T, Dims... > & operator*=(MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素乘法赋值(数组 *= 数组)。
Definition multiarray.h:550
MultiArray< bool, Dims... > operator<=(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素小于等于比较(数组 <= 数组)。
Definition multiarray.h:656
MultiArray< T, Dims... > & operator%=(MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素取模赋值(数组 %= 数组)。
Definition multiarray.h:578
MultiArray< bool, Dims... > operator!=(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素不等比较(数组 != 数组)。
Definition multiarray.h:608
MultiArray< T, Dims... > & operator/=(MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素除法赋值(数组 /= 数组)。
Definition multiarray.h:564
MultiArray< T, Dims... > & operator+=(MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素加法赋值(数组 += 数组)。
Definition multiarray.h:522
MultiArray< bool, Dims... > operator==(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素相等比较(数组 == 数组),返回 bool 数组。
Definition multiarray.h:592
MultiArray< T, Dims... > & operator<<=(MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
左移赋值(数组 <<= 数组)。
Definition multiarray.h:1301
MultiArray< T, Dims... > operator>>(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
右移(数组 >> 数组)。
Definition multiarray.h:1243
MultiArray< T, Dims... > operator+(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素加法(数组 + 数组)。
Definition multiarray.h:442
MultiArray< T, Dims... > operator^(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
按位异或(数组 ^ 数组)。
Definition multiarray.h:1211
MultiArray< bool, Dims... > operator!(const MultiArray< T, Dims... > &a)
逻辑非(数组),返回 bool 数组。
Definition multiarray.h:914
MultiArray< T, Dims... > operator*(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素乘法(数组 * 数组)。
Definition multiarray.h:474
MultiArray< T, Dims... > & operator&=(MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
按位与赋值(数组 &= 数组)。
Definition multiarray.h:1259
MultiArray< T, Dims... > operator/(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素除法(数组 / 数组)。
Definition multiarray.h:490
MultiArray< T, Dims... > & operator>>=(MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
右移赋值(数组 >>= 数组)。
Definition multiarray.h:1315
MultiArray< bool, Dims... > operator||(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
逻辑或(数组 || 数组)。
Definition multiarray.h:1111
MultiArray< T, Dims... > & operator-=(MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素减法赋值(数组 -= 数组)。
Definition multiarray.h:536
MultiArray< T, Dims... > & operator^=(MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
按位异或赋值(数组 ^= 数组)。
Definition multiarray.h:1287
MultiArray< T, Dims... > operator&(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
按位与(数组 & 数组)。
Definition multiarray.h:1179
MultiArray< bool, Dims... > operator&&(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
逻辑与(数组 && 数组),返回 bool 数组。
Definition multiarray.h:1095
MultiArray< T, Dims... > operator-(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素减法(数组 - 数组)。
Definition multiarray.h:458
MultiArray< T, Dims... > & operator|=(MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
按位或赋值(数组 |= 数组)。
Definition multiarray.h:1273
MultiArray< T, Dims... > operator~(const MultiArray< T, Dims... > &a)
按位取反(数组)。
Definition multiarray.h:928
MultiArray< bool, Dims... > operator<(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素小于比较(数组 < 数组)。
Definition multiarray.h:624
MultiArray< bool, Dims... > operator>(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素大于比较(数组 > 数组)。
Definition multiarray.h:640
MultiArray< T, Dims... > operator|(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
按位或(数组 | 数组)。
Definition multiarray.h:1195
MultiArray< T, Dims... > operator%(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
元素取模(数组 % 数组)。
Definition multiarray.h:506
bool all(const MultiArray< T, Dims... > &a)
检查所有元素是否都为 true(逻辑与归约)。
Definition multiarray.h:1571
T min(const MultiArray< T, Dims... > &a)
求最小值。
Definition multiarray.h:1551
bool any(const MultiArray< T, Dims... > &a)
检查是否存在至少一个 true 元素(逻辑或归约)。
Definition multiarray.h:1584
T max(const MultiArray< T, Dims... > &a)
求最大值。
Definition multiarray.h:1561
T sum(const MultiArray< T, Dims... > &a)
求和所有元素。
Definition multiarray.h:1538
enable_if_string< T > repr(T &&value, std::ostream &os=std::cout)
输出字符串类型(std::string, const char* 等)的表示,带双引号。
Definition repr.h:79
本库所有组件所在的顶层命名空间。
@ U
Definition kb.h:73
@ F
Definition kb.h:58
@ T
Definition kb.h:72
@ D
Definition kb.h:56
提供类似 Python 的 repr() 函数,用于生成对象的可读字符串表示。