GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 62.3% 43 / 0 / 69
Functions: 100.0% 1 / 0 / 1
Branches: 97.0% 32 / 0 / 33

char_poly.hpp
Line Branch Exec Source
1 #pragma once
2
3 #include <vector>
4 #include <bitset>
5 #include <cassert>
6
7 // Compute the characteristic polynomial of a square matrix A over some field.
8 // Not numerically stable at all.
9 // Takes argument by value, use std::move if you can.
10
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 28 times.
28 template <typename num> std::vector<num> charPoly(std::vector<std::vector<num>> A) {
11 28 int N = int(A.size());
12
1/1
✓ Branch 4 → 5 taken 28 times.
28 std::vector<num> res; res.reserve(N+1);
13
1/1
✓ Branch 5 → 6 taken 28 times.
28 res.push_back(num(1));
14
2/2
✓ Branch 44 → 7 taken 9590 times.
✓ Branch 44 → 45 taken 28 times.
9618 for (int i = 0, deg = 0; i < N; i++) {
15 9590 auto& Ai = A[i];
16
17 9590 int c = i+1;
18
4/4
✓ Branch 8 → 9 taken 384437 times.
✓ Branch 8 → 11 taken 1696 times.
✓ Branch 9 → 10 taken 376543 times.
✓ Branch 9 → 11 taken 7894 times.
386133 while (c < N && Ai[c] == num(0)) c++;
19
2/2
✓ Branch 11 → 12 taken 1696 times.
✓ Branch 11 → 23 taken 7894 times.
9590 if (c == N) {
20
1/1
✓ Branch 12 → 13 taken 1696 times.
1696 res.resize(i+2, num(0));
21
2/2
✓ Branch 21 → 14 taken 458172 times.
✓ Branch 21 → 22 taken 1696 times.
459868 for (int x = deg; x >= 0; x--) {
22 458172 num v = res[x];
23
2/2
✓ Branch 19 → 15 taken 1104371 times.
✓ Branch 19 → 20 taken 458172 times.
1562543 for (int y = x+1, z = i; z >= deg; z--, y++) {
24
2/2
✓ Branch 15 → 16 taken 494484 times.
✓ Branch 15 → 17 taken 609887 times.
2208742 res[y] -= v * Ai[z];
25 }
26 }
27 1696 deg = i+1;
28 1696 continue;
29 1696 }
30
31 7894 num vc = Ai[c];
32 7894 num ivc = inv(vc);
33
34 7894 Ai[c] = Ai[i+1];
35 7894 Ai[i+1] = 0;
36
37 7894 std::swap(A[i+1], A[c]);
38 7894 auto& Ai1 = A[i+1];
39
2/2
✓ Branch 26 → 25 taken 3271757 times.
✓ Branch 26 → 39 taken 7894 times.
3279651 for (int k = deg; k < N; k++) {
40 3271757 Ai1[k] *= vc;
41 }
42
43
2/2
✓ Branch 39 → 27 taken 1995001 times.
✓ Branch 39 → 41 taken 7894 times.
2002895 for (int k = i+1; k < N; k++) {
44 1995001 auto& Ak = A[k];
45 {
46 1995001 auto& x = Ak[i+1];
47 1995001 auto& y = Ak[c];
48 1995001 num tmp = y;
49 1995001 y = x;
50 1995001 x = tmp * ivc;
51 }
52 {
53 1995001 num v = Ak[i+1];
54
2/2
✓ Branch 32 → 28 taken 894607571 times.
✓ Branch 32 → 33 taken 1995001 times.
896602572 for (int j = deg; j < N; j++) {
55
2/2
✓ Branch 28 → 29 taken 446296308 times.
✓ Branch 28 → 30 taken 448311263 times.
1789215142 Ak[j] -= v * Ai[j];
56 }
57 }
58
2/2
✓ Branch 33 → 34 taken 1987107 times.
✓ Branch 33 → 38 taken 7894 times.
1995001 if (k > i+1) {
59 1987107 num v = Ai[k];
60
2/2
✓ Branch 37 → 35 taken 891335814 times.
✓ Branch 37 → 38 taken 1987107 times.
893322921 for (int j = deg; j < N; j++) {
61 891335814 Ai1[j] += v * Ak[j];
62 }
63 }
64 }
65
66
2/2
✓ Branch 41 → 40 taken 1276756 times.
✓ Branch 41 → 42 taken 7894 times.
1284650 for (int k = deg; k <= i; k++) {
67 1276756 Ai1[k+1] += Ai[k];
68 }
69 }
70 28 reverse(res.begin(), res.end());
71 28 return res;
72 }
73
74 // Compute the characteristic polynomial of a square matrix A over F2.
75 // Takes argument by value, use std::move if you can.
76 // Note that MAXS must be at least N+1
77 template <std::size_t MAXS> std::bitset<MAXS> charPoly(std::vector<std::bitset<MAXS>> A) {
78 using bs = std::bitset<MAXS>;
79 int N = int(A.size());
80 assert(MAXS >= N+1);
81 bs ans; ans[0] = 1;
82 int deg = 0;
83 for (int i = 0; i < N; i++) {
84 {
85 int j = int(A[i]._Find_next(i));
86 if (j >= N) {
87 bs nans;
88 for (; deg <= i; ans <<= 1, deg++) {
89 if (A[i][deg]) nans ^= ans;
90 }
91 ans ^= nans;
92 continue;
93 }
94 if (j != i+1) {
95 swap(A[j], A[i+1]);
96 for (auto& a : A) {
97 bool tmp = a[j];
98 a[j] = a[i+1];
99 a[i+1] = tmp;
100 }
101 }
102 }
103 assert(A[i][i+1]);
104 bs msk = A[i]; msk.flip(i+1);
105 for (int k = 0; k < N; k++) {
106 if (msk[k]) A[i+1] ^= A[k];
107 }
108 for (auto& a : A) {
109 if (a[i+1]) a ^= msk;
110 }
111 }
112 return ans;
113 }
114