GEN addui_sign(ulong x, GEN y, long sy) { long ly; GEN z; if (!x) return icopy_sign(y, sy); if (!sy) return utoipos(x); if (sy == 1) return adduispec(x,y+2, lgefint(y)-2); ly=lgefint(y); if (ly==3) { const ulong t = y[2]; if (x == t) return gen_0; z=cgeti(3); if (x < t) { z[1] = evalsigne(-1) | evallgefint(3); z[2] = t - x; } else { z[1] = evalsigne(1) | evallgefint(3); z[2] = x - t; } return z; } z = subiuspec(y+2,x, ly-2); setsigne(z,-1); return z; }
static void choose_prime(primedata *S, GEN pol, GEN dpol) { byteptr di = diffptr + 1; long i, j, k, r, lcm, oldlcm, pp, N = degpol(pol), minp = N*N / 4; GEN Z, p, ff, oldff, n, oldn; pari_sp av; if (DEBUGLEVEL) (void)timer2(); p = utoipos(2); while (p[2] <= minp) NEXT_PRIME_VIADIFF(p[2], di); oldlcm = 0; oldff = oldn = NULL; pp = 0; /* gcc -Wall */ av = avma; for(k = 1; k < 11 || !oldlcm; k++,avma = av) { do NEXT_PRIME_VIADIFF(p[2], di); while (!smodis(dpol, p[2])); if (k > 5 * N) pari_err(talker,"sorry, too many block systems in nfsubfields"); ff = (GEN)FpX_factor(pol, p)[1]; r = lg(ff)-1; if (r == N || r >= BIL) continue; n = cgetg(r+1, t_VECSMALL); lcm = n[1] = degpol(ff[1]); for (j=2; j<=r; j++) { n[j] = degpol(ff[j]); lcm = clcm(lcm, n[j]); } if (lcm <= oldlcm) continue; /* false when oldlcm = 0 */ if (DEBUGLEVEL) fprintferr("p = %ld,\tlcm = %ld,\torbits: %Z\n",p[2],lcm,n); pp = p[2]; oldn = n; oldff = ff; oldlcm = lcm; if (r == 1) break; av = avma; } if (DEBUGLEVEL) fprintferr("Chosen prime: p = %ld\n", pp); S->ff = oldff; S->lcm= oldlcm; S->p = utoipos(pp); S->pol = FpX_red(pol, S->p); init_primedata(S); n = oldn; r = lg(n); Z = cgetg(r,t_VEC); for (k=0,i=1; i<r; i++) { GEN t = cgetg(n[i]+1, t_VECSMALL); gel(Z,i) = t; for (j=1; j<=n[i]; j++) t[j] = ++k; } S->Z = Z; }
static GEN subfieldsall(GEN nf) { pari_sp av = avma; long N, ld, i, v0; GEN G, pol, dg, LSB, NLSB; poldata PD; primedata S; blockdata B; /* much easier if nf is Galois (WSS) */ G = galoisconj4(nf, NULL, 1); if (typ(G) != t_INT) { GEN L, S, p; long l; pol = get_nfpol(nf, &nf); L = lift_intern( galoissubfields(G, 0, varn(pol)) ); l = lg(L); S = cgetg(l, t_VECSMALL); for (i=1; i<l; i++) S[i] = lg(gmael(L,i,1)); p = vecsmall_indexsort(S); return gerepilecopy(av, vecpermute(L, p)); } subfields_poldata(nf, &PD); pol = PD.pol; v0 = varn(pol); N = degpol(pol); dg = divisors(utoipos(N)); ld = lg(dg)-1; if (DEBUGLEVEL) fprintferr("\n***** Entering subfields\n\npol = %Z\n",pol); LSB = _subfield(pol, pol_x[0]); if (ld > 2) { B.PD = &PD; B.S = &S; B.N = N; choose_prime(&S, PD.pol, PD.dis); for (i=2; i<ld; i++) { B.size = itos(gel(dg,i)); B.d = N / B.size; NLSB = subfields_of_given_degree(&B); if (NLSB) { LSB = concat(LSB, NLSB); gunclone(NLSB); } } (void)delete_var(); /* from choose_prime */ } LSB = shallowconcat(LSB, _subfield(pol_x[0], pol)); if (DEBUGLEVEL) fprintferr("\n***** Leaving subfields\n\n"); return fix_var(gerepilecopy(av, LSB), v0); }
GEN bezout(GEN a, GEN b, GEN *pu, GEN *pv) { GEN t,u,u1,v,v1,d,d1,q,r; GEN *pt; pari_sp av, av1; long s, sa, sb; ulong g; ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */ int lhmres; /* Lehmer stage return value */ s = abscmpii(a,b); if (s < 0) { t=b; b=a; a=t; pt=pu; pu=pv; pv=pt; } /* now |a| >= |b| */ sa = signe(a); sb = signe(b); if (!sb) { if (pv) *pv = gen_0; switch(sa) { case 0: if (pu) *pu = gen_0; return gen_0; case 1: if (pu) *pu = gen_1; return icopy(a); case -1: if (pu) *pu = gen_m1; return(negi(a)); } } if (s == 0) /* |a| == |b| != 0 */ { if (pu) *pu = gen_0; if (sb > 0) { if (pv) *pv = gen_1; return icopy(b); } else { if (pv) *pv = gen_m1; return(negi(b)); } } /* now |a| > |b| > 0 */ if (lgefint(a) == 3) /* single-word affair */ { g = xxgcduu(uel(a,2), uel(b,2), 0, &xu, &xu1, &xv, &xv1, &s); sa = s > 0 ? sa : -sa; sb = s > 0 ? -sb : sb; if (pu) { if (xu == 0) *pu = gen_0; /* can happen when b divides a */ else if (xu == 1) *pu = sa < 0 ? gen_m1 : gen_1; else if (xu == 2) *pu = sa < 0 ? gen_m2 : gen_2; else { *pu = cgeti(3); (*pu)[1] = evalsigne(sa)|evallgefint(3); (*pu)[2] = xu; } } if (pv) { if (xv == 1) *pv = sb < 0 ? gen_m1 : gen_1; else if (xv == 2) *pv = sb < 0 ? gen_m2 : gen_2; else { *pv = cgeti(3); (*pv)[1] = evalsigne(sb)|evallgefint(3); (*pv)[2] = xv; } } if (g == 1) return gen_1; else if (g == 2) return gen_2; else return utoipos(g); } /* general case */ av = avma; (void)new_chunk(lgefint(b) + (lgefint(a)<<1)); /* room for u,v,gcd */ /* if a is significantly larger than b, calling lgcdii() is not the best * way to start -- reduce a mod b first */ if (lgefint(a) > lgefint(b)) { d = absi(b), q = dvmdii(absi(a), d, &d1); if (!signe(d1)) /* a == qb */ { avma = av; if (pu) *pu = gen_0; if (pv) *pv = sb < 0 ? gen_m1 : gen_1; return (icopy(d)); } else { u = gen_0; u1 = v = gen_1; v1 = negi(q); } /* if this results in lgefint(d) == 3, will fall past main loop */ } else { d = absi(a); d1 = absi(b); u = v1 = gen_1; u1 = v = gen_0; } av1 = avma; /* main loop is almost identical to that of invmod() */ while (lgefint(d) > 3 && signe(d1)) { lhmres = lgcdii((ulong *)d, (ulong *)d1, &xu, &xu1, &xv, &xv1, ULONG_MAX); if (lhmres != 0) /* check progress */ { /* apply matrix */ if ((lhmres == 1) || (lhmres == -1)) { if (xv1 == 1) { r = subii(d,d1); d=d1; d1=r; a = subii(u,u1); u=u1; u1=a; a = subii(v,v1); v=v1; v1=a; } else { r = subii(d, mului(xv1,d1)); d=d1; d1=r; a = subii(u, mului(xv1,u1)); u=u1; u1=a; a = subii(v, mului(xv1,v1)); v=v1; v1=a; } } else { r = subii(muliu(d,xu), muliu(d1,xv)); d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r; a = subii(muliu(u,xu), muliu(u1,xv)); u1 = subii(muliu(u,xu1), muliu(u1,xv1)); u = a; a = subii(muliu(v,xu), muliu(v1,xv)); v1 = subii(muliu(v,xu1), muliu(v1,xv1)); v = a; if (lhmres&1) { togglesign(d); togglesign(u); togglesign(v); } else { togglesign(d1); togglesign(u1); togglesign(v1); } } } if (lhmres <= 0 && signe(d1)) { q = dvmdii(d,d1,&r); a = subii(u,mulii(q,u1)); u=u1; u1=a; a = subii(v,mulii(q,v1)); v=v1; v1=a; d=d1; d1=r; } if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"bezout"); gerepileall(av1,6, &d,&d1,&u,&u1,&v,&v1); } } /* end while */ /* Postprocessing - final sprint */ if (signe(d1)) { /* Assertions: lgefint(d)==lgefint(d1)==3, and * gcd(d,d1) is nonzero and fits into one word */ g = xxgcduu(uel(d,2), uel(d1,2), 0, &xu, &xu1, &xv, &xv1, &s); u = subii(muliu(u,xu), muliu(u1, xv)); v = subii(muliu(v,xu), muliu(v1, xv)); if (s < 0) { sa = -sa; sb = -sb; } avma = av; if (pu) *pu = sa < 0 ? negi(u) : icopy(u); if (pv) *pv = sb < 0 ? negi(v) : icopy(v); if (g == 1) return gen_1; else if (g == 2) return gen_2; else return utoipos(g); } /* get here when the final sprint was skipped (d1 was zero already). * Now the matrix is final, and d contains the gcd. */ avma = av; if (pu) *pu = sa < 0 ? negi(u) : icopy(u); if (pv) *pv = sb < 0 ? negi(v) : icopy(v); return icopy(d); }
/* Naive recombination of modular factors: combine up to maxK modular * factors, degree <= klim and divisible by hint * * target = polynomial we want to factor * famod = array of modular factors. Product should be congruent to * target/lc(target) modulo p^a * For true factors: S1,S2 <= p^b, with b <= a and p^(b-a) < 2^31 */ static GEN nfcmbf(nfcmbf_t *T, GEN p, long a, long maxK, long klim) { GEN pol = T->pol, nf = T->nf, famod = T->fact, dn = T->dn; GEN bound = T->bound; GEN nfpol = gel(nf,1); long K = 1, cnt = 1, i,j,k, curdeg, lfamod = lg(famod)-1, dnf = degpol(nfpol); GEN res = cgetg(3, t_VEC); pari_sp av0 = avma; GEN pk = gpowgs(p,a), pks2 = shifti(pk,-1); GEN ind = cgetg(lfamod+1, t_VECSMALL); GEN degpol = cgetg(lfamod+1, t_VECSMALL); GEN degsofar = cgetg(lfamod+1, t_VECSMALL); GEN listmod = cgetg(lfamod+1, t_COL); GEN fa = cgetg(lfamod+1, t_COL); GEN lc = absi(leading_term(pol)), lt = is_pm1(lc)? NULL: lc; GEN C2ltpol, C = T->L->topowden, Tpk = T->L->Tpk; GEN Clt = mul_content(C, lt); GEN C2lt = mul_content(C,Clt); const double Bhigh = get_Bhigh(lfamod, dnf); trace_data _T1, _T2, *T1, *T2; pari_timer ti; TIMERstart(&ti); if (maxK < 0) maxK = lfamod-1; C2ltpol = C2lt? gmul(C2lt,pol): pol; { GEN q = ceil_safe(sqrtr(T->BS_2)); GEN t1,t2, ltdn, lt2dn; GEN trace1 = cgetg(lfamod+1, t_MAT); GEN trace2 = cgetg(lfamod+1, t_MAT); ltdn = mul_content(lt, dn); lt2dn= mul_content(ltdn, lt); for (i=1; i <= lfamod; i++) { pari_sp av = avma; GEN P = gel(famod,i); long d = degpol(P); degpol[i] = d; P += 2; t1 = gel(P,d-1);/* = - S_1 */ t2 = gsqr(t1); if (d > 1) t2 = gsub(t2, gmul2n(gel(P,d-2), 1)); /* t2 = S_2 Newton sum */ t2 = typ(t2)!=t_INT? FpX_rem(t2, Tpk, pk): modii(t2, pk); if (lt) { if (typ(t2)!=t_INT) { t1 = FpX_red(gmul(ltdn, t1), pk); t2 = FpX_red(gmul(lt2dn,t2), pk); } else { t1 = remii(mulii(ltdn, t1), pk); t2 = remii(mulii(lt2dn,t2), pk); } } gel(trace1,i) = gclone( nf_bestlift(t1, NULL, T->L) ); gel(trace2,i) = gclone( nf_bestlift(t2, NULL, T->L) ); avma = av; } T1 = init_trace(&_T1, trace1, T->L, q); T2 = init_trace(&_T2, trace2, T->L, q); for (i=1; i <= lfamod; i++) { gunclone(gel(trace1,i)); gunclone(gel(trace2,i)); } } degsofar[0] = 0; /* sentinel */ /* ind runs through strictly increasing sequences of length K, * 1 <= ind[i] <= lfamod */ nextK: if (K > maxK || 2*K > lfamod) goto END; if (DEBUGLEVEL > 3) fprintferr("\n### K = %d, %Z combinations\n", K,binomial(utoipos(lfamod), K)); setlg(ind, K+1); ind[1] = 1; i = 1; curdeg = degpol[ind[1]]; for(;;) { /* try all combinations of K factors */ for (j = i; j < K; j++) { degsofar[j] = curdeg; ind[j+1] = ind[j]+1; curdeg += degpol[ind[j+1]]; } if (curdeg <= klim && curdeg % T->hint == 0) /* trial divide */ { GEN t, y, q, list; pari_sp av; av = avma; /* d - 1 test */ if (T1) { t = get_trace(ind, T1); if (rtodbl(QuickNormL2(t,DEFAULTPREC)) > Bhigh) { if (DEBUGLEVEL>6) fprintferr("."); avma = av; goto NEXT; } } /* d - 2 test */ if (T2) { t = get_trace(ind, T2); if (rtodbl(QuickNormL2(t,DEFAULTPREC)) > Bhigh) { if (DEBUGLEVEL>3) fprintferr("|"); avma = av; goto NEXT; } } avma = av; y = lt; /* full computation */ for (i=1; i<=K; i++) { GEN q = gel(famod, ind[i]); if (y) q = gmul(y, q); y = FqX_centermod(q, Tpk, pk, pks2); } y = nf_pol_lift(y, bound, T); if (!y) { if (DEBUGLEVEL>3) fprintferr("@"); avma = av; goto NEXT; } /* try out the new combination: y is the candidate factor */ q = RgXQX_divrem(C2ltpol, y, nfpol, ONLY_DIVIDES); if (!q) { if (DEBUGLEVEL>3) fprintferr("*"); avma = av; goto NEXT; } /* found a factor */ list = cgetg(K+1, t_VEC); gel(listmod,cnt) = list; for (i=1; i<=K; i++) list[i] = famod[ind[i]]; y = Q_primpart(y); gel(fa,cnt++) = QXQX_normalize(y, nfpol); /* fix up pol */ pol = q; for (i=j=k=1; i <= lfamod; i++) { /* remove used factors */ if (j <= K && i == ind[j]) j++; else { famod[k] = famod[i]; update_trace(T1, k, i); update_trace(T2, k, i); degpol[k] = degpol[i]; k++; } } lfamod -= K; if (lfamod < 2*K) goto END; i = 1; curdeg = degpol[ind[1]]; if (C2lt) pol = Q_primpart(pol); if (lt) lt = absi(leading_term(pol)); Clt = mul_content(C, lt); C2lt = mul_content(C,Clt); C2ltpol = C2lt? gmul(C2lt,pol): pol; if (DEBUGLEVEL > 2) { fprintferr("\n"); msgTIMER(&ti, "to find factor %Z",y); fprintferr("remaining modular factor(s): %ld\n", lfamod); } continue; } NEXT: for (i = K+1;;) { if (--i == 0) { K++; goto nextK; } if (++ind[i] <= lfamod - K + i) { curdeg = degsofar[i-1] + degpol[ind[i]]; if (curdeg <= klim) break; } } } END: if (degpol(pol) > 0) { /* leftover factor */ if (signe(leading_term(pol)) < 0) pol = gneg_i(pol); if (C2lt && lfamod < 2*K) pol = QXQX_normalize(Q_primpart(pol), nfpol); setlg(famod, lfamod+1); gel(listmod,cnt) = shallowcopy(famod); gel(fa,cnt++) = pol; } if (DEBUGLEVEL>6) fprintferr("\n"); if (cnt == 2) { avma = av0; gel(res,1) = mkvec(T->pol); gel(res,2) = mkvec(T->fact); } else { setlg(listmod, cnt); setlg(fa, cnt); gel(res,1) = fa; gel(res,2) = listmod; res = gerepilecopy(av0, res); } return res; }
/* return the factorization of x in nf */ GEN nffactor(GEN nf,GEN pol) { GEN A,g,y,p1,T, rep = cgetg(3, t_MAT); long l, j, dA; pari_sp av = avma; pari_timer ti; if (DEBUGLEVEL>2) { TIMERstart(&ti); fprintferr("\nEntering nffactor:\n"); } nf = checknf(nf); T = gel(nf,1); if (typ(pol) != t_POL) pari_err(notpoler,"nffactor"); if (varncmp(varn(pol), varn(T)) >= 0) pari_err(talker,"polynomial variable must have highest priority in nffactor"); A = fix_relative_pol(nf,pol,0); dA = degpol(A); if (dA <= 0) { avma = (pari_sp)(rep + 3); return dA == 0? trivfact(): zerofact(varn(pol)); } A = Q_primpart( QXQX_normalize(A, T) ); if (dA == 1) { GEN c; A = gerepilecopy(av, A); c = gel(A,2); if (typ(c) == t_POL && degpol(c) > 0) gel(A,2) = mkpolmod(c, gcopy(T)); gel(rep,1) = mkcol(A); gel(rep,2) = mkcol(gen_1); return rep; } if (degpol(T) == 1) return gerepileupto(av, factpol(Q_primpart(simplify(pol)), 0)); A = Q_primpart( lift_intern(A) ); g = nfgcd(A, derivpol(A), T, gel(nf,4)); A = QXQX_normalize(A, T); A = Q_primpart(A); if (DEBUGLEVEL>2) msgTIMER(&ti, "squarefree test"); if (degpol(g)) { /* not squarefree */ pari_sp av1; GEN ex; g = QXQX_normalize(g, T); A = RgXQX_div(A,g, T); y = nfsqff(nf,A,0); av1 = avma; l = lg(y); ex=(GEN)gpmalloc(l * sizeof(long)); for (j=l-1; j>=1; j--) { GEN fact = lift(gel(y,j)), quo = g, q; long e = 0; for(e = 1;; e++) { q = RgXQX_divrem(quo,fact,T, ONLY_DIVIDES); if (!q) break; quo = q; } ex[j] = e; } avma = av1; y = gerepileupto(av, RgXQXV_to_mod(y,T)); p1 = cgetg(l, t_COL); for (j=l-1; j>=1; j--) gel(p1,j) = utoipos(ex[j]); free(ex); } else { y = gerepileupto(av, RgXQXV_to_mod(nfsqff(nf,A,0), T)); l = lg(y); p1 = cgetg(l, t_COL); for (j=l-1; j>=1; j--) gel(p1,j) = gen_1; } if (DEBUGLEVEL>3) fprintferr("number of factor(s) found: %ld\n", lg(y)-1); gel(rep,1) = y; gel(rep,2) = p1; return sort_factor(rep, cmp_pol); }
static long nf_pick_prime(long ct, GEN nf, GEN polbase, long fl, GEN *lt, GEN *Fa, GEN *pr, GEN *Tp) { GEN nfpol = gel(nf,1), dk, bad; long maxf, n = degpol(nfpol), dpol = degpol(polbase), nbf = 0; byteptr pt = diffptr; ulong pp = 0; *lt = leading_term(polbase); /* t_INT */ if (gcmp1(*lt)) *lt = NULL; dk = absi(gel(nf,3)); bad = mulii(dk,gel(nf,4)); if (*lt) bad = mulii(bad, *lt); /* FIXME: slow factorization of large polynomials over large Fq */ maxf = 1; if (ct > 1) { if (dpol > 100) /* tough */ { if (n >= 20) maxf = 4; } else { if (n >= 15) maxf = 4; } } for (ct = 5;;) { GEN aT, apr, ap, modpr, red; long anbf; pari_timer ti_pr; GEN list, r = NULL, fa = NULL; pari_sp av2 = avma; if (DEBUGLEVEL>3) TIMERstart(&ti_pr); for (;;) { NEXT_PRIME_VIADIFF_CHECK(pp, pt); if (! umodiu(bad,pp)) continue; ap = utoipos(pp); list = (GEN)FpX_factor(nfpol, ap)[1]; if (maxf == 1) { /* deg.1 factors are best */ r = gel(list,1); if (degpol(r) == 1) break; } else { /* otherwise, pick factor of largish degree */ long i, dr; for (i = lg(list)-1; i > 0; i--) { r = gel(list,i); dr = degpol(r); if (dr <= maxf) break; } if (i > 0) break; } avma = av2; } apr = primedec_apply_kummer(nf,r,1,ap); modpr = zk_to_ff_init(nf,&apr,&aT,&ap); red = modprX(polbase, nf, modpr); if (!aT) { /* degree 1 */ red = ZX_to_Flx(red, pp); if (!Flx_is_squarefree(red, pp)) { avma = av2; continue; } anbf = fl? Flx_nbroots(red, pp): Flx_nbfact(red, pp); } else { GEN q; if (!FqX_is_squarefree(red,aT,ap)) { avma = av2; continue; } q = gpowgs(ap, degpol(aT)); anbf = fl? FqX_split_deg1(&fa, red, q, aT, ap) : FqX_split_by_degree(&fa, red, q, aT, ap); } if (fl == 2 && anbf < dpol) return anbf; if (anbf <= 1) { if (!fl) return anbf; /* irreducible */ if (!anbf) return 0; /* no root */ } if (!nbf || anbf < nbf || (anbf == nbf && cmpii(gel(apr,4), gel(*pr,4)) > 0)) { nbf = anbf; *pr = apr; *Tp = aT; *Fa = fa; } else avma = av2; if (DEBUGLEVEL>3) fprintferr("%3ld %s at prime\n %Z\nTime: %ld\n", anbf, fl?"roots": "factors", apr, TIMER(&ti_pr)); if (--ct <= 0) return nbf; } }
static GEN nf_LLL_cmbf(nfcmbf_t *T, GEN p, long k, long rec) { nflift_t *L = T->L; GEN pk = L->pk, PRK = L->prk, PRKinv = L->iprk, GSmin = L->GSmin; GEN Tpk = L->Tpk; GEN famod = T->fact, nf = T->nf, ZC = T->ZC, Br = T->Br; GEN Pbase = T->polbase, P = T->pol, dn = T->dn; GEN nfT = gel(nf,1); GEN Btra; long dnf = degpol(nfT), dP = degpol(P); double BitPerFactor = 0.5; /* nb bits / modular factor */ long i, C, tmax, n0; GEN lP, Bnorm, Tra, T2, TT, CM_L, m, list, ZERO; double Bhigh; pari_sp av, av2, lim; long ti_LLL = 0, ti_CF = 0; pari_timer ti2, TI; lP = absi(leading_term(P)); if (is_pm1(lP)) lP = NULL; n0 = lg(famod) - 1; /* Lattice: (S PRK), small vector (vS vP). To find k bound for the image, * write S = S1 q + S0, P = P1 q + P0 * |S1 vS + P1 vP|^2 <= Bhigh for all (vS,vP) assoc. to true factors */ Btra = mulrr(ZC, mulsr(dP*dP, normlp(Br, 2, dnf))); Bhigh = get_Bhigh(n0, dnf); C = (long)ceil(sqrt(Bhigh/n0)) + 1; /* C^2 n0 ~ Bhigh */ Bnorm = dbltor( n0 * C * C + Bhigh ); ZERO = zeromat(n0, dnf); av = avma; lim = stack_lim(av, 1); TT = cgetg(n0+1, t_VEC); Tra = cgetg(n0+1, t_MAT); for (i=1; i<=n0; i++) TT[i] = 0; CM_L = gscalsmat(C, n0); /* tmax = current number of traces used (and computed so far) */ for(tmax = 0;; tmax++) { long a, b, bmin, bgood, delta, tnew = tmax + 1, r = lg(CM_L)-1; GEN oldCM_L, M_L, q, S1, P1, VV; int first = 1; /* bound for f . S_k(genuine factor) = ZC * bound for T_2(S_tnew) */ Btra = mulrr(ZC, mulsr(dP*dP, normlp(Br, 2*tnew, dnf))); bmin = logint(ceil_safe(sqrtr(Btra)), gen_2, NULL); if (DEBUGLEVEL>2) fprintferr("\nLLL_cmbf: %ld potential factors (tmax = %ld, bmin = %ld)\n", r, tmax, bmin); /* compute Newton sums (possibly relifting first) */ if (gcmp(GSmin, Btra) < 0) { nflift_t L1; GEN polred; bestlift_init(k<<1, nf, T->pr, Btra, &L1); polred = ZqX_normalize(Pbase, lP, &L1); k = L1.k; pk = L1.pk; PRK = L1.prk; PRKinv = L1.iprk; GSmin = L1.GSmin; Tpk = L1.Tpk; famod = hensel_lift_fact(polred, famod, Tpk, p, pk, k); for (i=1; i<=n0; i++) TT[i] = 0; } for (i=1; i<=n0; i++) { GEN h, lPpow = lP? gpowgs(lP, tnew): NULL; GEN z = polsym_gen(gel(famod,i), gel(TT,i), tnew, Tpk, pk); gel(TT,i) = z; h = gel(z,tnew+1); /* make Newton sums integral */ lPpow = mul_content(lPpow, dn); if (lPpow) h = FpX_red(gmul(h,lPpow), pk); gel(Tra,i) = nf_bestlift(h, NULL, L); /* S_tnew(famod) */ } /* compute truncation parameter */ if (DEBUGLEVEL>2) { TIMERstart(&ti2); TIMERstart(&TI); } oldCM_L = CM_L; av2 = avma; b = delta = 0; /* -Wall */ AGAIN: M_L = Q_div_to_int(CM_L, utoipos(C)); VV = get_V(Tra, M_L, PRK, PRKinv, pk, &a); if (first) { /* initialize lattice, using few p-adic digits for traces */ bgood = (long)(a - max(32, BitPerFactor * r)); b = max(bmin, bgood); delta = a - b; } else { /* add more p-adic digits and continue reduction */ if (a < b) b = a; b = max(b-delta, bmin); if (b - delta/2 < bmin) b = bmin; /* near there. Go all the way */ } /* restart with truncated entries */ q = int2n(b); P1 = gdivround(PRK, q); S1 = gdivround(Tra, q); T2 = gsub(gmul(S1, M_L), gmul(P1, VV)); m = vconcat( CM_L, T2 ); if (first) { first = 0; m = shallowconcat( m, vconcat(ZERO, P1) ); /* [ C M_L 0 ] * m = [ ] square matrix * [ T2' PRK ] T2' = Tra * M_L truncated */ } CM_L = LLL_check_progress(Bnorm, n0, m, b == bmin, /*dbg:*/ &ti_LLL); if (DEBUGLEVEL>2) fprintferr("LLL_cmbf: (a,b) =%4ld,%4ld; r =%3ld -->%3ld, time = %ld\n", a,b, lg(m)-1, CM_L? lg(CM_L)-1: 1, TIMER(&TI)); if (!CM_L) { list = mkcol(QXQX_normalize(P,nfT)); break; } if (b > bmin) { CM_L = gerepilecopy(av2, CM_L); goto AGAIN; } if (DEBUGLEVEL>2) msgTIMER(&ti2, "for this trace"); i = lg(CM_L) - 1; if (i == r && gequal(CM_L, oldCM_L)) { CM_L = oldCM_L; avma = av2; continue; } if (i <= r && i*rec < n0) { pari_timer ti; if (DEBUGLEVEL>2) TIMERstart(&ti); list = nf_chk_factors(T, P, Q_div_to_int(CM_L,utoipos(C)), famod, pk); if (DEBUGLEVEL>2) ti_CF += TIMER(&ti); if (list) break; CM_L = gerepilecopy(av2, CM_L); } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"nf_LLL_cmbf"); gerepileall(av, Tpk? 9: 8, &CM_L,&TT,&Tra,&famod,&pk,&GSmin,&PRK,&PRKinv,&Tpk); } } if (DEBUGLEVEL>2) fprintferr("* Time LLL: %ld\n* Time Check Factor: %ld\n",ti_LLL,ti_CF); return list; }
int invmod(GEN a, GEN b, GEN *res) #endif { GEN v,v1,d,d1,q,r; pari_sp av, av1, lim; long s; ulong g; ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */ int lhmres; /* Lehmer stage return value */ if (typ(a) != t_INT || typ(b) != t_INT) pari_err(arither1); if (!signe(b)) { *res=absi(a); return 0; } av = avma; if (lgefint(b) == 3) /* single-word affair */ { ulong d1 = umodiu(a, (ulong)(b[2])); if (d1 == 0) { if (b[2] == 1L) { *res = gen_0; return 1; } else { *res = absi(b); return 0; } } g = xgcduu((ulong)(b[2]), d1, 1, &xv, &xv1, &s); #ifdef DEBUG_LEHMER fprintferr(" <- %lu,%lu\n", (ulong)(b[2]), (ulong)(d1[2])); fprintferr(" -> %lu,%ld,%lu; %lx\n", g,s,xv1,avma); #endif avma = av; if (g != 1UL) { *res = utoipos(g); return 0; } xv = xv1 % (ulong)(b[2]); if (s < 0) xv = ((ulong)(b[2])) - xv; *res = utoipos(xv); return 1; } (void)new_chunk(lgefint(b)); d = absi(b); d1 = modii(a,d); v=gen_0; v1=gen_1; /* general case */ #ifdef DEBUG_LEHMER fprintferr("INVERT: -------------------------\n"); output(d1); #endif av1 = avma; lim = stack_lim(av,1); while (lgefint(d) > 3 && signe(d1)) { #ifdef DEBUG_LEHMER fprintferr("Calling Lehmer:\n"); #endif lhmres = lgcdii((ulong*)d, (ulong*)d1, &xu, &xu1, &xv, &xv1, MAXULONG); if (lhmres != 0) /* check progress */ { /* apply matrix */ #ifdef DEBUG_LEHMER fprintferr("Lehmer returned %d [%lu,%lu;%lu,%lu].\n", lhmres, xu, xu1, xv, xv1); #endif if ((lhmres == 1) || (lhmres == -1)) { if (xv1 == 1) { r = subii(d,d1); d=d1; d1=r; a = subii(v,v1); v=v1; v1=a; } else { r = subii(d, mului(xv1,d1)); d=d1; d1=r; a = subii(v, mului(xv1,v1)); v=v1; v1=a; } } else { r = subii(muliu(d,xu), muliu(d1,xv)); a = subii(muliu(v,xu), muliu(v1,xv)); d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r; v1 = subii(muliu(v,xu1), muliu(v1,xv1)); v = a; if (lhmres&1) { setsigne(d,-signe(d)); setsigne(v,-signe(v)); } else { if (signe(d1)) { setsigne(d1,-signe(d1)); } setsigne(v1,-signe(v1)); } } } #ifdef DEBUG_LEHMER else fprintferr("Lehmer returned 0.\n"); output(d); output(d1); output(v); output(v1); sleep(1); #endif if (lhmres <= 0 && signe(d1)) { q = dvmdii(d,d1,&r); #ifdef DEBUG_LEHMER fprintferr("Full division:\n"); printf(" q = "); output(q); sleep (1); #endif a = subii(v,mulii(q,v1)); v=v1; v1=a; d=d1; d1=r; } if (low_stack(lim, stack_lim(av,1))) { GEN *gptr[4]; gptr[0]=&d; gptr[1]=&d1; gptr[2]=&v; gptr[3]=&v1; if(DEBUGMEM>1) pari_warn(warnmem,"invmod"); gerepilemany(av1,gptr,4); } } /* end while */ /* Postprocessing - final sprint */ if (signe(d1)) { /* Assertions: lgefint(d)==lgefint(d1)==3, and * gcd(d,d1) is nonzero and fits into one word */ g = xxgcduu((ulong)d[2], (ulong)d1[2], 1, &xu, &xu1, &xv, &xv1, &s); #ifdef DEBUG_LEHMER output(d);output(d1);output(v);output(v1); fprintferr(" <- %lu,%lu\n", (ulong)d[2], (ulong)d1[2]); fprintferr(" -> %lu,%ld,%lu; %lx\n", g,s,xv1,avma); #endif if (g != 1UL) { avma = av; *res = utoipos(g); return 0; } /* (From the xgcduu() blurb:) * For finishing the multiword modinv, we now have to multiply the * returned matrix (with properly adjusted signs) onto the values * v' and v1' previously obtained from the multiword division steps. * Actually, it is sufficient to take the scalar product of [v',v1'] * with [u1,-v1], and change the sign if s==1. */ v = subii(muliu(v,xu1),muliu(v1,xv1)); if (s > 0) setsigne(v,-signe(v)); avma = av; *res = modii(v,b); #ifdef DEBUG_LEHMER output(*res); fprintfderr("============================Done.\n"); sleep(1); #endif return 1; } /* get here when the final sprint was skipped (d1 was zero already) */ avma = av; if (!equalii(d,gen_1)) { *res = icopy(d); return 0; } *res = modii(v,b); #ifdef DEBUG_LEHMER output(*res); fprintferr("============================Done.\n"); sleep(1); #endif return 1; }
static GEN ell1(GEN ell) { return equaliu(ell,2)? utoipos(5): addiu(ell,1); }
/* d = requested degree for subfield. Return DATA, valid for given pol, S and d * If DATA != NULL, translate pol [ --> pol(X+1) ] and update DATA * 1: polynomial pol * 2: p^e (for Hensel lifts) such that p^e > max(M), * 3: Hensel lift to precision p^e of DATA[4] * 4: roots of pol in F_(p^S->lcm), * 5: number of polynomial changes (translations) * 6: Bezout coefficients associated to the S->ff[i] * 7: Hadamard bound for coefficients of h(x) such that g o h = 0 mod pol. * 8: bound M for polynomials defining subfields x PD->den * 9: *[i] = interpolation polynomial for S->ff[i] [= 1 on the first root S->firstroot[i], 0 on the others] */ static void compute_data(blockdata *B) { GEN ffL, roo, pe, p1, p2, fk, fhk, MM, maxroot, pol; primedata *S = B->S; GEN p = S->p, T = S->T, ff = S->ff, DATA = B->DATA; long i, j, l, e, N, lff = lg(ff); if (DEBUGLEVEL>1) fprintferr("Entering compute_data()\n\n"); pol = B->PD->pol; N = degpol(pol); roo = B->PD->roo; if (DATA) /* update (translate) an existing DATA */ { GEN Xm1 = gsub(pol_x[varn(pol)], gen_1); GEN TR = addis(gel(DATA,5), 1); GEN mTR = negi(TR), interp, bezoutC; gel(DATA,5) = TR; pol = translate_pol(gel(DATA,1), gen_m1); l = lg(roo); p1 = cgetg(l, t_VEC); for (i=1; i<l; i++) gel(p1,i) = gadd(TR, gel(roo,i)); roo = p1; fk = gel(DATA,4); l = lg(fk); for (i=1; i<l; i++) gel(fk,i) = gsub(Xm1, gel(fk,i)); bezoutC = gel(DATA,6); l = lg(bezoutC); interp = gel(DATA,9); for (i=1; i<l; i++) { if (degpol(interp[i]) > 0) /* do not turn pol_1[0] into gen_1 */ { p1 = translate_pol(gel(interp,i), gen_m1); gel(interp,i) = FpXX_red(p1, p); } if (degpol(bezoutC[i]) > 0) { p1 = translate_pol(gel(bezoutC,i), gen_m1); gel(bezoutC,i) = FpXX_red(p1, p); } } ff = cgetg(lff, t_VEC); /* copy, don't overwrite! */ for (i=1; i<lff; i++) gel(ff,i) = FpX_red(translate_pol((GEN)S->ff[i], mTR), p); } else { DATA = cgetg(10,t_VEC); fk = S->fk; gel(DATA,5) = gen_0; gel(DATA,6) = shallowcopy(S->bezoutC); gel(DATA,9) = shallowcopy(S->interp); } gel(DATA,1) = pol; MM = gmul2n(bound_for_coeff(B->d, roo, &maxroot), 1); gel(DATA,8) = MM; e = logint(shifti(vecmax(MM),20), p, &pe); /* overlift 2^20 [for d-1 test] */ gel(DATA,2) = pe; gel(DATA,4) = roots_from_deg1(fk); /* compute fhk = hensel_lift_fact(pol,fk,T,p,pe,e) in 2 steps * 1) lift in Zp to precision p^e */ ffL = hensel_lift_fact(pol, ff, NULL, p, pe, e); fhk = NULL; for (l=i=1; i<lff; i++) { /* 2) lift factorization of ff[i] in Qp[X] / T */ GEN F, L = gel(ffL,i); long di = degpol(L); F = cgetg(di+1, t_VEC); for (j=1; j<=di; j++) F[j] = fk[l++]; L = hensel_lift_fact(L, F, T, p, pe, e); fhk = fhk? shallowconcat(fhk, L): L; } gel(DATA,3) = roots_from_deg1(fhk); p1 = mulsr(N, gsqrt(gpowgs(utoipos(N-1),N-1),DEFAULTPREC)); p2 = gpowgs(maxroot, B->size + N*(N-1)/2); p1 = gdiv(gmul(p1,p2), gsqrt(B->PD->dis,DEFAULTPREC)); gel(DATA,7) = mulii(shifti(ceil_safe(p1), 1), B->PD->den); if (DEBUGLEVEL>1) { fprintferr("f = %Z\n",DATA[1]); fprintferr("p = %Z, lift to p^%ld\n", p, e); fprintferr("2 * Hadamard bound * ind = %Z\n",DATA[7]); fprintferr("2 * M = %Z\n",DATA[8]); } if (B->DATA) { DATA = gclone(DATA); if (isclone(B->DATA)) gunclone(B->DATA); } B->DATA = DATA; }
/* Computation of potential block systems of given size d associated to a * rational prime p: give a row vector of row vectors containing the * potential block systems of imprimitivity; a potential block system is a * vector of row vectors (enumeration of the roots). */ static GEN calc_block(blockdata *B, GEN Z, GEN Y, GEN SB) { long r = lg(Z), lK, i, j, t, tp, T, u, nn, lnon, lY; GEN K, n, non, pn, pnon, e, Yp, Zp, Zpp; pari_sp av0 = avma; if (DEBUGLEVEL>3) { fprintferr("lg(Z) = %ld, lg(Y) = %ld\n", r,lg(Y)); if (DEBUGLEVEL > 5) { fprintferr("Z = %Z\n",Z); fprintferr("Y = %Z\n",Y); } } lnon = min(BIL, r); e = new_chunk(BIL); n = new_chunk(r); non = new_chunk(lnon); pnon = new_chunk(lnon); pn = new_chunk(lnon); Zp = cgetg(lnon,t_VEC); Zpp = cgetg(lnon,t_VEC); nn = 0; for (i=1; i<r; i++) { n[i] = lg(Z[i])-1; nn += n[i]; } lY = lg(Y); Yp = cgetg(lY+1,t_VEC); for (j=1; j<lY; j++) Yp[j] = Y[j]; { pari_sp av = avma; long k = nn / B->size; for (j = 1; j < r; j++) if (n[j] % k) break; if (j == r) { gel(Yp,lY) = Z; SB = print_block_system(B, Yp, SB); avma = av; } } gel(Yp,lY) = Zp; K = divisors(utoipos(n[1])); lK = lg(K); for (i=1; i<lK; i++) { long ngcd = n[1], k = itos(gel(K,i)), dk = B->size*k, lpn = 0; for (j=2; j<r; j++) if (n[j]%k == 0) { if (++lpn >= BIL) pari_err(talker,"overflow in calc_block"); pn[lpn] = n[j]; pnon[lpn] = j; ngcd = cgcd(ngcd, n[j]); } if (dk % ngcd) continue; T = 1<<lpn; if (lpn == r-2) { T--; /* done already above --> print_block_system */ if (!T) continue; } if (dk == n[1]) { /* empty subset, t = 0. Split out for clarity */ Zp[1] = Z[1]; setlg(Zp, 2); for (u=1,j=2; j<r; j++) Zpp[u++] = Z[j]; setlg(Zpp, u); SB = calc_block(B, Zpp, Yp, SB); } for (t = 1; t < T; t++) { /* loop through all non-empty subsets of [1..lpn] */ for (nn=n[1],tp=t, u=1; u<=lpn; u++,tp>>=1) { if (tp&1) { nn += pn[u]; e[u] = 1; } else e[u] = 0; } if (dk != nn) continue; for (j=1; j<r; j++) non[j]=0; Zp[1] = Z[1]; for (u=2,j=1; j<=lpn; j++) if (e[j]) { Zp[u] = Z[pnon[j]]; non[pnon[j]] = 1; u++; } setlg(Zp, u); for (u=1,j=2; j<r; j++) if (!non[j]) Zpp[u++] = Z[j]; setlg(Zpp, u); SB = calc_block(B, Zpp, Yp, SB); } } avma = av0; return SB; }