9#include <unordered_set>
24 const std::vector<size_t>& indices,
27 std::vector<BigInt> product = {BigInt(1)};
29 for (
size_t index : indices) {
30 auto step =
context.consume_steps(1,
"zassenhaus_combine");
38 "zassenhaus_combine");
41 std::vector<BigInt> next(product.size() + factor_coeffs.size() - 1,
43 for (
size_t i = 0; i < product.size(); ++i) {
44 if (product[i].is_zero())
continue;
45 for (
size_t j = 0; j < factor_coeffs.size(); ++j) {
46 if (factor_coeffs[j].is_zero())
continue;
47 next[i + j] = next[i + j] + product[i] * factor_coeffs[j];
50 for (
auto& coefficient : next) {
53 while (!next.empty() && next.back().is_zero()) next.pop_back();
54 product = std::move(next);
70 const std::vector<BigInt>& coeffs,
71 const std::string& var) {
73 std::vector<Rational> rat_coeffs;
74 rat_coeffs.reserve(coeffs.size());
75 for (
const auto&
c : coeffs) {
76 rat_coeffs.emplace_back(
c);
104 if (m.is_zero() || m.is_negative())
return false;
107 const auto a_small =
a.try_to_int64();
108 const auto m_small = m.try_to_int64();
109 if (a_small && m_small) {
110 const int64_t a_val = *a_small;
111 const int64_t m_val = *m_small;
115 if (!reconstructed)
return false;
116 const auto [p, q] = reconstructed.value();
117 num = BigInt(
static_cast<std::int64_t
>(p));
118 den = BigInt(
static_cast<std::int64_t
>(q));
124 BigInt a_mod =
a % m;
125 if (a_mod.is_negative()) {
130 BigInt half_m = m / BigInt(2);
131 BigInt bound = half_m.sqrt();
132 if (bound.is_zero()) bound = BigInt(1);
135 BigInt r0 = m, r1 = a_mod;
136 BigInt s0 = BigInt(0), s1 = BigInt(1);
140 BigInt r_new = r0 - q * r1;
141 BigInt s_new = s0 - q * s1;
153 if (q_val.is_negative()) {
159 if (p.abs() > bound || q_val.is_zero() || q_val > bound) {
164 BigInt g = BigInt::gcd(p.abs(), q_val);
165 if (g != BigInt(1)) {
188 const std::vector<BigInt>& product_coeffs,
190 const std::string& var) {
192 std::vector<Rational> rat_coeffs;
193 rat_coeffs.reserve(product_coeffs.size());
196 for (
const auto&
c : product_coeffs) {
199 rat_coeffs.emplace_back(
num, den);
223 if (candidate.
is_zero())
return false;
225 if (candidate.
degree() == 0)
return true;
227 auto [quotient, remainder] = f.
div_mod(candidate);
228 return remainder.is_zero();
239 if (poly.
is_zero())
return poly;
244 const size_t width = positions.size();
245 for (
size_t cursor = width; cursor > 0; --cursor) {
246 const size_t i = cursor - 1;
247 if (positions[i] < count - width + i) {
249 for (
size_t j = i + 1; j < width; ++j) {
250 positions[j] = positions[j - 1] + 1;
259 const std::vector<size_t>& active,
260 const std::vector<size_t>& positions) {
261 std::vector<size_t> indices;
262 indices.reserve(positions.size());
263 for (
size_t position : positions) indices.push_back(active[position]);
270 const BigInt& modulus,
277 for (
size_t i = 0; i < all_indices.size(); ++i) {
280 auto product_result =
282 if (!product_result) {
285 auto product = std::move(product_result.value());
287 BigInt denominator_lcm(1);
288 for (
const Rational& coefficient : poly.
coeffs) {
290 BigInt::lcm(denominator_lcm, coefficient.get_denominator());
292 std::vector<BigInt> expected;
293 expected.reserve(poly.
coeffs.size());
294 for (
const Rational& coefficient : poly.
coeffs) {
295 BigInt integer_coefficient =
296 coefficient.get_numerator() *
297 (denominator_lcm / coefficient.get_denominator());
301 while (!expected.empty() && expected.back().is_zero()) {
304 while (!product.empty() && product.back().is_zero()) {
307 if (!(product == expected)) {
310 "lifted factors are not congruent to the normalized polynomial",
311 "zassenhaus_combine");
321 std::string reason) {
328 for (
const auto& factor : factors) product = product * factor;
332 "accepted Zassenhaus factors do not reconstruct the polynomial",
333 "zassenhaus_combine");
335 }
else if (!factors.empty()) {
338 "zero polynomial cannot have a nonempty monic factorization",
339 "zassenhaus_combine");
344 std::move(factors), completeness, std::move(reason)});
348 const std::vector<Polynomial<BigInt>>&
lifted;
371 if (candidate.is_zero() || candidate.degree() <= 0 ||
377 if (!remainder.is_zero()) {
380 "zassenhaus_combine");
382 search.
factors.push_back(candidate);
384 for (
size_t cursor = positions.size(); cursor > 0; --cursor) {
386 static_cast<std::ptrdiff_t
>(positions[cursor - 1]));
392 for (
size_t width = 1; width <= search.
active.size() / 2; ++width) {
393 std::vector<size_t> positions(width);
394 for (
size_t i = 0; i < width; ++i) positions[i] = i;
397 if (!candidate || candidate.value())
return candidate;
409 for (
size_t i = 0; i < search.
active.size(); ++i) search.
active[i] = i;
413 if (!found.value())
break;
428 "reconstruction modulus must be positive",
429 "zassenhaus_combine");
435 "zero polynomial requires an empty lifted-factor list",
436 "zassenhaus_combine");
445 "no lifted factors were provided");
463 }
catch (
const std::bad_alloc&) {
466 }
catch (
const std::exception& error) {
Result< void > consume_steps(std::size_t amount=1, const std::string &operation={})
std::pair< Polynomial, Polynomial > div_mod(const Polynomial &other) const
多项式带余除法
std::string variable_name
变量名
bool is_zero() const
判断是否为零多项式
std::vector< CoeffType > coeffs
系数数组,coeffs[i] 为 x^i 的系数
int degree() const
获取多项式的次数
Polynomial make_monic() const
首一化(使首项系数为 1)
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
BigInt symmetric_remainder(const BigInt &value, const BigInt &modulus)
std::shared_ptr< SymbolicExpr > num(int value)
static bool zc_next_combination(std::vector< size_t > &positions, size_t count)
static Result< void > zc_validate_lifted_product(const Polynomial< Rational > &poly, const std::vector< Polynomial< BigInt > > &lifted_factors, const BigInt &modulus, ComputationContext &context)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
std::vector< Polynomial< Rational > > factors
std::vector< size_t > active
const std::vector< Polynomial< BigInt > > & lifted
const VectorField const VectorField & c
static ZassenhausResult zassenhaus_combine_impl(const Polynomial< Rational > &poly, const std::vector< Polynomial< BigInt > > &lifted_factors, const BigInt &reconstruction_modulus, ComputationContext &context)
static Polynomial< Rational > zc_make_primitive(const Polynomial< Rational > &poly)
使候选多项式首一化(首项系数归一).
const std::vector< Polynomial< BigInt > > const BigInt & reconstruction_modulus
static Polynomial< Rational > zc_bigint_to_rational_poly(const std::vector< BigInt > &coeffs, const std::string &var)
将 BigInt 系数向量转换为有理系数多项式.
const std::vector< Polynomial< BigInt > > & lifted_factors
ComputationContext & context
static bool zc_divides_exactly(const Polynomial< Rational > &f, const Polynomial< Rational > &candidate)
检验候选因子是否整除原多项式(精确有理除法).
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::shared_ptr< SymbolicExpr > & a
static Polynomial< Rational > zc_reconstruct_candidate(const std::vector< BigInt > &product_coeffs, const BigInt &mod, const std::string &var)
对子集乘积的所有系数执行有理重构,构造有理系数多项式.
static bool zc_rational_reconstruction(const BigInt &a, const BigInt &m, BigInt &num, BigInt &den)
对 BigInt 系数执行有理数重构.
RationalReconstructionResult rational_reconstruction_checked(int64_t x, int64_t m, ComputationContext &context)
Checked rational reconstruction.
static ZassenhausResult zc_enumerate(const Polynomial< Rational > &poly, const std::vector< Polynomial< BigInt > > &lifted_factors, const BigInt &modulus, ComputationContext &context)
static std::vector< size_t > zc_select_indices(const std::vector< size_t > &active, const std::vector< size_t > &positions)
static Result< bool > zc_try_candidate(ZcFactorSearch &search, const std::vector< size_t > &positions)
static ZassenhausResult zc_finalize(const Polynomial< Rational > &original, std::vector< Polynomial< Rational > > factors, Polynomial< Rational > remaining, Completeness completeness, std::string reason)
static Result< std::vector< BigInt > > zc_subset_product(const std::vector< Polynomial< BigInt > > &lifted_factors, const std::vector< size_t > &indices, const BigInt &mod, ComputationContext &context)
在模 m 下乘以按字典序枚举的提升因子子集.
Result< MathResult< std::vector< Polynomial< Rational > > > > ZassenhausResult
ZassenhausResult zassenhaus_combine_checked(const Polynomial< Rational > &poly, const std::vector< Polynomial< BigInt > > &lifted_factors, const BigInt &reconstruction_modulus, ComputationContext &context)
static Result< bool > zc_find_factor(ZcFactorSearch &search)
Polynomial< Rational > remaining