int galoisTest(){ uint8_t a,b,c; int isOk = true; // Addition : a = 0x01; b = 0x0A; c = 0x0B; if((gadd(a,b) != c)){ printf("Galois addition failed\n"); isOk = false; } // Multiplication : if((gmul(a,b) != b) || (gmul(0x02, 0x02)!=0x04) ){ printf("Galois multiplication failed\n"); isOk = false; } // Division : if((gdiv(b,a) != b) || (gdiv(0x02, 0x02)!=0x01)){ printf("Galois division failed\n"); isOk = false; } return isOk; }
void rowReduce(uint8_t* row, uint8_t factor, int size){ // Reduce a row st row[i] = row[i] / factor if(factor != 0x01){ int i; for(i = 0; i < size ; i++){ row[i] = gdiv(row[i], factor); } } }
/* g in Z[X] potentially defines a subfield of Q[X]/f. It is a subfield iff A * (cf subfield) was a block system; then there * exists h in Q[X] such that f | g o h. listdelta determines h s.t f | g o h * in Fp[X] (cf chinese_retrieve_pol). Try to lift it; den is a * multiplicative bound for denominator of lift. */ static GEN embedding(GEN g, GEN DATA, primedata *S, GEN den, GEN listdelta) { GEN TR, w0_Q, w0, w1_Q, w1, wpow, h0, gp, T, q2, q, maxp, a, p = S->p; long rt; pari_sp av; T = gel(DATA,1); rt = brent_kung_optpow(degpol(T), 2); maxp= gel(DATA,7); gp = derivpol(g); av = avma; w0 = chinese_retrieve_pol(DATA, S, listdelta); w0_Q = centermod(gmul(w0,den), p); h0 = FpXQ_inv(FpX_FpXQ_compo(gp,w0, T,p), T,p); /* = 1/g'(w0) mod (T,p) */ wpow = NULL; q = sqri(p); for(;;) {/* Given g,w0,h0 in Z[x], s.t. h0.g'(w0) = 1 and g(w0) = 0 mod (T,p), find * [w1,h1] satisfying the same conditions mod p^2, [w1,h1] = [w0,h0] (mod p) * (cf. Dixon: J. Austral. Math. Soc., Series A, vol.49, 1990, p.445) */ if (DEBUGLEVEL>1) fprintferr("lifting embedding mod p^k = %Z^%ld\n",p, Z_pval(q,p)); /* w1 := w0 - h0 g(w0) mod (T,q) */ if (wpow) a = FpX_FpXQV_compo(g,wpow, T,q); else a = FpX_FpXQ_compo(g,w0, T,q); /* first time */ /* now, a = 0 (p) */ a = gmul(gneg(h0), gdivexact(a, p)); w1 = gadd(w0, gmul(p, FpX_rem(a, T,p))); w1_Q = centermod(gmul(w1, remii(den,q)), q); if (gequal(w1_Q, w0_Q) || cmpii(q,maxp) > 0) { GEN G = gcmp1(den)? g: RgX_rescale(g,den); if (gcmp0(RgX_RgXQ_compo(G, w1_Q, T))) break; } if (cmpii(q, maxp) > 0) { if (DEBUGLEVEL) fprintferr("coeff too big for embedding\n"); return NULL; } gerepileall(av, 5, &w1,&h0,&w1_Q,&q,&p); q2 = sqri(q); wpow = FpXQ_powers(w1, rt, T, q2); /* h0 := h0 * (2 - h0 g'(w1)) mod (T,q) * = h0 + h0 * (1 - h0 g'(w1)) */ a = gmul(gneg(h0), FpX_FpXQV_compo(gp, FpXV_red(wpow,q),T,q)); a = ZX_Z_add(FpX_rem(a, T,q), gen_1); /* 1 - h0 g'(w1) = 0 (p) */ a = gmul(h0, gdivexact(a, p)); h0 = gadd(h0, gmul(p, FpX_rem(a, T,p))); w0 = w1; w0_Q = w1_Q; p = q; q = q2; } TR = gel(DATA,5); if (!gcmp0(TR)) w1_Q = translate_pol(w1_Q, TR); return gdiv(w1_Q,den); }
static void bestlift_init(long a, GEN nf, GEN pr, GEN C, nflift_t *L) { const long D = 100; const double alpha = ((double)D-1) / D; /* LLL parameter */ const long d = degpol(nf[1]); pari_sp av = avma; GEN prk, PRK, B, GSmin, pk; pari_timer ti; TIMERstart(&ti); if (!a) a = (long)bestlift_bound(C, d, alpha, pr_norm(pr)); for (;; avma = av, a<<=1) { if (DEBUGLEVEL>2) fprintferr("exponent: %ld\n",a); PRK = prk = idealpows(nf, pr, a); pk = gcoeff(prk,1,1); /* reduce size first, "scramble" matrix */ PRK = lllintpartial_ip(PRK); /* now floating point reduction is fast */ PRK = lllint_fp_ip(PRK, 4); PRK = lllint_i(PRK, D, 0, NULL, NULL, &B); if (!PRK) { PRK = prk; GSmin = pk; } /* nf = Q */ else { pari_sp av2 = avma; GEN S = invmat( get_R(PRK) ), BB = GS_norms(B, DEFAULTPREC); GEN smax = gen_0; long i, j; for (i=1; i<=d; i++) { GEN s = gen_0; for (j=1; j<=d; j++) s = gadd(s, gdiv( gsqr(gcoeff(S,i,j)), gel(BB,j))); if (gcmp(s, smax) > 0) smax = s; } GSmin = gerepileupto(av2, ginv(gmul2n(smax, 2))); } if (gcmp(GSmin, C) >= 0) break; } if (DEBUGLEVEL>2) fprintferr("for this exponent, GSmin = %Z\nTime reduction: %ld\n", GSmin, TIMER(&ti)); L->k = a; L->den = L->pk = pk; L->prk = PRK; L->iprk = ZM_inv(PRK, pk); L->GSmin= GSmin; L->prkHNF = prk; init_proj(L, gel(nf,1), gel(pr,1)); }
/* return a bound for T_2(P), P | polbase * max |b_i|^2 <= 3^{3/2 + d} / (4 \pi d) [P]_2, * where [P]_2 is Bombieri's 2-norm * Sum over conjugates */ static GEN nf_Beauzamy_bound(GEN nf, GEN polbase) { GEN lt,C,run,s, G = gmael(nf,5,2), POL, bin; long i,prec,precnf, d = degpol(polbase), n = degpol(nf[1]); precnf = gprecision(G); prec = MEDDEFAULTPREC; bin = vecbinome(d); POL = polbase + 2; /* compute [POL]_2 */ for (;;) { run= real_1(prec); s = real_0(prec); for (i=0; i<=d; i++) { GEN p1 = gnorml2(arch_for_T2(G, gmul(run, gel(POL,i)))); /* T2(POL[i]) */ if (!signe(p1)) continue; if (lg(p1) == 3) break; /* s += T2(POL[i]) / binomial(d,i) */ s = addrr(s, gdiv(p1, gel(bin,i+1))); } if (i > d) break; prec = (prec<<1)-2; if (prec > precnf) { nffp_t F; remake_GM(nf, &F, prec); G = F.G; if (DEBUGLEVEL>1) pari_warn(warnprec, "nf_factor_bound", prec); } } lt = leading_term(polbase); s = gmul(s, mulis(sqri(lt), n)); C = powrshalf(stor(3,DEFAULTPREC), 3 + 2*d); /* 3^{3/2 + d} */ return gdiv(gmul(C, s), gmulsg(d, mppi(DEFAULTPREC))); }
static GEN QXQX_normalize(GEN P, GEN T) { GEN P0 = leading_term(P); if (!gcmp1(P0)) { long t = typ(P0); if (t == t_POL && !degpol(P0)) P0 = gel(P0,2); if (is_rational_t(t)) P = gdiv(P, P0); else P = RgXQX_RgXQ_mul(P, QXQ_inv(P0,T), T); } return P; }
/* log N_{F_P/Q_p}(x) / deg_F P */ static GEN vtilde_i(GEN K, GEN x, GEN T, GEN deg, GEN ell, long prec) { GEN L, N, cx; if (typ(x) != t_POL) x = nf_to_scalar_or_alg(K, x); x = Q_primitive_part(x,&cx); N = RgXQ_norm(x, T); L = Qp_log(cvtop(N,ell,prec)); if (cx) { Q_pvalrem(cx, ell, &cx); if (!isint1(cx)) L = gadd(L, gmulsg(degpol(T), Qp_log(cvtop(cx,ell,prec)))); } return gdiv(L, deg); }
int do_factor(GEN n, long prec) { pari_sp ltop; GEN sq = gfloor(gsqrt(n, prec)); GEN q = stoi(2); ltop = avma; for (;;) { if (cmpii(q, sq) > 0) return -1; if (equalsi(0, gmod(n, q))) { pari_printf("%Ps = %Ps * %Ps\n", n, q, gdiv(n, q)); return 0; } gaddz(gen_1, q, q); avma = ltop; } }
static GEN nf_DDF_roots(GEN pol, GEN polred, GEN nfpol, GEN lt, GEN init_fa, long nbf, long fl, nflift_t *L) { long Cltx_r[] = { evaltyp(t_POL)|_evallg(4), 0,0,0 }; long i, m; GEN C2ltpol, C = L->topowden; GEN Clt = mul_content(C, lt); GEN C2lt = mul_content(C,Clt); GEN z; if (L->Tpk) { int cof = (degpol(pol) > nbf); /* non trivial cofactor ? */ z = FqX_split_roots(init_fa, L->Tp, L->p, cof? polred: NULL); z = hensel_lift_fact(polred, z, L->Tpk, L->p, L->pk, L->k); if (cof) setlg(z, lg(z)-1); /* remove cofactor */ z = roots_from_deg1(z); } else z = rootpadicfast(polred, L->p, L->k); Cltx_r[1] = evalsigne(1) | evalvarn(varn(pol)); gel(Cltx_r,3) = Clt? Clt: gen_1; C2ltpol = C2lt? gmul(C2lt, pol): pol; for (m=1,i=1; i<lg(z); i++) { GEN q, r = gel(z,i); r = nf_bestlift_to_pol(lt? gmul(lt,r): r, NULL, L); gel(Cltx_r,2) = gneg(r); /* check P(r) == 0 */ q = RgXQX_divrem(C2ltpol, Cltx_r, nfpol, ONLY_DIVIDES); /* integral */ if (q) { C2ltpol = C2lt? gmul(Clt,q): q; if (Clt) r = gdiv(r, Clt); gel(z,m++) = r; } else if (fl == 2) return cgetg(1, t_VEC); } z[0] = evaltyp(t_VEC) | evallg(m); return z; }
/* return the roots of pol in nf */ GEN nfroots(GEN nf,GEN pol) { pari_sp av = avma; GEN A,g, T; long d; if (!nf) return nfrootsQ(pol); nf = checknf(nf); T = gel(nf,1); if (typ(pol) != t_POL) pari_err(notpoler,"nfroots"); if (varncmp(varn(pol), varn(T)) >= 0) pari_err(talker,"polynomial variable must have highest priority in nfroots"); d = degpol(pol); if (d == 0) return cgetg(1,t_VEC); if (d == 1) { A = gneg_i(gdiv(gel(pol,2),gel(pol,3))); return gerepilecopy(av, mkvec( basistoalg(nf,A) )); } A = fix_relative_pol(nf,pol,0); A = Q_primpart( lift_intern(A) ); if (DEBUGLEVEL>3) fprintferr("test if polynomial is square-free\n"); g = nfgcd(A, derivpol(A), T, gel(nf,4)); if (degpol(g)) { /* not squarefree */ g = QXQX_normalize(g, T); A = RgXQX_div(A,g,T); } A = QXQX_normalize(A, T); A = Q_primpart(A); A = nfsqff(nf,A,1); A = RgXQV_to_mod(A, T); return gerepileupto(av, gen_sort(A, 0, cmp_pol)); }
/* return the factorization of the square-free polynomial x. The coeffs of x are in Z_nf and its leading term is a rational integer. deg(x) > 1, deg(nfpol) > 1 If fl = 1, return only the roots of x in nf If fl = 2, as fl=1 if pol splits, [] otherwise */ static GEN nfsqff(GEN nf, GEN pol, long fl) { long n, nbf, dpol = degpol(pol); GEN pr, C0, polbase, init_fa = NULL; GEN N2, rep, polmod, polred, lt, nfpol = gel(nf,1); nfcmbf_t T; nflift_t L; pari_timer ti, ti_tot; if (DEBUGLEVEL>2) { TIMERstart(&ti); TIMERstart(&ti_tot); } n = degpol(nfpol); polbase = unifpol(nf, pol, t_COL); if (typ(polbase) != t_POL) pari_err(typeer, "nfsqff"); polmod = lift_intern( unifpol(nf, pol, t_POLMOD) ); if (dpol == 1) return mkvec(QXQX_normalize(polmod, nfpol)); /* heuristic */ if (dpol*3 < n) { GEN z, t; long i; if (DEBUGLEVEL>2) fprintferr("Using Trager's method\n"); z = (GEN)polfnf(polmod, nfpol)[1]; if (fl) { long l = lg(z); for (i = 1; i < l; i++) { t = gel(z,i); if (degpol(t) > 1) break; gel(z,i) = gneg(gdiv(gel(t,2), gel(t,3))); } setlg(z, i); if (fl == 2 && i != l) return cgetg(1,t_VEC); } return z; } nbf = nf_pick_prime(5, nf, polbase, fl, <, &init_fa, &pr, &L.Tp); if (fl == 2 && nbf < dpol) return cgetg(1,t_VEC); if (nbf <= 1) { if (!fl) return mkvec(QXQX_normalize(polmod, nfpol)); /* irreducible */ if (!nbf) return cgetg(1,t_VEC); /* no root */ } if (DEBUGLEVEL>2) { msgTIMER(&ti, "choice of a prime ideal"); fprintferr("Prime ideal chosen: %Z\n", pr); } pol = simplify_i(lift(polmod)); L.tozk = gel(nf,8); L.topow= Q_remove_denom(gel(nf,7), &L.topowden); T.ZC = L2_bound(nf, L.tozk, &(T.dn)); T.Br = nf_root_bounds(pol, nf); if (lt) T.Br = gmul(T.Br, lt); if (fl) C0 = normlp(T.Br, 2, n); else C0 = nf_factor_bound(nf, polbase); /* bound for T_2(Q_i), Q | P */ T.bound = mulrr(T.ZC, C0); /* bound for |Q_i|^2 in Z^n on chosen Z-basis */ N2 = mulsr(dpol*dpol, normlp(T.Br, 4, n)); /* bound for T_2(lt * S_2) */ T.BS_2 = mulrr(T.ZC, N2); /* bound for |S_2|^2 on chosen Z-basis */ if (DEBUGLEVEL>2) { msgTIMER(&ti, "bound computation"); fprintferr(" 1) T_2 bound for %s: %Z\n", fl?"root":"factor", C0); fprintferr(" 2) Conversion from T_2 --> | |^2 bound : %Z\n", T.ZC); fprintferr(" 3) Final bound: %Z\n", T.bound); } L.p = gel(pr,1); if (L.Tp && degpol(L.Tp) == 1) L.Tp = NULL; bestlift_init(0, nf, pr, T.bound, &L); if (DEBUGLEVEL>2) TIMERstart(&ti); polred = ZqX_normalize(polbase, lt, &L); /* monic */ if (fl) { GEN z = nf_DDF_roots(pol, polred, nfpol, lt, init_fa, nbf, fl, &L); if (lg(z) == 1) return cgetg(1, t_VEC); return z; } { pari_sp av = avma; if (L.Tp) rep = FqX_split_all(init_fa, L.Tp, L.p); else { long d; rep = cgetg(dpol + 1, t_VEC); gel(rep,1) = FpX_red(polred,L.p); d = FpX_split_Berlekamp((GEN*)(rep + 1), L.p); setlg(rep, d + 1); } T.fact = gerepilecopy(av, sort_vecpol(rep, &cmp_pol)); } if (DEBUGLEVEL>2) msgTIMER(&ti, "splitting mod %Z", pr); T.pr = pr; T.L = &L; T.polbase = polbase; T.pol = pol; T.nf = nf; T.hint = 1; /* useless */ rep = nf_combine_factors(&T, polred, L.p, L.k, dpol-1); if (DEBUGLEVEL>2) fprintferr("Total Time: %ld\n===========\n", TIMER(&ti_tot)); return rep; }
GEN gdive(GEN *x, GEN y) { *x=gdiv(*x,y); return *x; }
/* 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; }