static GEN real_read(pari_sp av, const char **s, GEN y, long prec) { long l, n = 0; switch(**s) { default: return y; /* integer */ case '.': { const char *old = ++*s; if (isalpha((int)**s) || **s=='.') { if (**s == 'E' || **s == 'e') { n = exponent(s); if (!signe(y)) { avma = av; return real_0_digits(n); } break; } --*s; return y; /* member */ } y = int_read_more(y, s); n = old - *s; if (**s != 'E' && **s != 'e') { if (!signe(y)) { avma = av; return real_0(prec); } break; } } /* Fall through */ case 'E': case 'e': n += exponent(s); if (!signe(y)) { avma = av; return real_0_digits(n); } } l = nbits2prec(bit_accuracy(lgefint(y))); if (l < prec) l = prec; else prec = l; if (!n) return itor(y, prec); incrprec(l); y = itor(y, l); if (n > 0) y = mulrr(y, rpowuu(10UL, (ulong)n, l)); else y = divrr(y, rpowuu(10UL, (ulong)-n, l)); return gerepileuptoleaf(av, rtor(y, prec)); }
/* 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; }
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; }