📄 lzz_pxfactoring.c
字号:
#include <NTL/lzz_pXFactoring.h>#include <NTL/vec_vec_lzz_p.h>#include <NTL/FacVec.h>#include <NTL/new.h>NTL_START_IMPLvoid SquareFreeDecomp(vec_pair_zz_pX_long& u, const zz_pX& ff){ zz_pX f = ff; if (!IsOne(LeadCoeff(f))) Error("SquareFreeDecomp: bad args"); zz_pX r, t, v, tmp1; long m, j, finished, done; u.SetLength(0); if (deg(f) == 0) return; m = 1; finished = 0; do { j = 1; diff(tmp1, f); GCD(r, f, tmp1); div(t, f, r); if (deg(t) > 0) { done = 0; do { GCD(v, r, t); div(tmp1, t, v); if (deg(tmp1) > 0) append(u, cons(tmp1, j*m)); if (deg(v) > 0) { div(r, r, v); t = v; j++; } else done = 1; } while (!done); if (deg(r) == 0) finished = 1; } if (!finished) { /* r is a p-th power */ long p, k, d; p = long(zz_p::modulus()); d = deg(r)/p; f.rep.SetLength(d+1); for (k = 0; k <= d; k++) f.rep[k] = r.rep[k*p]; m = m*p; } } while (!finished);} staticvoid NullSpace(long& r, vec_long& D, vec_vec_zz_p& M, long verbose){ long k, l, n; long i, j; long pos; zz_p t1, t2; zz_p *x, *y; n = M.length(); D.SetLength(n); for (j = 0; j < n; j++) D[j] = -1; long p = zz_p::modulus(); double pinv = zz_p::ModulusInverse(); long T1, T2; double T1pinv; r = 0; l = 0; for (k = 0; k < n; k++) { if (verbose && k % 10 == 0) cerr << "+"; pos = -1; for (i = l; i < n; i++) { if (!IsZero(M[i][k])) { pos = i; break; } } if (pos != -1) { swap(M[pos], M[l]); // make M[l, k] == -1 mod p inv(t1, M[l][k]); negate(t1, t1); for (j = k+1; j < n; j++) { mul(M[l][j], M[l][j], t1); } for (i = l+1; i < n; i++) { // M[i] = M[i] + M[l]*M[i,k] t1 = M[i][k]; T1 = rep(t1); T1pinv = ((double) T1)*pinv; x = M[i].elts() + (k+1); y = M[l].elts() + (k+1); for (j = k+1; j < n; j++, x++, y++) { // *x = *x + (*y)*t1 T2 = MulMod2(rep(*y), T1, p, T1pinv); T2 = AddMod(T2, rep(*x), p); (*x).LoopHole() = T2; } } D[k] = l; // variable k is defined by row l l++; } else { r++; } }}staticvoid BuildMatrix(vec_vec_zz_p& M, long n, const zz_pX& g, const zz_pXModulus& F, long verbose){ long i, j, m; zz_pXMultiplier G; zz_pX h; M.SetLength(n); for (i = 0; i < n; i++) M[i].SetLength(n); build(G, g, F); set(h); for (j = 0; j < n; j++) { if (verbose && j % 10 == 0) cerr << "+"; m = deg(h); for (i = 0; i < n; i++) { if (i <= m) M[i][j] = h.rep[i]; else clear(M[i][j]); } if (j < n-1) MulMod(h, h, G, F); } for (i = 0; i < n; i++) add(M[i][i], M[i][i], -1);}staticvoid RecFindRoots(vec_zz_p& x, const zz_pX& f){ if (deg(f) == 0) return; if (deg(f) == 1) { long k = x.length(); x.SetLength(k+1); negate(x[k], ConstTerm(f)); return; } zz_pX h; zz_p r; long p1 = zz_p::modulus() >> 1; { zz_pXModulus F; build(F, f); do { random(r); PowerXPlusAMod(h, r, p1, F); add(h, h, -1); GCD(h, h, f); } while (deg(h) <= 0 || deg(h) == deg(f)); } RecFindRoots(x, h); div(h, f, h); RecFindRoots(x, h);}void FindRoots(vec_zz_p& x, const zz_pX& ff){ zz_pX f = ff; x.SetMaxLength(deg(f)); x.SetLength(0); RecFindRoots(x, f);}staticvoid RandomBasisElt(zz_pX& g, const vec_long& D, const vec_vec_zz_p& M){ zz_p t1, t2; long n = D.length(); long i, j, s; g.rep.SetLength(n); vec_zz_p& v = g.rep; for (j = n-1; j >= 0; j--) { if (D[j] == -1) random(v[j]); else { i = D[j]; // v[j] = sum_{s=j+1}^{n-1} v[s]*M[i,s] clear(t1); for (s = j+1; s < n; s++) { mul(t2, v[s], M[i][s]); add(t1, t1, t2); } v[j] = t1; } }}staticvoid split(zz_pX& f1, zz_pX& g1, zz_pX& f2, zz_pX& g2, const zz_pX& f, const zz_pX& g, const vec_zz_p& roots, long lo, long mid){ long r = mid-lo+1; zz_pXModulus F; build(F, f); vec_zz_p lroots(INIT_SIZE, r); long i; for (i = 0; i < r; i++) lroots[i] = roots[lo+i]; zz_pX h, a, d; BuildFromRoots(h, lroots); CompMod(a, h, g, F); GCD(f1, a, f); div(f2, f, f1); rem(g1, g, f1); rem(g2, g, f2);}staticvoid RecFindFactors(vec_zz_pX& factors, const zz_pX& f, const zz_pX& g, const vec_zz_p& roots, long lo, long hi){ long r = hi-lo+1; if (r == 0) return; if (r == 1) { append(factors, f); return; } zz_pX f1, g1, f2, g2; long mid = (lo+hi)/2; split(f1, g1, f2, g2, f, g, roots, lo, mid); RecFindFactors(factors, f1, g1, roots, lo, mid); RecFindFactors(factors, f2, g2, roots, mid+1, hi);}staticvoid FindFactors(vec_zz_pX& factors, const zz_pX& f, const zz_pX& g, const vec_zz_p& roots){ long r = roots.length(); factors.SetMaxLength(r); factors.SetLength(0); RecFindFactors(factors, f, g, roots, 0, r-1);}#if 0staticvoid IterFindFactors(vec_zz_pX& factors, const zz_pX& f, const zz_pX& g, const vec_zz_p& roots){ long r = roots.length(); long i; zz_pX h; factors.SetLength(r); for (i = 0; i < r; i++) { sub(h, g, roots[i]); GCD(factors[i], f, h); }}#endif void SFBerlekamp(vec_zz_pX& factors, const zz_pX& ff, long verbose){ zz_pX f = ff; if (!IsOne(LeadCoeff(f))) Error("SFBerlekamp: bad args"); if (deg(f) == 0) { factors.SetLength(0); return; } if (deg(f) == 1) { factors.SetLength(1); factors[0] = f; return; } double t; long p; p = zz_p::modulus(); long n = deg(f); zz_pXModulus F; build(F, f); zz_pX g, h; if (verbose) { cerr << "computing X^p..."; t = GetTime(); } PowerXMod(g, p, F); if (verbose) { cerr << (GetTime()-t) << "\n"; } vec_long D; long r; vec_vec_zz_p M; if (verbose) { cerr << "building matrix..."; t = GetTime(); } BuildMatrix(M, n, g, F, verbose); if (verbose) { cerr << (GetTime()-t) << "\n"; } if (verbose) { cerr << "diagonalizing..."; t = GetTime(); } NullSpace(r, D, M, verbose); if (verbose) { cerr << (GetTime()-t) << "\n"; } if (verbose) cerr << "number of factors = " << r << "\n"; if (r == 1) { factors.SetLength(1); factors[0] = f; return; } if (verbose) { cerr << "factor extraction..."; t = GetTime(); } vec_zz_p roots; RandomBasisElt(g, D, M); MinPolyMod(h, g, F, r); if (deg(h) == r) M.kill(); FindRoots(roots, h); FindFactors(factors, f, g, roots); zz_pX g1; vec_zz_pX S, S1; long i; while (factors.length() < r) { if (verbose) cerr << "+"; RandomBasisElt(g, D, M); S.kill(); for (i = 0; i < factors.length(); i++) { const zz_pX& f = factors[i]; if (deg(f) == 1) { append(S, f); continue; } build(F, f); rem(g1, g, F); if (deg(g1) <= 0) { append(S, f); continue; } MinPolyMod(h, g1, F, min(deg(f), r-factors.length()+1)); FindRoots(roots, h); S1.kill(); FindFactors(S1, f, g1, roots); append(S, S1); } swap(factors, S); } if (verbose) { cerr << (GetTime()-t) << "\n"; } if (verbose) { cerr << "degrees:"; long i; for (i = 0; i < factors.length(); i++) cerr << " " << deg(factors[i]); cerr << "\n"; }}void berlekamp(vec_pair_zz_pX_long& factors, const zz_pX& f, long verbose){ double t; vec_pair_zz_pX_long sfd; vec_zz_pX x; if (!IsOne(LeadCoeff(f))) Error("berlekamp: bad args"); if (verbose) { cerr << "square-free decomposition..."; t = GetTime(); } SquareFreeDecomp(sfd, f); if (verbose) cerr << (GetTime()-t) << "\n"; factors.SetLength(0); long i, j; for (i = 0; i < sfd.length(); i++) { if (verbose) { cerr << "factoring multiplicity " << sfd[i].b << ", deg = " << deg(sfd[i].a) << "\n"; } SFBerlekamp(x, sfd[i].a, verbose); for (j = 0; j < x.length(); j++) append(factors, cons(x[j], sfd[i].b)); }}staticvoid AddFactor(vec_pair_zz_pX_long& factors, const zz_pX& g, long d, long verbose){ if (verbose) cerr << "degree=" << d << ", number=" << deg(g)/d << "\n"; append(factors, cons(g, d));}staticvoid ProcessTable(zz_pX& f, vec_pair_zz_pX_long& factors, const zz_pXModulus& F, long limit, const vec_zz_pX& tbl, long d, long verbose){ if (limit == 0) return; if (verbose) cerr << "+"; zz_pX t1; if (limit == 1) { GCD(t1, f, tbl[0]); if (deg(t1) > 0) { AddFactor(factors, t1, d, verbose); div(f, f, t1); } return; } long i; t1 = tbl[0]; for (i = 1; i < limit; i++) MulMod(t1, t1, tbl[i], F); GCD(t1, f, t1); if (deg(t1) == 0) return; div(f, f, t1); zz_pX t2; i = 0; d = d - limit + 1; while (2*d <= deg(t1)) { GCD(t2, tbl[i], t1); if (deg(t2) > 0) { AddFactor(factors, t2, d, verbose); div(t1, t1, t2); } i++; d++; } if (deg(t1) > 0) AddFactor(factors, t1, deg(t1), verbose);}void TraceMap(zz_pX& w, const zz_pX& a, long d, const zz_pXModulus& F, const zz_pX& b){ if (d < 0) Error("TraceMap: bad args"); zz_pX y, z, t; z = b; y = a; clear(w); while (d) { if (d == 1) { if (IsZero(w)) w = y; else { CompMod(w, w, z, F); add(w, w, y); } } else if ((d & 1) == 0) { Comp2Mod(z, t, z, y, z, F); add(y, t, y); } else if (IsZero(w)) { w = y; Comp2Mod(z, t, z, y, z, F); add(y, t, y); } else { Comp3Mod(z, t, w, z, y, w, z, F); add(w, w, y); add(y, t, y); } d = d >> 1; }}void PowerCompose(zz_pX& y, const zz_pX& h, long q, const zz_pXModulus& F){ if (q < 0) Error("PowerCompose: bad args"); zz_pX z(INIT_SIZE, F.n); long sw; z = h; SetX(y); while (q) { sw = 0; if (q > 1) sw = 2; if (q & 1) { if (IsX(y)) y = z; else sw = sw | 1; } switch (sw) { case 0: break; case 1: CompMod(y, y, z, F); break; case 2: CompMod(z, z, z, F); break; case 3: Comp2Mod(y, z, y, z, z, F); break; } q = q >> 1; }}long ProbIrredTest(const zz_pX& f, long iter){ long n = deg(f); if (n <= 0) return 0; if (n == 1) return 1; long p; p = zz_p::modulus();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -