Skip to content

Commit f2a2377

Browse files
committed
Improve Frobenius normal form computation
1 parent a8ffa71 commit f2a2377

File tree

4 files changed

+28
-23
lines changed

4 files changed

+28
-23
lines changed

cp-algo/linalg/frobenius.hpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,9 @@ namespace cp_algo::linalg {
3939
if(full_rec.mod_xk(start) != polyn()) {
4040
auto charp = full_rec.div_xk(start);
4141
auto x = basis_init[start];
42-
start = 0;
43-
for(auto &rec: charps) {
44-
polyn cur_rec = full_rec.substr(start, rec.deg());
45-
auto shift = cur_rec / charp;
46-
for(int j = 0; j <= shift.deg(); j++) {
47-
x.add_scaled(basis_init[start + j], shift[j]);
48-
}
49-
start += rec.deg();
42+
auto shift = full_rec / charp;
43+
for(int j = 0; j < shift.deg(); j++) {
44+
x.add_scaled(basis_init[j], shift[j]);
5045
}
5146
basis.resize(start);
5247
basis_init.resize(start);
@@ -75,13 +70,12 @@ namespace cp_algo::linalg {
7570
}
7671

7772
template<typename base>
78-
auto frobenius_pow(matrix<base> A, uint64_t k) {
79-
using polyn = math::poly_t<base>;
73+
auto with_frobenius(matrix<base> const& A, auto &&callback) {
8074
auto [T, Tinv, charps] = frobenius_form<full>(A);
8175
std::vector<matrix<base>> blocks;
8276
for(auto charp: charps) {
8377
matrix<base> block(charp.deg());
84-
auto xk = polyn::xk(1).powmod(k, charp);
78+
auto xk = callback(charp);
8579
for(size_t i = 0; i < block.n(); i++) {
8680
std::ranges::copy(xk.a, begin(block[i]));
8781
xk = xk.mul_xk(1) % charp;
@@ -91,5 +85,12 @@ namespace cp_algo::linalg {
9185
auto S = matrix<base>::block_diagonal(blocks);
9286
return Tinv * S * T;
9387
}
88+
89+
template<typename base>
90+
auto frobenius_pow(matrix<base> const& A, uint64_t k) {
91+
return with_frobenius(A, [k](auto const& charp) {
92+
return math::poly_t<base>::xk(1).powmod(k, charp);
93+
});
94+
}
9495
};
9596
#endif // CP_ALGO_LINALG_FROBENIUS_HPP

cp-algo/linalg/vector.hpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,10 @@ namespace cp_algo::linalg {
5656
}
5757

5858
virtual void add_scaled(vec const& b, base scale, size_t i = 0) {
59-
for(; i < size(*this); i++) {
60-
(*this)[i] += scale * b[i];
59+
if(scale != base(0)) {
60+
for(; i < size(*this); i++) {
61+
(*this)[i] += scale * b[i];
62+
}
6163
}
6264
}
6365
virtual vec const& normalize() {
@@ -125,14 +127,16 @@ namespace cp_algo::linalg {
125127
using Base::Base;
126128

127129
void add_scaled(vec const& b, base scale, size_t i = 0) override {
128-
for(; i < size(*this); i++) {
129-
(*this)[i].add_unsafe(scale.getr() * b[i].getr());
130-
}
131-
if(++counter == 8) {
132-
for(auto &it: *this) {
133-
it.pseudonormalize();
130+
if(scale != base(0)) {
131+
for(; i < size(*this); i++) {
132+
(*this)[i].add_unsafe(scale.getr() * b[i].getr());
133+
}
134+
if(++counter == 8) {
135+
for(auto &it: *this) {
136+
it.pseudonormalize();
137+
}
138+
counter = 0;
134139
}
135-
counter = 0;
136140
}
137141
}
138142
vec const& normalize() override {

verify/linalg/characteristic.test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// @brief Characteristic Polynomial
22
#define PROBLEM "https://judge.yosupo.jp/problem/characteristic_polynomial"
33
#pragma GCC optimize("Ofast,unroll-loops")
4-
#pragma GCC target("tune=native")
5-
#define CP_ALGO_MAXN 1 << 12
4+
//#pragma GCC target("tune=native")
5+
#define CP_ALGO_MAXN 1 << 10
66
#include "cp-algo/linalg/frobenius.hpp"
77
#include <bits/stdc++.h>
88

verify/linalg/pow_fast.test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#define PROBLEM "https://judge.yosupo.jp/problem/pow_of_matrix"
33
#pragma GCC optimize("Ofast,unroll-loops")
44
#pragma GCC target("tune=native")
5-
#define CP_ALGO_MAXN 1 << 12
5+
#define CP_ALGO_MAXN 1 << 10
66
#include "cp-algo/linalg/frobenius.hpp"
77
#include <bits/stdc++.h>
88

0 commit comments

Comments
 (0)