Console Library 8.0.0
A header-only library that makes C++ simple
Loading...
Searching...
No Matches
matools.h
Go to the documentation of this file.
1
11
12/*
13Copyright (c) 2026 MrXie1109
14
15Permission is hereby granted, free of charge, to any person obtaining a copy
16of this software and associated documentation files (the "Software"), to deal
17in the Software without restriction, including without limitation the rights
18to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19copies of the Software, and to permit persons to whom the Software is
20furnished to do so, subject to the following conditions:
21
22The above copyright notice and this permission notice shall be included in all
23copies or substantial portions of the Software.
24
25THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31SOFTWARE.
32*/
33
34#pragma once
35#define _USE_MATH_DEFINES
36#include <cmath>
37#include <complex>
38#include <iostream>
39#include <numeric>
40
41#include "../async/pool.h"
43#include "../core/sfinae.h"
44#include "./random.h"
45
46#ifndef M_PI
47#define M_PI 3.14159265358979323846
48#endif
49
50namespace console {
56
57 // ---------------------------- 统计 ----------------------------
65 template <class T, size_t... Dims>
66 double mean(const MultiArray<T, Dims...> &arr) {
67 return double(sum(arr)) / arr.fsize();
68 }
69
79 template <class T, size_t... Dims>
80 double variance(const MultiArray<T, Dims...> &arr, bool sample = true) {
81 double m = mean(arr);
82 double sq_sum = 0;
83 arr.for_each([&](const T &x) {
84 double d = double(x) - m;
85 sq_sum += d * d;
86 });
87 return sq_sum / (arr.fsize() - (sample ? 1 : 0));
88 }
89
99 template <class T, size_t... Dims>
100 double stddev(const MultiArray<T, Dims...> &arr, bool sample = true) {
101 return std::sqrt(variance(arr, sample));
102 }
103
104 // ---------------------------- 向量运算(一维) ----------------------------
113 template <class T, size_t N>
115 return std::inner_product(a.fbegin(), a.fend(), b.fbegin(), T{});
116 }
117
125 template <class T, size_t N>
126 double norm(const MultiArray<T, N> &a) {
127 return std::sqrt(double(dot(a, a)));
128 }
129
138 template <class T, size_t N>
139 double cosine(const MultiArray<T, N> &a, const MultiArray<T, N> &b) {
140 return dot(a, b) / (norm(a) * norm(b));
141 }
142
150 template <class T, size_t N>
152 double len = norm(a);
153 if (std::abs(len) < std::numeric_limits<double>::epsilon()) return a;
154 MultiArray<T, N> result;
155 auto ai = a.fbegin();
156 auto ri = result.fbegin();
157 while (ri != result.fend()) *ri++ = *ai++ / len;
158 return result;
159 }
160
169 template <class T, size_t N>
170 double euclidean(const MultiArray<T, N> &a, const MultiArray<T, N> &b) {
171 double sum = 0;
172 auto ai = a.fbegin();
173 auto bi = b.fbegin();
174 while (ai != a.fend()) {
175 double d = *ai++ - *bi++;
176 sum += d * d;
177 }
178 return std::sqrt(sum);
179 }
180
189 template <class T, size_t N>
190 double manhattan(const MultiArray<T, N> &a, const MultiArray<T, N> &b) {
191 double sum = 0;
192 auto ai = a.fbegin();
193 auto bi = b.fbegin();
194 while (ai != a.fend()) sum += std::abs(*ai++ - *bi++);
195 return sum;
196 }
197
198 // ---------------------------- 矩阵运算(二维) ----------------------------
199#ifndef CONSOLE_MATMUL_BLOCK_SIZE
200#define CONSOLE_MATMUL_BLOCK_SIZE 128
201#endif
202
213 template <class T, size_t M, size_t N, size_t K>
214 MultiArray<T, M, K>
216 using std::min;
218 constexpr size_t BLOCK = CONSOLE_MATMUL_BLOCK_SIZE;
219 for (size_t i0 = 0; i0 < M; i0 += BLOCK)
220 for (size_t j0 = 0; j0 < K; j0 += BLOCK)
221 for (size_t k0 = 0; k0 < N; k0 += BLOCK)
222 for (size_t i = i0; i < min(i0 + BLOCK, M); ++i)
223 for (size_t j = j0; j < min(j0 + BLOCK, K); ++j)
224 for (size_t k = k0; k < min(k0 + BLOCK, N); ++k)
225 C[i][j] += A[i][k] * B[k][j];
226 return C;
227 }
228
239 template <class T, size_t M, size_t N, size_t K>
240 MultiArray<T, M, K>
243 for (size_t i = 0; i < M; ++i)
244 for (size_t j = 0; j < K; ++j)
245 for (size_t k = 0; k < N; ++k) C[i][j] += A[i][k] * B[k][j];
246 return C;
247 }
248
259 template <class T, size_t M, size_t N, size_t K>
261 const MultiArray<T, N, K> &B,
262 std::true_type) {
263 return matmul_blocked(A, B);
264 }
265
276 template <class T, size_t M, size_t N, size_t K>
278 const MultiArray<T, N, K> &B,
279 std::false_type) {
280 return matmul_simple(A, B);
281 }
282
293 template <class T, size_t M, size_t N, size_t K>
294 inline MultiArray<T, M, K>
296 constexpr size_t BLOCK = CONSOLE_MATMUL_BLOCK_SIZE;
297 constexpr bool use_blocked = M >= BLOCK && N >= BLOCK && K >= BLOCK;
298 return matmul_impl(A, B, std::integral_constant<bool, use_blocked>{});
299 }
300
313 template <class T, size_t M, size_t N, size_t K>
315 const MultiArray<T, M, N> &A, const MultiArray<T, N, K> &B) {
316 using std::min;
318 constexpr size_t BLOCK = CONSOLE_MATMUL_BLOCK_SIZE;
319 const size_t num_i_blocks = (M + BLOCK - 1) / BLOCK;
320 const size_t num_j_blocks = (K + BLOCK - 1) / BLOCK;
321 std::vector<std::future<void>> futures;
322 futures.reserve(num_i_blocks * num_j_blocks);
323 for (size_t i0_idx = 0; i0_idx < num_i_blocks; ++i0_idx)
324 for (size_t j0_idx = 0; j0_idx < num_j_blocks; ++j0_idx) {
325 size_t i0 = i0_idx * BLOCK;
326 size_t j0 = j0_idx * BLOCK;
327 futures.push_back(pool::submit([&, i0, j0]() {
328 for (size_t k0 = 0; k0 < N; k0 += BLOCK)
329 for (size_t i = i0; i < min(i0 + BLOCK, M); ++i)
330 for (size_t j = j0; j < min(j0 + BLOCK, K); ++j) {
331 T sum = C[i][j];
332 for (size_t k = k0; k < min(k0 + BLOCK, N); ++k)
333 sum += A[i][k] * B[k][j];
334 C[i][j] = sum;
335 }
336 }));
337 }
338 for (auto &f : futures) f.get();
339 return C;
340 }
341
350 template <class T, size_t M, size_t N>
353 for (size_t i = 0; i < M; i++)
354 for (size_t j = 0; j < N; j++) B[j][i] = A[i][j];
355 return B;
356 }
357
364 template <class T, size_t N>
367 for (size_t i = 0; i < N; i++) I[i][i] = T{1};
368 return I;
369 }
370
378 template <class T, size_t N>
380 T result{};
381 for (size_t i = 0; i < N; i++) result += A[i][i];
382 return result;
383 }
384
392 template <class T>
393 MultiArray<T, 3>
395 return MultiArray<T, 3>{a[1] * b[2] - a[2] * b[1],
396 a[2] * b[0] - a[0] * b[2],
397 a[0] * b[1] - a[1] * b[0]};
398 }
399
400 // ---------------------------- 元素级运算 ----------------------------
410 template <class T, size_t... Dims>
411 MultiArray<T, Dims...>
412 clamp(const MultiArray<T, Dims...> &arr, T low, T high) {
413 MultiArray<T, Dims...> result;
414 auto ri = result.fbegin();
415 auto ai = arr.fbegin();
416 while (ri != result.fend()) {
417 *ri = *ai < low ? low : (*ai > high ? high : *ai);
418 ++ri;
419 ++ai;
420 }
421 return result;
422 }
423
431 template <class T, size_t... Dims>
432 MultiArray<T, Dims...> abs(const MultiArray<T, Dims...> &arr) {
433 MultiArray<T, Dims...> result;
434 auto ri = result.fbegin();
435 auto ai = arr.fbegin();
436 while (ri != result.fend()) *ri++ = std::abs(*ai++);
437 return result;
438 }
439
440 // ---------------------------- 随机初始化 ----------------------------
449 template <class T, size_t... Dims>
450 void randomize(MultiArray<T, Dims...> &arr, T min = 0, T max = 100) {
452 arr.for_each([&](T &x) { x = dis(thread_rng()); });
453 }
454
463 template <class T, size_t... Dims>
464 void
466 std::normal_distribution<T> dis(mean, stddev);
467 arr.for_each([&](T &x) { x = dis(thread_rng()); });
468 }
469
478 template <class T, size_t... Dims>
479 void linspace(MultiArray<T, Dims...> &arr, T start, T end) {
480 size_t n = arr.fsize();
481 for (size_t i = 0; i < n; i++)
482 arr.fbegin()[i] = start + (end - start) * i / (n - 1);
483 }
484
485 // ---------------------------- 其他 ----------------------------
493 template <class T, size_t... Dims>
495 return std::accumulate(
496 arr.fbegin(), arr.fend(), T{1}, std::multiplies<T>());
497 }
498
507 template <class T, size_t... Dims>
509 if (k >= arr.fsize()) k = arr.fsize() - 1;
510 std::nth_element(arr.fbegin(), arr.fbegin() + k, arr.fend());
511 return arr.fbegin()[k];
512 }
513
523 template <class T, size_t N, size_t K>
524 MultiArray<T, N + K - 1>
525 convolve1d(const MultiArray<T, N> &signal, const MultiArray<T, K> &kernel) {
526 MultiArray<T, N + K - 1> result(T{});
527 for (size_t i = 0; i < N; i++) {
528 T sum{};
529 for (size_t j = 0; j < K; j++)
530 result[i + j] += signal[i] * kernel[j];
531 }
532 return result;
533 }
534
535 // ---------------------------- 三角函数 ----------------------------
543 template <class T, size_t... Dims>
544 MultiArray<T, Dims...> sin(const MultiArray<T, Dims...> &arr) {
545 MultiArray<T, Dims...> result;
546 auto ri = result.fbegin();
547 auto ai = arr.fbegin();
548 while (ri != result.fend()) *ri++ = std::sin(*ai++);
549 return result;
550 }
551
559 template <class T, size_t... Dims>
560 MultiArray<T, Dims...> cos(const MultiArray<T, Dims...> &arr) {
561 MultiArray<T, Dims...> result;
562 auto ri = result.fbegin();
563 auto ai = arr.fbegin();
564 while (ri != result.fend()) *ri++ = std::cos(*ai++);
565 return result;
566 }
567
575 template <class T, size_t... Dims>
576 MultiArray<T, Dims...> tan(const MultiArray<T, Dims...> &arr) {
577 MultiArray<T, Dims...> result;
578 auto ri = result.fbegin();
579 auto ai = arr.fbegin();
580 while (ri != result.fend()) *ri++ = std::tan(*ai++);
581 return result;
582 }
583
591 template <class T, size_t... Dims>
592 MultiArray<T, Dims...> asin(const MultiArray<T, Dims...> &arr) {
593 MultiArray<T, Dims...> result;
594 auto ri = result.fbegin();
595 auto ai = arr.fbegin();
596 while (ri != result.fend()) *ri++ = std::asin(*ai++);
597 return result;
598 }
599
607 template <class T, size_t... Dims>
608 MultiArray<T, Dims...> acos(const MultiArray<T, Dims...> &arr) {
609 MultiArray<T, Dims...> result;
610 auto ri = result.fbegin();
611 auto ai = arr.fbegin();
612 while (ri != result.fend()) *ri++ = std::acos(*ai++);
613 return result;
614 }
615
623 template <class T, size_t... Dims>
624 MultiArray<T, Dims...> atan(const MultiArray<T, Dims...> &arr) {
625 MultiArray<T, Dims...> result;
626 auto ri = result.fbegin();
627 auto ai = arr.fbegin();
628 while (ri != result.fend()) *ri++ = std::atan(*ai++);
629 return result;
630 }
631
639 template <class T, size_t... Dims>
640 MultiArray<T, Dims...> sinh(const MultiArray<T, Dims...> &arr) {
641 MultiArray<T, Dims...> result;
642 auto ri = result.fbegin();
643 auto ai = arr.fbegin();
644 while (ri != result.fend()) *ri++ = std::sinh(*ai++);
645 return result;
646 }
647
655 template <class T, size_t... Dims>
656 MultiArray<T, Dims...> cosh(const MultiArray<T, Dims...> &arr) {
657 MultiArray<T, Dims...> result;
658 auto ri = result.fbegin();
659 auto ai = arr.fbegin();
660 while (ri != result.fend()) *ri++ = std::cosh(*ai++);
661 return result;
662 }
663
671 template <class T, size_t... Dims>
672 MultiArray<T, Dims...> tanh(const MultiArray<T, Dims...> &arr) {
673 MultiArray<T, Dims...> result;
674 auto ri = result.fbegin();
675 auto ai = arr.fbegin();
676 while (ri != result.fend()) *ri++ = std::tanh(*ai++);
677 return result;
678 }
679
680 // ---------------------------- 指数对数 ----------------------------
688 template <class T, size_t... Dims>
689 MultiArray<T, Dims...> exp(const MultiArray<T, Dims...> &arr) {
690 MultiArray<T, Dims...> result;
691 auto ri = result.fbegin();
692 auto ai = arr.fbegin();
693 while (ri != result.fend()) *ri++ = std::exp(*ai++);
694 return result;
695 }
696
704 template <class T, size_t... Dims>
705 MultiArray<T, Dims...> log(const MultiArray<T, Dims...> &arr) {
706 MultiArray<T, Dims...> result;
707 auto ri = result.fbegin();
708 auto ai = arr.fbegin();
709 while (ri != result.fend()) *ri++ = std::log(*ai++);
710 return result;
711 }
712
720 template <class T, size_t... Dims>
721 MultiArray<T, Dims...> log10(const MultiArray<T, Dims...> &arr) {
722 MultiArray<T, Dims...> result;
723 auto ri = result.fbegin();
724 auto ai = arr.fbegin();
725 while (ri != result.fend()) *ri++ = std::log10(*ai++);
726 return result;
727 }
728
737 template <class T, size_t... Dims>
738 MultiArray<T, Dims...> pow(const MultiArray<T, Dims...> &arr, T exponent) {
739 MultiArray<T, Dims...> result;
740 auto ri = result.fbegin();
741 auto ai = arr.fbegin();
742 while (ri != result.fend()) *ri++ = std::pow(*ai++, exponent);
743 return result;
744 }
745
754 template <class T, size_t... Dims>
755 MultiArray<T, Dims...>
757 MultiArray<T, Dims...> result;
758 auto bi = base.fbegin();
759 auto ei = exp.fbegin();
760 auto ri = result.fbegin();
761 while (ri != result.fend()) *ri++ = std::pow(*bi++, *ei++);
762 return result;
763 }
764
765 // ---------------------------- 取整函数 ----------------------------
773 template <class T, size_t... Dims>
774 MultiArray<T, Dims...> floor(const MultiArray<T, Dims...> &arr) {
775 MultiArray<T, Dims...> result;
776 auto ri = result.fbegin();
777 auto ai = arr.fbegin();
778 while (ri != result.fend()) *ri++ = std::floor(*ai++);
779 return result;
780 }
781
789 template <class T, size_t... Dims>
790 MultiArray<T, Dims...> ceil(const MultiArray<T, Dims...> &arr) {
791 MultiArray<T, Dims...> result;
792 auto ri = result.fbegin();
793 auto ai = arr.fbegin();
794 while (ri != result.fend()) *ri++ = std::ceil(*ai++);
795 return result;
796 }
797
805 template <class T, size_t... Dims>
806 MultiArray<T, Dims...> round(const MultiArray<T, Dims...> &arr) {
807 MultiArray<T, Dims...> result;
808 auto ri = result.fbegin();
809 auto ai = arr.fbegin();
810 while (ri != result.fend()) *ri++ = std::round(*ai++);
811 return result;
812 }
813
822 template < //
823 class T,
824 size_t... Dims,
825 class CharT,
826 class Traits = std::char_traits<CharT>>
827 void print_stats(std::basic_ostream<CharT, Traits> &os,
828 const MultiArray<T, Dims...> &arr,
829 const std::string &name = "") {
830 if (!name.empty()) os << "=== " << name << " ===" << '\n';
831 os << " sum : " << sum(arr) << '\n';
832 os << " mean : " << mean(arr) << '\n';
833 os << " min : " << min(arr) << '\n';
834 os << " max : " << max(arr) << '\n';
835 os << " stddev: " << stddev(arr) << std::endl;
836 }
837
846 template <class T, size_t... Dims>
849 double mean_a = mean(a);
850 double mean_b = mean(b);
851 double sum = 0;
852 auto ai = a.fbegin();
853 auto bi = b.fbegin();
854 while (ai != a.fend()) {
855 sum += (double(*ai) - mean_a) * (double(*bi) - mean_b);
856 ++ai;
857 ++bi;
858 }
859 return sum / (a.fsize() - 1);
860 }
861
870 template <class T, size_t... Dims>
873 double cov = covariance(a, b);
874 double std_a = stddev(a);
875 double std_b = stddev(b);
876 if (std_a == 0 || std_b == 0) return 0;
877 return cov / (std_a * std_b);
878 }
879
887 template <class T, size_t... Dims>
889 size_t n = arr.fsize();
890 auto begin = arr.fbegin();
891 auto end = arr.fend();
892 std::nth_element(begin, begin + n / 2, end);
893 if (n % 2 == 1) {
894 return double(arr.fbegin()[n / 2]);
895 } else {
896 double a = double(arr.fbegin()[n / 2 - 1]);
897 double b = double(arr.fbegin()[n / 2]);
898 return (a + b) / 2;
899 }
900 }
901
914
924 template <class T, size_t... Dims>
926 double q,
928 size_t n = arr.fsize();
929 if (n == 0) return 0;
930 if (q < 0) q = 0;
931 if (q > 1) q = 1;
932 auto begin = arr.fbegin();
933 auto end = arr.fend();
934 switch (method) {
936 size_t idx = size_t(q * (n - 1) + 0.5);
937 if (idx >= n) idx = n - 1;
938 std::nth_element(begin, begin + idx, end);
939 return double(arr.fbegin()[idx]);
940 }
942 double pos = q * (n - 1);
943 size_t idx = size_t(pos);
944 double frac = pos - idx;
945 if (idx >= n - 1) {
946 std::nth_element(begin, begin + n - 1, end);
947 return double(arr.fbegin()[n - 1]);
948 }
949 std::nth_element(begin, begin + idx + 1, end);
950 double a = double(arr.fbegin()[idx]);
951 double b = double(arr.fbegin()[idx + 1]);
952 return a + (b - a) * frac;
953 }
955 double pos = q * (n - 1);
956 size_t idx = size_t(pos);
957 if (idx >= n - 1) {
958 std::nth_element(begin, begin + n - 1, end);
959 return double(arr.fbegin()[n - 1]);
960 }
961 std::nth_element(begin, begin + idx + 1, end);
962 double a = double(arr.fbegin()[idx]);
963 double b = double(arr.fbegin()[idx + 1]);
964 return (a + b) / 2;
965 }
967 size_t idx = size_t(q * (n - 1));
968 if (idx >= n) idx = n - 1;
969 std::nth_element(begin, begin + idx, end);
970 return double(arr.fbegin()[idx]);
971 }
973 size_t idx = size_t(q * (n - 1));
974 if (idx >= n - 1) return double(arr.fbegin()[n - 1]);
975 idx++;
976 std::nth_element(begin, begin + idx, end);
977 return double(arr.fbegin()[idx]);
978 }
980 double pos = (n - 1) * q;
981 size_t idx = size_t(pos);
982 double frac = pos - idx;
983 if (idx >= n - 1) {
984 return double(arr.fbegin()[n - 1]);
985 }
986 std::nth_element(begin, begin + idx + 1, end);
987 double a = double(arr.fbegin()[idx]);
988 double b = double(arr.fbegin()[idx + 1]);
989 return a + (b - a) * frac;
990 }
992 double pos = (n + 1) * q;
993 size_t idx = size_t(pos);
994 double frac = pos - idx;
995 if (idx < 1) idx = 1;
996 if (idx >= n) {
997 if (idx == n) {
998 std::nth_element(begin, begin + n - 1, end);
999 return double(arr.fbegin()[n - 1]);
1000 }
1001 return double(arr.fbegin()[n - 1]);
1002 }
1003 std::nth_element(begin, begin + idx, end);
1004 double a = double(arr.fbegin()[idx - 1]);
1005 double b = double(arr.fbegin()[idx]);
1006 return a + (b - a) * frac;
1007 }
1008 default:
1009 return quantile(arr, q, QuantileMethod::Nearest);
1010 }
1011 }
1012
1019 template <class T>
1021 return A[0][0] * A[1][1] - A[0][1] * A[1][0];
1022 }
1023
1030 template <class T>
1032 return A[0][0] * (A[1][1] * A[2][2] - A[1][2] * A[2][1])
1033 - A[0][1] * (A[1][0] * A[2][2] - A[1][2] * A[2][0])
1034 + A[0][2] * (A[1][0] * A[2][1] - A[1][1] * A[2][0]);
1035 }
1036
1043 template <class T>
1045 T d = det2x2(A);
1046 if (d == 0) return MultiArray<T, 2, 2>{};
1047 return MultiArray<T, 2, 2>{
1048 A[1][1] / d, -A[0][1] / d, -A[1][0] / d, A[0][0] / d};
1049 }
1050
1057 template <class T>
1059 T d = det3x3(A);
1060 if (d == 0) return MultiArray<T, 3, 3>{};
1062 B[0][0] = (A[1][1] * A[2][2] - A[1][2] * A[2][1]) / d;
1063 B[0][1] = (A[0][2] * A[2][1] - A[0][1] * A[2][2]) / d;
1064 B[0][2] = (A[0][1] * A[1][2] - A[0][2] * A[1][1]) / d;
1065 B[1][0] = (A[1][2] * A[2][0] - A[1][0] * A[2][2]) / d;
1066 B[1][1] = (A[0][0] * A[2][2] - A[0][2] * A[2][0]) / d;
1067 B[1][2] = (A[0][2] * A[1][0] - A[0][0] * A[1][2]) / d;
1068 B[2][0] = (A[1][0] * A[2][1] - A[1][1] * A[2][0]) / d;
1069 B[2][1] = (A[0][1] * A[2][0] - A[0][0] * A[2][1]) / d;
1070 B[2][2] = (A[0][0] * A[1][1] - A[0][1] * A[1][0]) / d;
1071 return B;
1072 }
1073
1081 template <class T, size_t... Dims>
1083 MultiArray<T, Dims...> result(T{});
1084 auto ri = result.fbegin();
1085 auto ai = arr.fbegin();
1086 while (ri != result.fend()) {
1087 *ri++ = T(1) / (T(1) + std::exp(-*ai++));
1088 }
1089 return result;
1090 }
1091
1099 template <class T, size_t... Dims>
1100 MultiArray<T, Dims...> relu(const MultiArray<T, Dims...> &arr) {
1101 MultiArray<T, Dims...> result;
1102 auto ri = result.fbegin();
1103 auto ai = arr.fbegin();
1104 while (ri != result.fend()) {
1105 *ri++ = *ai < 0 ? 0 : *ai;
1106 ++ai;
1107 }
1108 return result;
1109 }
1110
1118 template <class T, size_t... Dims>
1120 auto max_val = max(arr);
1121 MultiArray<T, Dims...> exp_arr;
1122 auto ri = exp_arr.fbegin();
1123 auto ai = arr.fbegin();
1124 while (ri != exp_arr.fend()) {
1125 *ri++ = std::exp(*ai++ - max_val);
1126 }
1127 T sum_exp = sum(exp_arr);
1128 MultiArray<T, Dims...> result;
1129 ri = result.fbegin();
1130 ai = exp_arr.fbegin();
1131 while (ri != result.fend()) {
1132 *ri++ = *ai++ / sum_exp;
1133 }
1134 return result;
1135 }
1136
1148 template <class T, size_t H, size_t W, size_t KH, size_t KW>
1149 MultiArray<T, H - KH + 1, W - KW + 1> convolve2d(
1150 const MultiArray<T, H, W> &image, const MultiArray<T, KH, KW> &kernel) {
1151 constexpr size_t OH = H - KH + 1;
1152 constexpr size_t OW = W - KW + 1;
1153 MultiArray<T, OH, OW> result(T{});
1154 for (size_t i = 0; i < OH; ++i) {
1155 for (size_t j = 0; j < OW; ++j) {
1156 T sum{};
1157 for (size_t ki = 0; ki < KH; ++ki) {
1158 for (size_t kj = 0; kj < KW; ++kj) {
1159 sum += image[i + ki][j + kj] * kernel[ki][kj];
1160 }
1161 }
1162 result[i][j] = sum;
1163 }
1164 }
1165 return result;
1166 }
1167
1177 template <class T, size_t M, size_t N>
1178 void print_matrix(std::ostream &os,
1179 const MultiArray<T, M, N> &A,
1180 const char *name = nullptr) {
1181 if (name) os << name << " = \n";
1182 for (size_t i = 0; i < M; ++i) {
1183 os << " [";
1184 for (size_t j = 0; j < N; ++j) {
1185 repr(A[i][j], os);
1186 if (j < N - 1) os << ", ";
1187 }
1188 os << "]\n";
1189 }
1190 }
1191
1198 template <class T, size_t N>
1199 MultiArray<std::complex<T>, N>
1200 fft(const MultiArray<std::complex<T>, N> &x) {
1201 static_assert((N & (N - 1)) == 0, "FFT length must be a power of 2");
1202 MultiArray<std::complex<T>, N> result = x;
1203 for (size_t i = 0; i < N; ++i) {
1204 size_t j = 0;
1205 for (size_t k = 1; k < N; k <<= 1) {
1206 if (i & k)
1207 j = (j << 1) | 1;
1208 else
1209 j <<= 1;
1210 }
1211 if (i < j) std::swap(result[i], result[j]);
1212 }
1213 for (size_t len = 2; len <= N; len <<= 1) {
1214 T angle = T(-2 * M_PI) / len;
1215 std::complex<T> wlen(std::cos(angle), std::sin(angle));
1216 for (size_t i = 0; i < N; i += len) {
1217 std::complex<T> w = 1;
1218 for (size_t j = 0; j < len / 2; ++j) {
1219 auto u = result[i + j];
1220 auto v = result[i + j + len / 2] * w;
1221 result[i + j] = u + v;
1222 result[i + j + len / 2] = u - v;
1223 w *= wlen;
1224 }
1225 }
1226 }
1227 return result;
1228 }
1229
1236 template <class T, size_t N>
1237 MultiArray<std::complex<T>, N>
1238 ifft(const MultiArray<std::complex<T>, N> &X) {
1240 for (size_t i = 0; i < N; ++i) conj_X[i] = std::conj(X[i]);
1241
1242 auto result = fft(conj_X);
1243
1244 for (size_t i = 0; i < N; ++i) {
1245 result[i] = std::conj(result[i]) / T(N);
1246 }
1247
1248 return result;
1249 }
1250
1257 template <class T, size_t N>
1260 for (size_t i = 0; i < N; ++i) cx[i] = std::complex<T>(x[i], 0);
1261 return fft(cx);
1262 }
1263
1270 template <class T, size_t N>
1271 MultiArray<T, N> irfft(const MultiArray<std::complex<T>, N> &X) {
1272 auto cx = ifft(X);
1273 MultiArray<T, N> result;
1274 for (size_t i = 0; i < N; ++i) result[i] = cx[i].real();
1275 return result;
1276 }
1277
1286 template <class T, size_t N>
1288 auto f = rfft(x);
1289 MultiArray<T, N / 2 + 1> mag(T{});
1290 const T norm = T(1) / T(N);
1291 for (size_t i = 0; i <= N / 2; ++i) mag[i] = std::abs(f[i]) * norm;
1292 return mag;
1293 }
1294
1302 template <class T, size_t N>
1304 auto mag = spectrum(x);
1305 for (size_t i = 0; i < mag.fsize(); ++i) {
1306 mag[i] = mag[i] * mag[i];
1307 }
1308 return mag;
1309 }
1310
1318 template <class T, size_t N>
1320 auto f = rfft(x);
1321 MultiArray<T, N / 2 + 1> phase;
1322 for (size_t i = 0; i <= N / 2; ++i) {
1323 phase[i] = std::arg(f[i]);
1324 }
1325 return phase;
1326 }
1327
1335 template <class T, size_t N>
1337 auto mag = spectrum(x);
1338 MultiArray<T, N / 2 + 1> logmag;
1339 for (size_t i = 0; i < mag.fsize(); ++i) {
1340 T val = mag[i];
1341 logmag[i] = (val > 0) ? T(20) * std::log10(val) : T(-100);
1342 }
1343 return logmag;
1344 }
1345
1355 template <class T, size_t M, size_t N>
1356 MultiArray<T, M>
1358 MultiArray<T, M> y(T{});
1359 for (size_t i = 0; i < M; ++i) {
1360 T sum{};
1361 for (size_t j = 0; j < N; ++j) {
1362 sum += A[i][j] * x[j];
1363 }
1364 y[i] = sum;
1365 }
1366 return y;
1367 }
1368
1378 template <class T, size_t M, size_t N>
1379 MultiArray<T, M, N>
1381 MultiArray<T, M, N> result(T{});
1382 for (size_t i = 0; i < M; ++i) {
1383 for (size_t j = 0; j < N; ++j) {
1384 result[i][j] = a[i] * b[j];
1385 }
1386 }
1387 return result;
1388 }
1389
1398 template <class T, size_t M, size_t N>
1400 double sum{};
1401 for (auto it = A.fbegin(); it != A.fend(); ++it) {
1402 double v = double(*it);
1403 sum += v * v;
1404 }
1405 return std::sqrt(sum);
1406 }
1407
1416 template <class T, size_t M, size_t N>
1418 T max_col{};
1419 for (size_t j = 0; j < N; ++j) {
1420 T col_sum{};
1421 for (size_t i = 0; i < M; ++i) {
1422 col_sum += std::abs(A[i][j]);
1423 }
1424 if (j == 0 || col_sum > max_col) max_col = col_sum;
1425 }
1426 return max_col;
1427 }
1428
1437 template <class T, size_t M, size_t N>
1439 T max_row{};
1440 for (size_t i = 0; i < M; ++i) {
1441 T row_sum{};
1442 for (size_t j = 0; j < N; ++j) {
1443 row_sum += std::abs(A[i][j]);
1444 }
1445 if (i == 0 || row_sum > max_row) max_row = row_sum;
1446 }
1447 return max_row;
1448 }
1449
1456 template <class T, size_t N>
1458 MultiArray<T, N> win;
1459 for (size_t i = 0; i < N; ++i) {
1460 win[i] = T(0.5) * (T(1) - std::cos(T(2 * M_PI) * i / (N - 1)));
1461 }
1462 return win;
1463 }
1464
1471 template <class T, size_t N>
1473 MultiArray<T, N> win;
1474 for (size_t i = 0; i < N; ++i) {
1475 win[i] = T(0.54) - T(0.46) * std::cos(T(2 * M_PI) * i / (N - 1));
1476 }
1477 return win;
1478 }
1479
1486 template <class T, size_t N>
1488 MultiArray<T, N> win;
1489 for (size_t i = 0; i < N; ++i) {
1490 T a = T(2 * M_PI) * i / (N - 1);
1491 win[i] = T(0.42) - T(0.5) * std::cos(a) + T(0.08) * std::cos(2 * a);
1492 }
1493 return win;
1494 }
1495
1503 template <class T, size_t N>
1505 MultiArray<T, N> result;
1506 size_t half = N / 2;
1507 for (size_t i = 0; i < half; ++i) {
1508 result[i] = x[i + half];
1509 result[i + half] = x[i];
1510 }
1511 return result;
1512 }
1513
1523 template <class T, size_t N, size_t M>
1524 MultiArray<T, N + M - 1>
1526 MultiArray<T, N + M - 1> result(T{});
1527 for (size_t i = 0; i < N; ++i) {
1528 for (size_t j = 0; j < M; ++j) {
1529 result[i + j] += a[i] * b[j];
1530 }
1531 }
1532 return result;
1533 }
1534 // end of matools group
1536}
编译期固定维度的多维数组(堆版本)。
Definition multiarray.h:461
MultiArray< T, 3, 3 > inv3x3(const MultiArray< T, 3, 3 > &A)
计算 3x3 矩阵的逆矩阵。
Definition matools.h:1058
MultiArray< T, M, K > matmul_simple(const MultiArray< T, M, N > &A, const MultiArray< T, N, K > &B)
矩阵乘法(二维),使用简单算法。
Definition matools.h:241
MultiArray< T, Dims... > ceil(const MultiArray< T, Dims... > &arr)
对数组每个元素向上取整。
Definition matools.h:790
MultiArray< T, Dims... > softmax(const MultiArray< T, Dims... > &arr)
计算 Softmax 激活函数。
Definition matools.h:1119
MultiArray< T, 3 > cross(const MultiArray< T, 3 > &a, const MultiArray< T, 3 > &b)
三维向量的叉积。
Definition matools.h:394
void print_stats(std::basic_ostream< CharT, Traits > &os, const MultiArray< T, Dims... > &arr, const std::string &name="")
打印数组的基本统计信息(和、均值、最小值、最大值、标准差)。
Definition matools.h:827
double manhattan(const MultiArray< T, N > &a, const MultiArray< T, N > &b)
计算两个向量的曼哈顿距离(L1 距离)。
Definition matools.h:190
void randomize(MultiArray< T, Dims... > &arr, T min=0, T max=100)
用均匀分布随机数填充数组。
Definition matools.h:450
MultiArray< T, Dims... > round(const MultiArray< T, Dims... > &arr)
对数组每个元素四舍五入。
Definition matools.h:806
double covariance(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
计算两个数组的协方差。
Definition matools.h:847
T trace(const MultiArray< T, N, N > &A)
计算方阵的迹(对角线元素之和)。
Definition matools.h:379
MultiArray< T, M, K > matmul_parallel(const MultiArray< T, M, N > &A, const MultiArray< T, N, K > &B)
并行矩阵乘法(二维),使用分块算法并行计算。
Definition matools.h:314
MultiArray< T, N, N > identity()
生成 N×N 的单位矩阵。
Definition matools.h:365
MultiArray< T, Dims... > abs(const MultiArray< T, Dims... > &arr)
计算数组中每个元素的绝对值。
Definition matools.h:432
double norm(const MultiArray< T, N > &a)
计算向量的欧几里得范数(L2 范数)。
Definition matools.h:126
T kth_smallest(MultiArray< T, Dims... > arr, size_t k)
查找第 k 小的元素(会修改数组顺序)。
Definition matools.h:508
MultiArray< T, Dims... > cos(const MultiArray< T, Dims... > &arr)
对数组每个元素应用 std::cos。
Definition matools.h:560
MultiArray< T, Dims... > atan(const MultiArray< T, Dims... > &arr)
对数组每个元素应用 std::atan。
Definition matools.h:624
MultiArray< T, N+M - 1 > cross_correlation(const MultiArray< T, N > &a, const MultiArray< T, M > &b)
互相关。
Definition matools.h:1525
MultiArray< T, N > hamming_window()
汉明窗。
Definition matools.h:1472
MultiArray< std::complex< T >, N > fft(const MultiArray< std::complex< T >, N > &x)
一维 FFT(Cooley-Tukey 算法)。
Definition matools.h:1200
MultiArray< T, Dims... > asin(const MultiArray< T, Dims... > &arr)
对数组每个元素应用 std::asin。
Definition matools.h:592
MultiArray< T, Dims... > clamp(const MultiArray< T, Dims... > &arr, T low, T high)
将数组每个元素限制在 [low, high] 范围内。
Definition matools.h:412
T det2x2(const MultiArray< T, 2, 2 > &A)
计算 2x2 矩阵的行列式。
Definition matools.h:1020
MultiArray< T, M, K > matmul(const MultiArray< T, M, N > &A, const MultiArray< T, N, K > &B)
矩阵乘法(二维),根据 BLOCK 大小选择简单算法或分块算法。
Definition matools.h:295
MultiArray< T, Dims... > pow(const MultiArray< T, Dims... > &arr, T exponent)
对数组每个元素取幂(常数指数)。
Definition matools.h:738
MultiArray< T, M > matvec(const MultiArray< T, M, N > &A, const MultiArray< T, N > &x)
矩阵-向量乘法。
Definition matools.h:1357
MultiArray< T, N > hann_window()
窗函数。
Definition matools.h:1457
MultiArray< T, Dims... > log(const MultiArray< T, Dims... > &arr)
对数组每个元素应用 std::log(自然对数)。
Definition matools.h:705
MultiArray< T, Dims... > relu(const MultiArray< T, Dims... > &arr)
计算 ReLU 激活函数。
Definition matools.h:1100
MultiArray< T, Dims... > tanh(const MultiArray< T, Dims... > &arr)
对数组每个元素应用 std::tanh。
Definition matools.h:672
MultiArray< T, N > fftshift(const MultiArray< T, N > &x)
FFT 移位。
Definition matools.h:1504
QuantileMethod
Definition matools.h:905
double median(MultiArray< T, Dims... > arr)
计算数组的中位数。
Definition matools.h:888
T product(const MultiArray< T, Dims... > &arr)
计算所有元素的乘积。
Definition matools.h:494
MultiArray< T, N/2+1 > phase_spectrum(const MultiArray< T, N > &x)
相位谱(弧度)。
Definition matools.h:1319
T det3x3(const MultiArray< T, 3, 3 > &A)
计算 3x3 矩阵的行列式。
Definition matools.h:1031
MultiArray< T, N > blackman_window()
布莱克曼窗。
Definition matools.h:1487
MultiArray< T, N+K - 1 > convolve1d(const MultiArray< T, N > &signal, const MultiArray< T, K > &kernel)
一维卷积。
Definition matools.h:525
MultiArray< T, H - KH+1, W - KW+1 > convolve2d(const MultiArray< T, H, W > &image, const MultiArray< T, KH, KW > &kernel)
执行二维卷积操作。
Definition matools.h:1149
#define CONSOLE_MATMUL_BLOCK_SIZE
Definition matools.h:200
MultiArray< T, M, K > matmul_impl(const MultiArray< T, M, N > &A, const MultiArray< T, N, K > &B, std::true_type)
矩阵乘法(二维) std::true_type 特化,使用分块算法。
Definition matools.h:260
MultiArray< T, Dims... > tan(const MultiArray< T, Dims... > &arr)
对数组每个元素应用 std::tan。
Definition matools.h:576
MultiArray< T, N/2+1 > log_spectrum(const MultiArray< T, N > &x)
对数频谱(分贝)。
Definition matools.h:1336
MultiArray< T, N > irfft(const MultiArray< std::complex< T >, N > &X)
实数 IFFT(输入为复数频域,输出为实数时域)。
Definition matools.h:1271
MultiArray< T, Dims... > sigmoid(const MultiArray< T, Dims... > &arr)
计算 Sigmoid 激活函数。
Definition matools.h:1082
MultiArray< T, N/2+1 > spectrum(const MultiArray< T, N > &x)
频谱(幅值谱),归一化到真实幅度。
Definition matools.h:1287
double euclidean(const MultiArray< T, N > &a, const MultiArray< T, N > &b)
计算两个向量的欧几里得距离。
Definition matools.h:170
MultiArray< T, Dims... > cosh(const MultiArray< T, Dims... > &arr)
对数组每个元素应用 std::cosh。
Definition matools.h:656
MultiArray< T, Dims... > sinh(const MultiArray< T, Dims... > &arr)
对数组每个元素应用 std::sinh。
Definition matools.h:640
double correlation(const MultiArray< T, Dims... > &a, const MultiArray< T, Dims... > &b)
计算两个数组的相关系数。
Definition matools.h:871
double mean(const MultiArray< T, Dims... > &arr)
计算 MultiArray 中所有元素的算术平均值。
Definition matools.h:66
MultiArray< T, N/2+1 > power_spectrum(const MultiArray< T, N > &x)
功率谱(幅值平方)。
Definition matools.h:1303
MultiArray< T, N, M > transpose(const MultiArray< T, M, N > &A)
矩阵转置。
Definition matools.h:351
MultiArray< std::complex< T >, N > rfft(const MultiArray< T, N > &x)
实数 FFT(输入为实数,输出为复数频域)。
Definition matools.h:1258
MultiArray< T, Dims... > sin(const MultiArray< T, Dims... > &arr)
对数组每个元素应用 std::sin。
Definition matools.h:544
MultiArray< T, Dims... > floor(const MultiArray< T, Dims... > &arr)
对数组每个元素向下取整。
Definition matools.h:774
MultiArray< T, Dims... > log10(const MultiArray< T, Dims... > &arr)
对数组每个元素应用 std::log10(常用对数)。
Definition matools.h:721
T row_norm(const MultiArray< T, M, N > &A)
行范数(最大行和范数)。
Definition matools.h:1438
void linspace(MultiArray< T, Dims... > &arr, T start, T end)
用线性等间距值填充数组。
Definition matools.h:479
double quantile(MultiArray< T, Dims... > arr, double q, QuantileMethod method=QuantileMethod::Nearest)
计算数组的分位数。
Definition matools.h:925
T dot(const MultiArray< T, N > &a, const MultiArray< T, N > &b)
计算两个一维向量的点积。
Definition matools.h:114
MultiArray< T, M, K > matmul_blocked(const MultiArray< T, M, N > &A, const MultiArray< T, N, K > &B)
矩阵乘法(二维),使用分块算法。
Definition matools.h:215
MultiArray< T, N > normalize(const MultiArray< T, N > &a)
将向量归一化为单位向量。
Definition matools.h:151
void print_matrix(std::ostream &os, const MultiArray< T, M, N > &A, const char *name=nullptr)
打印矩阵。
Definition matools.h:1178
MultiArray< T, Dims... > acos(const MultiArray< T, Dims... > &arr)
对数组每个元素应用 std::acos。
Definition matools.h:608
double variance(const MultiArray< T, Dims... > &arr, bool sample=true)
计算方差。
Definition matools.h:80
double stddev(const MultiArray< T, Dims... > &arr, bool sample=true)
计算标准差。
Definition matools.h:100
double cosine(const MultiArray< T, N > &a, const MultiArray< T, N > &b)
计算两个向量的余弦相似度。
Definition matools.h:139
MultiArray< T, Dims... > exp(const MultiArray< T, Dims... > &arr)
对数组每个元素应用 std::exp。
Definition matools.h:689
T column_norm(const MultiArray< T, M, N > &A)
列范数(最大列和范数)。
Definition matools.h:1417
MultiArray< T, 2, 2 > inv2x2(const MultiArray< T, 2, 2 > &A)
计算 2x2 矩阵的逆矩阵。
Definition matools.h:1044
MultiArray< T, M, N > outer(const MultiArray< T, M > &a, const MultiArray< T, N > &b)
外积。
Definition matools.h:1380
MultiArray< std::complex< T >, N > ifft(const MultiArray< std::complex< T >, N > &X)
一维 IFFT(逆快速傅里叶变换)。
Definition matools.h:1238
double frobenius_norm(const MultiArray< T, M, N > &A)
矩阵范数(弗罗贝尼乌斯范数)。
Definition matools.h:1399
void randomize_normal(MultiArray< T, Dims... > &arr, T mean=0, T stddev=1)
用正态分布随机数填充数组。
Definition matools.h:465
@ ExcelExc
PERCENTILE.EXC.
Definition matools.h:912
@ Upper
取上界
Definition matools.h:910
@ Linear
线性插值(NumPy 默认)
Definition matools.h:907
@ Nearest
取最近的元素(默认)
Definition matools.h:906
@ ExcelInc
PERCENTILE.INC.
Definition matools.h:911
@ Midpoint
取两个值的中点
Definition matools.h:908
@ Lower
取下界
Definition matools.h:909
std::vector< typename C::value_type > sample(const C &c, size_t size, bool replace=false, std::mt19937 &gen=thread_rng())
从容器中随机抽取指定数量的元素(有放回或无放回)。
Definition random.h:421
std::mt19937 & thread_rng()
获取一个全局的、以当前时间戳为种子的 Mersenne Twister 随机数引擎。
Definition random.h:55
std::enable_if< is_string< typenamestd::decay< T >::type >::value >::type repr(T &&value, std::basic_ostream< CharT, Traits > &os=std::cout)
输出字符串类型(std::string, const char* 等)的表示,带双引号。
Definition repr.h:97
typename uniform_distribution_impl< T >::type uniform_distribution_t
取得对印类型所对应的均匀分布。
Definition sfinae.h:328
#define M_PI
Definition matools.h:47
提供编译期维度固定的多维数组容器 MultiArray,支持任意维度和元素级算术/逻辑/位运算。
auto submit(F &&f, Args &&...args) -> std::future< decltype(std::forward< F >(f)(std::forward< Args >(args)...))>
提交任务到线程池。
Definition pool.h:327
本库所有组件所在的顶层命名空间。
T min(const MultiArray< T, Dims... > &a)
求最小值。
Definition multiarray.h:1676
T max(const MultiArray< T, Dims... > &a)
求最大值。
Definition multiarray.h:1685
@ X
Definition kb.h:103
@ C
Definition kb.h:82
@ W
Definition kb.h:102
@ M
Definition kb.h:92
@ A
Definition kb.h:80
@ N
Definition kb.h:93
@ B
Definition kb.h:81
@ K
Definition kb.h:90
@ T
Definition kb.h:99
T sum(const MultiArray< T, Dims... > &a)
求和所有元素。
Definition multiarray.h:1665
简单的线程池实现,模仿了 Python 的 concurrent.futures.ThreadPoolExecutor 接口。
提供随机数生成、随机选择、随机打乱等实用工具。
提供编译期类型特征检测(SFINAE 工具), 用于判断容器、可调用对象、迭代器、下标访问、字符串、可打印类型、字符类型等。