2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
52#include <unordered_map>
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
82
83
84
85
86
87
90
91
95
96
100
101
105
106
110
111
115
116
122template <ComponentType T>
124template <ComponentType T>
126template <ComponentType T>
129template <ComponentType T>
131template <ComponentType T>
133template <ComponentType T>
135template <ComponentType T>
137template <ComponentType T>
139template <ComponentType T>
140std::ostream& operator<<(
std::ostream& os,
const Matrix<T>& rhs);
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173template <ComponentType T>
179 template <ReliablyComparableType U>
181 friend std::ostream& operator<< <>(
std::ostream& os,
const Matrix& rhs);
187
188
197
198
199
200
201 Matrix(size_t m, size_t n,
const T& l);
204
205
206
207
208 constexpr Matrix(size_t m, size_t n, std::initializer_list<T> l);
211
212
213
214
215 Matrix(std::initializer_list<std::initializer_list<T>> l);
224 transposed(other.transposed),
232 transposed(other.transposed),
237
238
239
240
241
242
243
244
245 template <FiniteFieldType S>
250
251
252
253
254
255
256
257
258
259
266
267
280
281
296
297
300
301
302
303
307
308
309
310
314
315
316
317
324
325
326
327
328
329
335
336
339
340
341
342
343
344
345
346
347
348
349
355
356
359
360
361
362
366
367
368
369
373
374
375
376
377 constexpr bool is_empty()
const noexcept {
return m == 0 || n == 0; }
380
381
382
383
384
385
386
389 const bool b = std::ranges::all_of(data, [](
const T& v) {
return v == T(0); });
395
396
397
398
401 return std::ranges::all_of(data, [](
const T& v) {
return v == T(0); });
412
413
414
415
416
417
418
423
424
425
426
434
435
436
437
438
439
443
444
445
446
447
448
449
450
451
456
457
458
459
460
461
466
467
468
469
477
478
479
480
481
482
483
484
485
490
491
492
493
494
495
496
497
502
503
504
505
506
507
512
513
514
515
525
526
529
530
531
532
533
534
535
536
537
538 template <
typename U>
543
544
545
546
547
548
549
550
554
555
556
557
558
559
560
564
565
566
567
568
569
570
574
575
576
577
578
579
580
581
582
583
587
588
589
590
591
592
593
594
595
599
600
601
602
603
604
605
609
610
611
612
613
614
615
619
620
621
622
623
624
625
629
630
631
632
633
634
635
639
640
641
642
643
644
645
646
650
651
652
653
654
655
656
657
661
662
663
664
665
666
667
668
672
673
674
675
676
677
678
679
683
684
685
686
687
688
689
690
691
695
696
697
698
699
700
701
702
703
707
708
709
710
711
712
713
714
716 if (i >= m || j >= m)
717 throw std::invalid_argument(
"trying to add row to other row, at least one of them is non-existent");
718 return add_scaled_row(T(1), i, j);
722
723
724
725
726
727
728
729
731 if (i >= n || j >= n)
732 throw std::invalid_argument(
"trying to add column to other column, at least one of them is non-existent");
734 add_scaled_row(T(1), i, j);
740
741
742
743
744
745
746
750
751
752
753
754
755
756
760
761
762
763
764
765
766
770
771
772
773
774
775
776
779#ifdef CECCO_ERASURE_SUPPORT
782
783
784
785
786
787
788
789
790
791
792
793
794
795
800
801
802
803
804
805
806
807
812
813
814
815
816
817
818
819
820
825
826
827
828
829
830
831
839
840
841
842
843
844
845
850
851
852
853
854
855
856
864
865
866
867
868
869
870
871
872
877
878
879
880
881
882
883
891
892
893
894
895
896
897
902
903
904
905
906
907
908
920
921
924
925
926
927
931
932
933
934
938
939
940
941
942
943
944
948
949
950
951
952
953
957
958
959
960
961
962
963
964
965
970
971
972
973
974
975
976
977
982
983
984
985
986
987
988
989
996
997
1000
1001
1002
1003
1004
1005
1006
1007 template <FiniteFieldType S>
1012
1013
1014
1015
1019
1020
1021
1022
1023
1024
1025
1026
1027
1035 std::vector<T> data;
1043 bool transposed =
false;
1049 enum CacheIds { Rank = 0, Weight = 1 };
1052 size_t calculate_weight()
const
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067 template <
bool this_transposed,
bool rhs_transposed>
1068 static void multiply_kernel(
const T* this_data,
const T* rhs_data, T* res_data, size_t M, size_t K, size_t N,
1070 for (size_t ii = 0; ii < M; ii += BS) {
1071 const size_t imax = std::min(ii + BS, M);
1072 for (size_t kk = 0; kk < K; kk += BS) {
1073 const size_t kmax = std::min(kk + BS, K);
1074 for (size_t jj = 0; jj < N; jj += BS) {
1075 const size_t jmax = std::min(jj + BS, N);
1076 for (size_t i = ii; i < imax; ++i) {
1077 for (size_t k = kk; k < kmax; ++k) {
1079 const size_t this_idx = this_transposed ? (i + k * M) : (i * K + k);
1080 const T aik = this_data[this_idx];
1081 const size_t res_row_offset = i * N;
1082 for (size_t j = jj; j < jmax; ++j) {
1084 const size_t rhs_idx = rhs_transposed ? (k + j * K) : (k * N + j);
1085 res_data[res_row_offset + j] += aik * rhs_data[rhs_idx];
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105 template <
bool transposed>
1106 static void eliminate_row_kernel(T* data, size_t m, size_t n, size_t target_row, size_t pivot_row,
1107 size_t start_col,
const T& f) {
1108 if constexpr (!transposed) {
1110 T* target_data = data + target_row * n;
1111 const T* pivot_data = data + pivot_row * n;
1112 for (size_t j = start_col; j < n; ++j) {
1113 target_data[j] -= f * pivot_data[j];
1117 for (size_t j = start_col; j < n; ++j) {
1118 data[target_row + j * m] -= f * data[pivot_row + j * m];
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133 template <
bool transposed>
1134 static size_t ref_elimination_kernel(T* data, size_t m, size_t n, size_t h, size_t k) {
1135 while (h < m && k < n) {
1139 for (size_t row = h; row < m; ++row) {
1140 const size_t idx = transposed ? (row + k * m) : (row * n + k);
1141 if (data[idx] != T(0)) {
1151 if constexpr (!transposed)
1152 std::swap_ranges(data + h * n, data + (h + 1) * n, data + p * n);
1154 for (size_t j = 0; j < n; ++j)
std::swap(data[h + j * m], data[p + j * m]);
1156 const size_t pivot_idx = transposed ? (h + k * m) : (h * n + k);
1157 const T pivot = data[pivot_idx];
1160 const T inv = T(1) / pivot;
1161 if constexpr (!transposed) {
1162 for (size_t j = k; j < n; ++j) data[h * n + j] *= inv;
1164 for (size_t j = k; j < n; ++j) data[h + j * m] *= inv;
1168 for (size_t i = h + 1; i < m; ++i) {
1169 const size_t f_idx = transposed ? (i + k * m) : (i * n + k);
1170 const T f = data[f_idx];
1172 if (f != T(0)) eliminate_row_kernel<transposed>(data, m, n, i, h, k, f);
1183
1184
1185
1186
1187
1188
1189
1190 template <
bool transposed>
1191 void rref_backward_elimination_kernel(T* data, size_t m, size_t n, size_t r) {
1192 for (size_t i = 0; i < r; ++i) {
1193 const size_t pivot_row = r - 1 - i;
1196 size_t pivot_col = 0;
1197 while (pivot_col < n) {
1198 const size_t pivot_idx = transposed ? (pivot_row + pivot_col * m) : (pivot_row * n + pivot_col);
1199 if (data[pivot_idx] != T(0)) {
1205 if (pivot_col < n) {
1207 for (size_t row = 0; row < pivot_row; ++row) {
1208 const size_t f_idx = transposed ? (row + pivot_col * m) : (row * n + pivot_col);
1209 const T f = data[f_idx];
1211 if (f != T(0)) eliminate_row_kernel<transposed>(data, m, n, row, pivot_row, pivot_col, f);
1218
1219
1220 size_t calculate_rank()
const
1226template <ComponentType T>
1229 std::fill(data.begin(), data.end(), l);
1231 cache.
template set<Rank>(1);
1233 cache.
template set<Rank>(0);
1236template <ComponentType T>
1239 if (l.size() != m * n) {
1240 throw std::invalid_argument(
1241 "number of elements in initializer list does not correspond to number of rows and columns specified");
1245template <ComponentType T>
1248 for (
auto it = l.begin(); it != l.end(); ++it) {
1249 if (it->size() > n) n = it->size();
1255 for (
const auto& row : l) {
1257 for (
const auto& val : row) set_component(i, j++, val);
1262template <ComponentType T>
1265 std::copy(v.data.begin(), v.data.end(), data.begin());
1266 cache.
template set<Rank>(v.is_zero() ? 0 : 1);
1270template <FiniteFieldType S>
1289template <ComponentType T>
1299 if (
tok[0] ==
'#') {
1346#ifdef CECCO_ERASURE_SUPPORT
1356template <ComponentType T>
1358 if (
this == &rhs)
return *
this;
1362 transposed = rhs.transposed;
1368template <ComponentType T>
1370 data = std::move(rhs.data);
1373 transposed = rhs.transposed;
1375 cache = std::move(rhs.cache);
1385 [&](
const S&
e) {
return T(
e); });
1394template <ComponentType T>
1397 auto rank_backup = res.cache.
template get<Rank>();
1399 std::ranges::for_each(res.data, [](T& x) { x = -x; });
1405 for (size_t mu = 0; mu < m; ++mu) res.data[mu * n + mu] = -res.data[mu * n + mu];
1406 if constexpr (FiniteFieldType<T>) {
1407 if (T::get_characteristic() != 2 && type == details::Identity) res.type =
details::Diagonal;
1412 if (rank_backup) res.cache.
template set<Rank>(*rank_backup);
1416template <ComponentType T>
1418 auto rank_backup = cache.
template get<Rank>();
1420 std::ranges::for_each(data, [](T& x) { x = -x; });
1427 for (size_t mu = 0; mu < m; ++mu) data[mu * n + mu] = -data[mu * n + mu];
1428 if constexpr (FiniteFieldType<T>) {
1429 if (T::get_characteristic() != 2 && type == details::Identity) type =
details::Diagonal;
1434 if (rank_backup) cache.
template set<Rank>(*rank_backup);
1435 return std::move(*
this);
1438template <ComponentType T>
1440 if (m != rhs.m || n != rhs.n)
1441 throw std::invalid_argument(
1442 "trying to add two matrices of different "
1452 for (size_t mu = 0; mu < m; ++mu) data[mu * n + mu] += rhs.data[mu * n + mu];
1455 if (!transposed && !rhs.transposed) {
1456 std::transform(data.begin(), data.end(), rhs.data.begin(), data.begin(), std::plus<T>{});
1460 for (size_t mu = 0; mu < m; ++mu)
1461 for (size_t nu = 0; nu < n; ++nu) set_component(mu, nu, (*
this)(mu, nu) + rhs(mu, nu));
1464 if (std::all_of(data.cbegin(), data.cend(), [](
const T& x) {
return x == T(0); })) {
1471template <ComponentType T>
1473 if (m != rhs.m || n != rhs.n)
1474 throw std::invalid_argument(
1475 "trying to subtract two matrices of different "
1482template <ComponentType T>
1485 throw std::invalid_argument(
1486 "trying to multiply two matrices "
1487 "with incompatible dimensions");
1489 *
this = Matrix(m, rhs.n);
1495 for (size_t mu = 0; mu < m; ++mu) data[mu * n + mu] *= rhs.data[mu * n + mu];
1498 for (size_t mu = 0; mu < m; ++mu) {
1499 auto s = (*
this)(mu, mu);
1500 for (size_t nu = 0; nu < rhs.n; ++nu) res.set_component(mu, nu, res(mu, nu) * s);
1502 *
this =
std::move(res);
1504 for (size_t nu = 0; nu < n; ++nu) {
1505 const auto& s = rhs(nu, nu);
1506 for (size_t mu = 0; mu < m; ++mu) set_component(mu, nu, (*
this)(mu, nu) * s);
1509 const size_t M = get_m();
1510 const size_t K = get_n();
1511 const size_t N = rhs.get_n();
1512 Matrix<T> res(M, N, T(0));
1514 const T* this_data =
this->data.data();
1515 const T* rhs_data = rhs.data.data();
1516 T* res_data = res.data.data();
1519 constexpr size_t BS = 64;
1522 if (!
this->transposed && !rhs.transposed) {
1523 multiply_kernel<
false,
false>(this_data, rhs_data, res_data, M, K, N, BS);
1524 }
else if (
this->transposed && !rhs.transposed) {
1525 multiply_kernel<
true,
false>(this_data, rhs_data, res_data, M, K, N, BS);
1526 }
else if (!
this->transposed && rhs.transposed) {
1527 multiply_kernel<
false,
true>(this_data, rhs_data, res_data, M, K, N, BS);
1529 multiply_kernel<
true,
true>(this_data, rhs_data, res_data, M, K, N, BS);
1532 *
this =
std::move(res);
1534 if (
std::all_of(
this->data.cbegin(),
this->data.cend(), [](
const T& elem) {
return elem == T(0); })) {
1541template <ComponentType T>
1544 *
this = Matrix(m, n);
1548 std::ranges::for_each(data, [&s](T& x) { x *= s; });
1551 for (size_t mu = 0; mu < m; ++mu) data[mu * n + mu] *= s;
1557template <ComponentType T>
1559 if (s == T(0))
throw std::invalid_argument(
"trying to divide components of matrix by zero");
1564template <ComponentType T>
1566 if constexpr (FieldType<T>) {
1567 std::ranges::for_each(data, std::mem_fn(&T::randomize));
1568 }
else if constexpr (std::same_as<T,
double>) {
1569 std::uniform_real_distribution<
double> dist(-1.0, 1.0);
1570 std::ranges::for_each(data, [&](
double& val) { val = dist(gen()); });
1571 }
else if constexpr (std::same_as<T, std::complex<
double>>) {
1572 std::uniform_real_distribution<
double> dist(-1.0, 1.0);
1573 std::ranges::for_each(data,
1574 [&](std::complex<
double>& val) { val = std::complex<
double>(dist(gen()), dist(gen())); });
1575 }
else if constexpr (SignedIntType<T>) {
1576 std::uniform_int_distribution<
long long> dist(-100, 100);
1577 std::ranges::for_each(data, [&](T& val) { val = T(dist(gen())); });
1584template <ComponentType T>
1585size_t
Matrix<T>::calculate_weight()
const
1588 if (
m == 0 ||
n == 0)
return 0;
1594#ifdef CECCO_ERASURE_SUPPORT
1599 throw std::
logic_error(
"calculate_weight(): unhandled matrix type");
1602template <ComponentType T>
1609template <ComponentType T>
1611 if (m != n)
throw std::invalid_argument(
"trying to extract diagonal of non-square matrix");
1613 for (size_t i = 0; i < n; ++i) res.data[i] = (*
this)(i, i);
1617template <ComponentType T>
1621 if (
m !=
n)
throw std::
invalid_argument(
"trying to calculate characteristic polynomial of non-square matrix");
1622 if (
m == 0)
throw std::
invalid_argument(
"trying to calculate characteristic polynomial of empty matrix");
1632 T a = (*
this)(
i,
i);
1638 }
else if (
m -
i == 2) {
1675 if (
m % 2)
res *=
T(-1);
1689 throw std::
logic_error(
"characteristic_polynomial(): unhandled matrix type");
1692template <ComponentType T>
1745template <ComponentType T>
1751 if (
m == 1)
return ((*
this))(0, 0);
1755 return (
m % 2 == 0) ?
c : -
c;
1766 if ((*
this)(
i,
i) ==
T(0))
return T(0);
1776template <ComponentType T>
1789template <ComponentType T>
1795 throw std::
out_of_range(
"row space too big (more than 10^10 elements) to compute all elements");
1817template <
typename U>
1837 if (
i ==
j &&
m ==
n)
1903 if (
i +
h >
m ||
j +
w >
n)
1905 "trying to extract a submatrix with incompatible "
1944 "trying to replace submatrix with "
1945 "matrix of incompatible dimensions");
1963 "trying to horizontally join two "
1964 "matrices of incompatible dimensions");
1980 "trying to vertically join two "
1981 "matrices of incompatible dimensions");
2048 if (
i ==
j)
return *
this;
2055 const auto temp = (*
this)(
i,
nu);
2077 if (
s ==
T(1))
return *
this;
2107 if (
i >=
m ||
j >=
m)
2108 throw std::
invalid_argument(
"trying to add scaled row to other row, at least one of them is non-existent");
2109 if (
s ==
T(0))
return *
this;
2139 if (
v.
empty())
return *
this;
2161 if (
v.
empty())
return *
this;
2181#ifdef CECCO_ERASURE_SUPPORT
2219 if (
v.
empty())
return *
this;
2241 if (
v.
empty())
return *
this;
2400 if ((*
this)(
i,
i) ==
T(0))
2440 if (
r ==
m &&
m ==
n)
2479 if ((*
this)(
i,
i) ==
T(0)) {
2524 if (
m !=
n)
throw std::
invalid_argument(
"trying to invert a non-square details::Vandermonde matrix");
2529 if (
k ==
i)
continue;
2539 if ((*
this)(
mu,
mu) ==
T(0))
2541 "trying to invert a non-invertible matrix/a diagonal matrix with at least one zero on the "
2558 throw std::
invalid_argument(
"trying to create superfield vector from subfield matrix, wrong number of rows");
2600#ifdef CECCO_ERASURE_SUPPORT
2616 file <<
std::
setw(3) <<
static_cast<
int>(
r) <<
" " <<
std::
setw(3) <<
static_cast<
int>(
g) <<
" "
2617 <<
std::
setw(3) <<
static_cast<
int>(
b) <<
" ";
2638
2639
2670
2671
2702
2703
2720
2721
2734
2735
2752
2753
2770
2771
3093#ifdef CECCO_ERASURE_SUPPORT
3322
3323
3324
3325
3326
3327
3328
3335 }
else if (
lhs.
m == 1) {
3337 }
else if (
lhs.
n == 1) {
3371
3372
3373
3374
3381
3382
3383
3384
3385
3386
3390 os <<
" (empty matrix)";
3401 os <<
" " << (
rhs.
m == 1 ?
"(" :
"⌈");
3407 os << (
rhs.
m == 1 ?
")" :
"⌉");
3433
3434
3437
3438
3439
3440
3441
3442
3449
3450
3451
3452
3453
3463
3464
3465
3466
3467
3468
3469
3478 throw std::
invalid_argument(
"Trying to construct permutation matrix from a list that is not a permutation");
3492
3493
3494
3495
3496
3505
3506
3507
3508
3509
3520
3521
3522
3523
3524
3525
3526
3527
3528
3533 "vector for constructing m x n details::Toeplitz matrix must have "
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3568
3569
3570
3571
3572
3573
3574
3575
3581 "vector for constructing details::Vandermonde matrix must have "
3582 "at least one element");
3583 if (
m == 0)
throw std::
invalid_argument(
"trying to construct details::Vandermonde matrix with zero rows");
3586 "vector for constructing details::Vandermonde matrix must have pairwise distinct elements");
3607
3608
3609
3610
3611
3620
3621
3622
3623
3624
3631
3632
3633
3634
3635
3636
3637
3638
3639
Dense m × n matrix over a CECCO::ComponentType.
Matrix(std::initializer_list< std::initializer_list< T > > l)
From nested initializer lists, e.g. {{1, 2, 3}, {4, 5, 6}}.
Matrix(size_t m, size_t n, const T &l)
m × n matrix with every component equal to l
constexpr bool is_empty() const noexcept
Check if matrix is empty.
constexpr bool is_zero()
Check if the matrix is zero, caching the result via the type tag.
Matrix< T > & swap_columns(size_t i, size_t j)
Swap columns i and j.
constexpr Matrix operator+() const &
Unary + (lvalue): returns a copy.
Matrix< T > & diagonal_join(const Matrix &other)
Block-diagonal join: this in the upper-left, other in the lower-right.
size_t wH() const
Hamming weight: number of non-zero, non-erased components; cached on first call.
std::vector< Vector< T > > span() const
Alias for rowspace.
Matrix< T > get_submatrix(size_t i, size_t j, size_t h, size_t w) const
Extract submatrix from region [i, i+h) × [j, j+w).
constexpr Matrix & operator=(const Matrix &rhs)
constexpr Matrix & operator=(Matrix &&rhs) noexcept
friend constexpr Matrix< T > ToeplitzMatrix(const Vector< T > &v, size_t m, size_t n)
m × n Toeplitz matrix from its diagonal entries (tag details::Toeplitz)
Matrix< T > & set_component(size_t i, size_t j, U &&c)
bool is_invertible() const
Check if matrix is invertible.
Matrix(const std::string &filename)
Read from a PPM (P3) image file using the 64-entry colormap of export_as_ppm.
Vector< T > to_vector() const
Flatten in row-major order.
Matrix< T > basis_of_kernel() const
Alias for basis_of_nullspace.
Matrix< T > & add_scaled_column(const T &s, size_t i, size_t j)
col[j] ← col[j] + s · col[i]
const T & operator()(size_t i, size_t j) const
Access component (i, j) (read-only).
Matrix & operator-=(const Matrix &rhs)
Component-wise subtraction this(i, j) -= rhs(i, j).
std::vector< Vector< T > > rowspace() const
Enumerate every vector in the row space.
constexpr size_t get_m() const noexcept
Get the number of rows.
constexpr Matrix operator-() const &
Unary − (lvalue): returns a new matrix with each component negated.
constexpr Matrix() noexcept=default
Default constructor: empty matrix.
constexpr bool is_zero() const
Check if the matrix is zero (no caching).
Matrix< T > & reverse_columns()
Reverse the column order.
constexpr Matrix(const Matrix &other)
void export_as_ppm(const std::string &filename) const
Export the matrix as a PPM (P3) image.
Matrix< T > & set_submatrix(size_t i, size_t j, const Matrix &N)
Overwrite the region starting at (i, j) with N.
Matrix & operator*=(const Matrix &rhs)
Matrix multiplication *this = *this · rhs.
Matrix< T > & horizontal_join(const Matrix &other)
Concatenate other to the right (column-wise).
constexpr size_t get_n() const noexcept
Get the number of columns.
friend constexpr bool operator==(const Matrix< U > &lhs, const Matrix< U > &rhs)
constexpr Matrix(size_t m, size_t n, std::initializer_list< T > l)
m × n matrix from a flat initializer list (row-major)
constexpr Matrix operator-() &&
Unary − (rvalue): negates components in place.
Vector< T > get_col(size_t j) const
Extract column j as a (row) vector.
Polynomial< T > characteristic_polynomial() const
Characteristic polynomial det(λI − A).
Matrix< T > & rref(size_t *rank=nullptr)
Reduced row echelon form (RREF).
Matrix(const Vector< T > &v)
1 × n row matrix from a Vector<T>
constexpr Matrix(size_t m, size_t n)
m × n zero matrix (tag details::Zero)
Matrix< T > & scale_row(const T &s, size_t i)
row[i] ← s · row[i]
friend constexpr Matrix< T > DiagonalMatrix(const Vector< T > &v)
Diagonal matrix with diagonal v (tag details::Diagonal).
friend constexpr Matrix< T > IdentityMatrix(size_t m)
m × m identity matrix I_m (tag details::Identity)
constexpr Matrix< T > & transpose()
Transpose in place.
constexpr Matrix(Matrix &&other) noexcept
Matrix< T > & delete_rows(const std::vector< size_t > &v)
Delete the rows whose indices appear in v.
constexpr Matrix(const Matrix< S > &other)
Cross-field conversion between two finite fields of the same characteristic.
Matrix< T > & add_scaled_row(const T &s, size_t i, size_t j)
row[j] ← row[j] + s · row[i]
Matrix< T > & add_row(size_t i, size_t j)
row[j] ← row[j] + row[i]
constexpr Matrix operator+() &&noexcept
Unary + (rvalue): returns the rvalue itself.
Matrix< T > & reverse_rows()
Reverse the row order.
Matrix< T > & scale_column(const T &s, size_t i)
col[i] ← s · col[i]
Matrix< T > basis_of_nullspace() const
Basis of the nullspace (right kernel).
Matrix & operator/=(const T &s)
Divide every component by the scalar s.
Matrix< T > & ref(size_t *rank=nullptr)
Row echelon form (REF), with a binary-field fast path.
Matrix & operator+=(const Matrix &rhs)
Component-wise addition this(i, j) += rhs(i, j).
Matrix< T > & Kronecker_product(const Matrix &other)
Kronecker (tensor) product with other.
Matrix< T > & swap_rows(size_t i, size_t j)
Swap rows i and j.
Vector< T > get_row(size_t i) const
Extract row i as a vector.
constexpr Matrix< T > & fill(const T &s)
Set every component to s.
constexpr Vector< S > as_vector() const
Reinterpret the columns as elements of a superfield.
friend constexpr Matrix< T > VandermondeMatrix(const Vector< T > &v, size_t m)
Vandermonde matrix V_{i, j} = v[j]^i (tag details::Vandermonde).
constexpr Matrix & operator*=(const T &s)
Multiply every component by the scalar s.
Matrix< T > & delete_column(size_t i)
Delete column i (single-index convenience for delete_columns).
Matrix< T > & add_column(size_t i, size_t j)
col[j] ← col[j] + col[i]
Matrix< T > & vertical_join(const Matrix &other)
Concatenate other below (row-wise).
Matrix< T > & invert()
Invert in place.
Matrix< T > & delete_columns(const std::vector< size_t > &v)
Delete the columns whose indices appear in v.
std::vector< T > eigenvalues() const
Eigenvalues lying in the underlying finite field.
Matrix< T > & delete_row(size_t i)
Delete row i (single-index convenience for delete_rows).
Matrix & randomize()
Fill matrix with random values.
Univariate polynomial p(x) = a₀ + a₁x + … + aₙxⁿ over a CECCO::ComponentType.
Vector v = (v₀, v₁, …, vₙ₋₁) over a CECCO::ComponentType.
Contains implementation details not to be exposed to the user. Functions and classes here may change ...
matrix_type_t
Matrix structural type tag for optimization (internal).
@ Generic
Generic matrix with arbitrary elements.
@ Identity
Identity matrix with ones on diagonal and zeros elsewhere.
@ Toeplitz
Toeplitz matrix T_{i,j} = t_{i-j} with constant diagonals.
@ Zero
Zero matrix with all elements equal to zero.
@ Vandermonde
Vandermonde matrix with arithmetic progressions (of pairwise distinct elements) in columns.
@ Diagonal
Diagonal matrix (square) with non-zero elements only on the main diagonal.
Provides a framework for error correcting codes.
constexpr Matrix< T > ToeplitzMatrix(const Vector< T > &v, size_t m, size_t n)
m × n Toeplitz matrix from its diagonal entries (tag details::Toeplitz)
constexpr Matrix< T > VandermondeMatrix(const Vector< T > &v, size_t m)
Vandermonde matrix V_{i, j} = v[j]^i (tag details::Vandermonde).
constexpr Matrix< T > DiagonalMatrix(const Vector< T > &v)
Diagonal matrix with diagonal v (tag details::Diagonal).
constexpr Matrix< T > IdentityMatrix(size_t m)
m × m identity matrix I_m (tag details::Identity)
constexpr Matrix< T > ZeroMatrix(size_t m, size_t n)
m × n matrix of zeros (tag details::Zero)