Line data Source code
1 : /* Copyright (C) 2000-2004 The PARI group.
2 :
3 : This file is part of the PARI/GP package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation. It is distributed in the hope that it will be useful, but WITHOUT
8 : ANY WARRANTY WHATSOEVER.
9 :
10 : Check the License for details. You should have received a copy of it, along
11 : with the package; see the file 'COPYING'. If not, write to the Free Software
12 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
13 :
14 : /*******************************************************************/
15 : /* */
16 : /* POLYNOMIAL FACTORIZATION IN A NUMBER FIELD */
17 : /* */
18 : /*******************************************************************/
19 : #include "pari.h"
20 : #include "paripriv.h"
21 :
22 : static GEN nfsqff(GEN nf,GEN pol,long fl,GEN den);
23 : static int nfsqff_use_Trager(long n, long dpol);
24 :
25 : enum { FACTORS = 0, ROOTS, ROOTS_SPLIT };
26 :
27 : /* for nf_bestlift: reconstruction of algebraic integers known mod P^k,
28 : * P maximal ideal above p */
29 : typedef struct {
30 : long k; /* input known mod P^k */
31 : GEN p, pk; /* p^k = denom(prk^-1) [ assume pr unramified ]*/
32 : GEN prk; /* |.|^2 LLL-reduced basis (b_i) of P^k (NOT T2-reduced) */
33 : GEN iprk; /* den * prk^-1 */
34 : GEN GSmin; /* min |b_i^*|^2 */
35 :
36 : GEN Tp; /* Tpk mod p */
37 : GEN Tpk;
38 : GEN ZqProj;/* projector to Zp / P^k = Z/p^k[X] / Tpk */
39 :
40 : GEN tozk;
41 : GEN topow;
42 : GEN topowden; /* topow x / topowden = basistoalg(x) */
43 : GEN dn; /* NULL (we trust nf.zk) or a t_INT > 1 (an alg. integer has
44 : denominator dividing dn, when expressed on nf.zk */
45 : } nflift_t;
46 :
47 : typedef struct
48 : {
49 : nflift_t *L;
50 : GEN nf;
51 : GEN pol, polbase; /* leading coeff is a t_INT */
52 : GEN fact;
53 : GEN Br, bound, ZC, BS_2;
54 : } nfcmbf_t;
55 :
56 : /*******************************************************************/
57 : /* RATIONAL RECONSTRUCTION (use ratlift) */
58 : /*******************************************************************/
59 : /* NOT stack clean. a, b stay on the stack */
60 : static GEN
61 12943001 : lift_to_frac_tdenom(GEN t, GEN mod, GEN amax, GEN bmax, GEN denom, GEN tdenom)
62 : {
63 : GEN a, b;
64 12943001 : if (signe(t) < 0) t = addii(t, mod); /* in case t is a centerlift */
65 12943001 : if (tdenom)
66 : {
67 10967937 : pari_sp av = avma;
68 10967937 : a = Fp_center_i(Fp_mul(t, tdenom, mod), mod, shifti(mod,-1));
69 10967937 : if (abscmpii(a, amax) < 0)
70 : {
71 10481160 : GEN d = gcdii(a, tdenom);
72 10481160 : a = diviiexact(a, d);
73 10481160 : b = diviiexact(tdenom, d);
74 10481160 : if (is_pm1(b)) { return gerepileuptoint(av, a); }
75 1482154 : return gerepilecopy(av, mkfrac(a, b));
76 : }
77 486777 : avma = av;
78 : }
79 2461841 : if (!Fp_ratlift(t, mod, amax,bmax, &a,&b)
80 2381013 : || (denom && !dvdii(denom,b))
81 2379504 : || !is_pm1(gcdii(a,b))) return NULL;
82 2379408 : if (is_pm1(b)) { cgiv(b); return a; }
83 1116128 : return mkfrac(a, b);
84 : }
85 :
86 : static GEN
87 120154 : lift_to_frac(GEN t, GEN mod, GEN amax, GEN bmax, GEN denom)
88 : {
89 120154 : return lift_to_frac_tdenom(t, mod, amax, bmax, denom, NULL);
90 : }
91 :
92 : /* Compute rational lifting for all the components of M modulo mod.
93 : * Assume all Fp_ratlift preconditions are met; we allow centerlifts but in
94 : * that case are no longer stack clean. If one component fails, return NULL.
95 : * If denom != NULL, check that the denominators divide denom.
96 : *
97 : * We suppose gcd(mod, denom) = 1, then a and b are coprime; so we can use
98 : * mkfrac rather than gdiv */
99 : GEN
100 1854910 : FpC_ratlift(GEN P, GEN mod, GEN amax, GEN bmax, GEN denom)
101 : {
102 1854910 : pari_sp ltop = avma;
103 : long j, l;
104 1854910 : GEN a, d, tdenom = NULL, Q = cgetg_copy(P, &l);
105 1854910 : if (l==1) return Q;
106 14602305 : for (j = 1; j < l; ++j)
107 : {
108 12822847 : a = lift_to_frac_tdenom(gel(P,j), mod, amax, bmax, denom, tdenom);
109 12822847 : if (!a) { avma = ltop; return NULL; }
110 12747395 : d = Q_denom(a);
111 12747395 : tdenom = tdenom ? cmpii(tdenom, d)<0? d: tdenom : d;
112 12747395 : gel(Q,j) = a;
113 : }
114 1779458 : return Q;
115 : }
116 :
117 : GEN
118 900515 : FpM_ratlift(GEN M, GEN mod, GEN amax, GEN bmax, GEN denom)
119 : {
120 900515 : pari_sp av = avma;
121 900515 : long j, l = lg(M);
122 900515 : GEN N = cgetg_copy(M, &l);
123 900515 : if (l == 1) return N;
124 2636020 : for (j = 1; j < l; ++j)
125 : {
126 1854910 : GEN a = FpC_ratlift(gel(M, j), mod, amax, bmax, denom);
127 1854910 : if (!a) { avma = av; return NULL; }
128 1779458 : gel(N,j) = a;
129 : }
130 781110 : return N;
131 : }
132 :
133 : GEN
134 46394 : FpX_ratlift(GEN P, GEN mod, GEN amax, GEN bmax, GEN denom)
135 : {
136 46394 : pari_sp ltop = avma;
137 : long j, l;
138 46394 : GEN a, Q = cgetg_copy(P, &l);
139 46394 : Q[1] = P[1];
140 159567 : for (j = 2; j < l; ++j)
141 : {
142 120154 : a = lift_to_frac(gel(P,j), mod, amax,bmax,denom);
143 120154 : if (!a) { avma = ltop; return NULL; }
144 113173 : gel(Q,j) = a;
145 : }
146 39413 : return Q;
147 : }
148 :
149 : /*******************************************************************/
150 : /* GCD in K[X], K NUMBER FIELD */
151 : /*******************************************************************/
152 : /* P,Q in Z[X,Y], T in Z[Y] irreducible. compute GCD in Q[Y]/(T)[X].
153 : *
154 : * M. Encarnacion "On a modular Algorithm for computing GCDs of polynomials
155 : * over number fields" (ISSAC'94).
156 : *
157 : * We procede as follows
158 : * 1:compute the gcd modulo primes discarding bad primes as they are detected.
159 : * 2:reconstruct the result via FpM_ratlift, stoping as soon as we get weird
160 : * denominators.
161 : * 3:if FpM_ratlift succeeds, try the full division.
162 : * Suppose accuracy is insufficient to get the result right: FpM_ratlift will
163 : * rarely succeed, and even if it does the polynomial we get has sensible
164 : * coefficients, so the full division will not be too costly.
165 : *
166 : * If not NULL, den must be a multiple of the denominator of the gcd,
167 : * for example the discriminant of T.
168 : *
169 : * NOTE: if T is not irreducible, nfgcd may loop forever, esp. if gcd | T */
170 : GEN
171 8415 : nfgcd_all(GEN P, GEN Q, GEN T, GEN den, GEN *Pnew)
172 : {
173 8415 : pari_sp btop, ltop = avma;
174 8415 : GEN lP, lQ, M, dsol, R, bo, sol, mod = NULL, lden = NULL;
175 8415 : long vP = varn(P), vT = varn(T), dT = degpol(T), dM = 0, dR;
176 : forprime_t S;
177 :
178 8415 : if (!signe(P)) { if (Pnew) *Pnew = pol_0(vT); return gcopy(Q); }
179 8415 : if (!signe(Q)) { if (Pnew) *Pnew = pol_1(vT); return gcopy(P); }
180 : /*Compute denominators*/
181 8331 : lP = leading_coeff(P);
182 8331 : lQ = leading_coeff(Q);
183 8331 : if ( !((typ(lP)==t_INT && is_pm1(lP)) || (typ(lQ)==t_INT && is_pm1(lQ))) )
184 : {
185 3304 : lden = gcdii(ZX_resultant(lP, T), ZX_resultant(lQ, T));
186 3304 : if (den) den = mulii(den, lden);
187 : }
188 :
189 8331 : init_modular_small(&S);
190 8331 : btop = avma;
191 : for(;;)
192 : {
193 9491 : ulong p = u_forprime_next(&S);
194 : GEN Tp;
195 9491 : if (!p) pari_err_OVERFLOW("nfgcd [ran out of primes]");
196 : /*Discard primes dividing disc(T) or lc(PQ) */
197 9491 : if (lden && !umodiu(lden, p)) continue;
198 9491 : Tp = ZX_to_Flx(T,p);
199 9491 : if (!Flx_is_squarefree(Tp, p)) continue;
200 : /*Discard primes when modular gcd does not exist*/
201 9491 : if ((R = FlxqX_safegcd(ZXX_to_FlxX(P,p,vT),
202 : ZXX_to_FlxX(Q,p,vT),
203 0 : Tp, p)) == NULL) continue;
204 9491 : dR = degpol(R);
205 9491 : if (dR == 0) { avma = ltop; if (Pnew) *Pnew = P; return pol_1(vP); }
206 1853 : if (mod && dR > dM) continue; /* p divides Res(P/gcd, Q/gcd). Discard. */
207 :
208 1853 : R = FlxX_to_Flm(R, dT);
209 : /* previous primes divided Res(P/gcd, Q/gcd)? Discard them. */
210 1853 : if (!mod || dR < dM) { M = ZM_init_CRT(R, p); mod = utoipos(p); dM = dR; continue; }
211 1160 : (void)ZM_incremental_CRT(&M,R, &mod,p);
212 1160 : if (gc_needed(btop, 1))
213 : {
214 0 : if (DEBUGMEM>1) pari_warn(warnmem,"nfgcd");
215 0 : gerepileall(btop, 2, &M, &mod);
216 : }
217 : /* I suspect it must be better to take amax > bmax*/
218 1160 : bo = sqrti(shifti(mod, -1));
219 1160 : if ((sol = FpM_ratlift(M, mod, bo, bo, den)) == NULL) continue;
220 693 : sol = RgM_to_RgXX(sol,vP,vT);
221 693 : dsol = Q_primpart(sol);
222 :
223 693 : if (!ZXQX_dvd(Q, dsol, T)) continue;
224 693 : if (Pnew)
225 : {
226 168 : *Pnew = RgXQX_pseudodivrem(P, dsol, T, &R);
227 168 : if (signe(R)) continue;
228 : }
229 : else
230 : {
231 525 : if (!ZXQX_dvd(P, dsol, T)) continue;
232 : }
233 693 : gerepileall(ltop, Pnew? 2: 1, &dsol, Pnew);
234 693 : return dsol; /* both remainders are 0 */
235 1160 : }
236 : }
237 : GEN
238 2296 : nfgcd(GEN P, GEN Q, GEN T, GEN den)
239 2296 : { return nfgcd_all(P,Q,T,den,NULL); }
240 :
241 : int
242 2198 : nfissquarefree(GEN nf, GEN x)
243 : {
244 2198 : pari_sp av = avma;
245 2198 : GEN g, y = RgX_deriv(x);
246 2198 : if (RgX_is_rational(x))
247 749 : g = QX_gcd(x, y);
248 : else
249 : {
250 1449 : GEN T = get_nfpol(nf,&nf);
251 1449 : x = Q_primpart( liftpol_shallow(x) );
252 1449 : y = Q_primpart( liftpol_shallow(y) );
253 1449 : g = nfgcd(x, y, T, nf? nf_get_index(nf): NULL);
254 : }
255 2198 : avma = av; return (degpol(g) == 0);
256 : }
257 :
258 : /*******************************************************************/
259 : /* FACTOR OVER (Z_K/pr)[X] --> FqX_factor */
260 : /*******************************************************************/
261 : GEN
262 7 : nffactormod(GEN nf, GEN x, GEN pr)
263 : {
264 7 : long j, l, vx = varn(x), vn;
265 7 : pari_sp av = avma;
266 : GEN F, E, rep, xrd, modpr, T, p;
267 :
268 7 : nf = checknf(nf);
269 7 : vn = nf_get_varn(nf);
270 7 : if (typ(x)!=t_POL) pari_err_TYPE("nffactormod",x);
271 7 : if (varncmp(vx,vn) >= 0) pari_err_PRIORITY("nffactormod", x, ">=", vn);
272 :
273 7 : modpr = nf_to_Fq_init(nf, &pr, &T, &p);
274 7 : xrd = nfX_to_FqX(x, nf, modpr);
275 7 : rep = FqX_factor(xrd,T,p);
276 7 : settyp(rep, t_MAT);
277 7 : F = gel(rep,1); l = lg(F);
278 7 : E = gel(rep,2); settyp(E, t_COL);
279 14 : for (j = 1; j < l; j++) {
280 7 : gel(F,j) = FqX_to_nfX(gel(F,j), modpr);
281 7 : gel(E,j) = stoi(E[j]);
282 : }
283 7 : return gerepilecopy(av, rep);
284 : }
285 :
286 : /*******************************************************************/
287 : /* MAIN ROUTINES nfroots / nffactor */
288 : /*******************************************************************/
289 : static GEN
290 6854 : QXQX_normalize(GEN P, GEN T)
291 : {
292 6854 : GEN P0 = leading_coeff(P);
293 6854 : long t = typ(P0);
294 6854 : if (t == t_POL)
295 : {
296 1197 : if (degpol(P0)) return RgXQX_RgXQ_mul(P, QXQ_inv(P0,T), T);
297 441 : P0 = gel(P0,2); t = typ(P0);
298 : }
299 : /* t = t_INT/t_FRAC */
300 6098 : if (t == t_INT && is_pm1(P0) && signe(P0) > 0) return P; /* monic */
301 2660 : return RgX_Rg_div(P, P0);
302 : }
303 : /* assume leading term of P is an integer */
304 : static GEN
305 2828 : RgX_int_normalize(GEN P)
306 : {
307 2828 : GEN P0 = leading_coeff(P);
308 : /* cater for t_POL */
309 2828 : if (typ(P0) == t_POL)
310 : {
311 59 : P0 = gel(P0,2); /* non-0 constant */
312 59 : P = shallowcopy(P);
313 59 : gel(P,lg(P)-1) = P0; /* now leading term is a t_INT */
314 : }
315 2828 : if (typ(P0) != t_INT) pari_err_BUG("RgX_int_normalize");
316 2828 : if (is_pm1(P0)) return signe(P0) > 0? P: RgX_neg(P);
317 1806 : return RgX_Rg_div(P, P0);
318 : }
319 :
320 : /* discard change of variable if nf is of the form [nf,c] as return by nfinit
321 : * for non-monic polynomials */
322 : static GEN
323 847 : proper_nf(GEN nf)
324 847 : { return (lg(nf) == 3)? gel(nf,1): nf; }
325 :
326 : /* if *pnf = NULL replace if by a "quick" K = nfinit(T), ensuring maximality
327 : * by small primes only. Return a multiplicative bound for the denominator of
328 : * algebraic integers in Z_K in terms of K.zk */
329 : static GEN
330 5944 : fix_nf(GEN *pnf, GEN *pT, GEN *pA)
331 : {
332 5944 : GEN nf, NF, fa, P, Q, q, D, T = *pT;
333 : nfmaxord_t S;
334 : long i, l;
335 :
336 5944 : if (*pnf) return gen_1;
337 847 : nfmaxord(&S, T, nf_PARTIALFACT);
338 847 : NF = nfinit_complete(&S, 0, DEFAULTPREC);
339 847 : *pnf = nf = proper_nf(NF);
340 847 : if (nf != NF) { /* t_POL defining base field changed (not monic) */
341 35 : GEN A = *pA, a = cgetg_copy(A, &l);
342 35 : GEN rev = gel(NF,2), pow, dpow;
343 :
344 35 : *pT = T = nf_get_pol(nf); /* need to update T */
345 35 : pow = QXQ_powers(lift_shallow(rev), degpol(T)-1, T);
346 35 : pow = Q_remove_denom(pow, &dpow);
347 35 : a[1] = A[1];
348 154 : for (i=2; i<l; i++) {
349 119 : GEN c = gel(A,i);
350 119 : if (typ(c) == t_POL) c = QX_ZXQV_eval(c, pow, dpow);
351 119 : gel(a,i) = c;
352 : }
353 35 : *pA = Q_primpart(a); /* need to update A */
354 : }
355 :
356 847 : D = nf_get_disc(nf);
357 847 : if (is_pm1(D)) return gen_1;
358 840 : fa = absZ_factor_limit(D, 0);
359 840 : P = gel(fa,1); q = gel(P, lg(P)-1);
360 840 : if (BPSW_psp(q)) return gen_1;
361 : /* nf_get_disc(nf) may be incorrect */
362 7 : P = nf_get_ramified_primes(nf);
363 7 : l = lg(P);
364 7 : Q = q; q = gen_1;
365 42 : for (i = 1; i < l; i++)
366 : {
367 35 : GEN p = gel(P,i);
368 35 : if (Z_pvalrem(Q, p, &Q) && !BPSW_psp(p)) q = mulii(q, p);
369 : }
370 7 : return q;
371 : }
372 :
373 : /* lt(A) is an integer; ensure it is not a constant t_POL. In place */
374 : static void
375 6056 : ensure_lt_INT(GEN A)
376 : {
377 6056 : long n = lg(A)-1;
378 6056 : GEN lt = gel(A,n);
379 6056 : while (typ(lt) != t_INT) gel(A,n) = lt = gel(lt,2);
380 6056 : }
381 :
382 : /* set B = A/gcd(A,A'), squarefree */
383 : static GEN
384 6042 : get_nfsqff_data(GEN *pnf, GEN *pT, GEN *pA, GEN *pB, GEN *ptbad)
385 : {
386 6042 : GEN den, bad, D, B, A = *pA, T = *pT;
387 6042 : long n = degpol(T);
388 :
389 6042 : A = Q_primpart( QXQX_normalize(A, T) );
390 6042 : if (nfsqff_use_Trager(n, degpol(A)))
391 : {
392 182 : *pnf = T;
393 182 : bad = den = ZX_disc(T);
394 182 : if (is_pm1(leading_coeff(T))) den = indexpartial(T, den);
395 : }
396 : else
397 : {
398 5860 : den = fix_nf(pnf, &T, &A);
399 5860 : bad = nf_get_index(*pnf);
400 5860 : if (den != gen_1) bad = mulii(bad, den);
401 : }
402 6042 : D = nfgcd_all(A, RgX_deriv(A), T, bad, &B);
403 6042 : if (degpol(D)) B = Q_primpart( QXQX_normalize(B, T) );
404 6042 : if (ptbad) *ptbad = bad;
405 6042 : *pA = A;
406 6042 : *pB = B; ensure_lt_INT(B);
407 6042 : *pT = T; return den;
408 : }
409 :
410 : /* return the roots of pol in nf */
411 : GEN
412 6504 : nfroots(GEN nf,GEN pol)
413 : {
414 6504 : pari_sp av = avma;
415 : GEN z, A, B, T, den;
416 : long d, dT;
417 :
418 6504 : if (!nf) return nfrootsQ(pol);
419 4894 : T = get_nfpol(nf, &nf);
420 4894 : RgX_check_ZX(T,"nfroots");
421 4894 : A = RgX_nffix("nfroots", T,pol,1);
422 4894 : d = degpol(A);
423 4894 : if (d < 0) pari_err_ROOTS0("nfroots");
424 4894 : if (d == 0) return cgetg(1,t_VEC);
425 4894 : if (d == 1)
426 : {
427 14 : A = QXQX_normalize(A,T);
428 14 : A = mkpolmod(gneg_i(gel(A,2)), T);
429 14 : return gerepilecopy(av, mkvec(A));
430 : }
431 4880 : dT = degpol(T);
432 4880 : if (dT == 1) return gerepileupto(av, nfrootsQ(simplify_shallow(A)));
433 :
434 4880 : den = get_nfsqff_data(&nf, &T, &A, &B, NULL);
435 4880 : if (RgX_is_ZX(B))
436 : {
437 1450 : GEN v = gel(ZX_factor(B), 1);
438 1450 : long i, l = lg(v), p = mael(factoru(dT),1,1); /* smallest prime divisor */
439 1450 : z = cgetg(1, t_VEC);
440 3964 : for (i = 1; i < l; i++)
441 : {
442 2514 : GEN b = gel(v,i); /* irreducible / Q */
443 2514 : long db = degpol(b);
444 2514 : if (db != 1 && degpol(b) < p) continue;
445 2514 : z = shallowconcat(z, nfsqff(nf, b, ROOTS, den));
446 : }
447 : }
448 : else
449 3430 : z = nfsqff(nf,B, ROOTS, den);
450 4880 : z = gerepileupto(av, QXQV_to_mod(z, T));
451 4880 : gen_sort_inplace(z, (void*)&cmp_RgX, &cmp_nodata, NULL);
452 4880 : return z;
453 : }
454 :
455 : static GEN
456 170296 : _norml2(GEN x) { return RgC_fpnorml2(x, DEFAULTPREC); }
457 :
458 : /* return a minimal lift of elt modulo id, as a ZC */
459 : static GEN
460 46409 : nf_bestlift(GEN elt, GEN bound, nflift_t *L)
461 : {
462 : GEN u;
463 46409 : long i,l = lg(L->prk), t = typ(elt);
464 46409 : if (t != t_INT)
465 : {
466 9636 : if (t == t_POL) elt = ZM_ZX_mul(L->tozk, elt);
467 9636 : u = ZM_ZC_mul(L->iprk,elt);
468 9636 : for (i=1; i<l; i++) gel(u,i) = diviiround(gel(u,i), L->pk);
469 : }
470 : else
471 : {
472 36773 : u = ZC_Z_mul(gel(L->iprk,1), elt);
473 36773 : for (i=1; i<l; i++) gel(u,i) = diviiround(gel(u,i), L->pk);
474 36773 : elt = scalarcol(elt, l-1);
475 : }
476 46409 : u = ZC_sub(elt, ZM_ZC_mul(L->prk, u));
477 46409 : if (bound && gcmp(_norml2(u), bound) > 0) u = NULL;
478 46409 : return u;
479 : }
480 :
481 : /* Warning: return L->topowden * (best lift). */
482 : static GEN
483 33249 : nf_bestlift_to_pol(GEN elt, GEN bound, nflift_t *L)
484 : {
485 33249 : pari_sp av = avma;
486 33249 : GEN u,v = nf_bestlift(elt,bound,L);
487 33249 : if (!v) return NULL;
488 27719 : if (ZV_isscalar(v))
489 : {
490 17843 : if (L->topowden)
491 17843 : u = mulii(L->topowden, gel(v,1));
492 : else
493 0 : u = icopy(gel(v,1));
494 17843 : u = gerepileuptoint(av, u);
495 : }
496 : else
497 : {
498 9876 : v = gclone(v); avma = av;
499 9876 : u = RgV_dotproduct(L->topow, v);
500 9876 : gunclone(v);
501 : }
502 27719 : return u;
503 : }
504 :
505 : /* return the T->powden * (lift of pol with coefficients of T2-norm <= C)
506 : * if it exists. */
507 : static GEN
508 7343 : nf_pol_lift(GEN pol, GEN bound, nflift_t *L)
509 : {
510 7343 : long i, l = lg(pol);
511 7343 : GEN x = cgetg(l,t_POL);
512 :
513 7343 : x[1] = pol[1];
514 7343 : gel(x,l-1) = mul_content(gel(pol,l-1), L->topowden);
515 29883 : for (i=l-2; i>1; i--)
516 : {
517 28070 : GEN t = nf_bestlift_to_pol(gel(pol,i), bound, L);
518 28070 : if (!t) return NULL;
519 22540 : gel(x,i) = t;
520 : }
521 1813 : return x;
522 : }
523 :
524 : static GEN
525 0 : zerofact(long v)
526 : {
527 0 : GEN z = cgetg(3, t_MAT);
528 0 : gel(z,1) = mkcol(pol_0(v));
529 0 : gel(z,2) = mkcol(gen_1); return z;
530 : }
531 :
532 : /* Return the factorization of A in Q[X]/(T) in rep [pre-allocated with
533 : * cgetg(3,t_MAT)], reclaiming all memory between avma and rep.
534 : * y is the vector of irreducible factors of B = Q_primpart( A/gcd(A,A') ).
535 : * Bad primes divide 'bad' */
536 : static void
537 1176 : fact_from_sqff(GEN rep, GEN A, GEN B, GEN y, GEN T, GEN bad)
538 : {
539 1176 : pari_sp av = (pari_sp)rep;
540 1176 : long n = lg(y)-1;
541 : GEN ex;
542 :
543 1176 : if (A != B)
544 : { /* not squarefree */
545 70 : if (n == 1)
546 : { /* perfect power, simple ! */
547 7 : long e = degpol(A) / degpol(gel(y,1));
548 7 : y = gerepileupto(av, QXQXV_to_mod(y, T));
549 7 : ex = mkcol(utoipos(e));
550 : }
551 : else
552 : { /* compute valuations mod a prime of degree 1 (avoid coeff explosion) */
553 63 : GEN quo, p, r, Bp, lb = leading_coeff(B), E = cgetalloc(t_VECSMALL,n+1);
554 63 : pari_sp av1 = avma;
555 : ulong pp;
556 : long j;
557 : forprime_t S;
558 63 : u_forprime_init(&S, degpol(T), ULONG_MAX);
559 168 : for (; ; avma = av1)
560 : {
561 231 : pp = u_forprime_next(&S);
562 231 : if (! umodiu(bad,pp) || !umodiu(lb, pp)) continue;
563 217 : p = utoipos(pp);
564 217 : r = FpX_oneroot(T, p);
565 217 : if (!r) continue;
566 112 : Bp = FpXY_evalx(B, r, p);
567 112 : if (FpX_is_squarefree(Bp, p)) break;
568 168 : }
569 :
570 63 : quo = FpXY_evalx(Q_primpart(A), r, p);
571 140 : for (j=n; j>=2; j--)
572 : {
573 77 : GEN junk, fact = Q_remove_denom(gel(y,j), &junk);
574 77 : long e = 0;
575 77 : fact = FpXY_evalx(fact, r, p);
576 182 : for(;; e++)
577 : {
578 259 : GEN q = FpX_divrem(quo,fact,p,ONLY_DIVIDES);
579 259 : if (!q) break;
580 182 : quo = q;
581 182 : }
582 77 : E[j] = e;
583 : }
584 63 : E[1] = degpol(quo) / degpol(gel(y,1));
585 63 : y = gerepileupto(av, QXQXV_to_mod(y, T));
586 63 : ex = zc_to_ZC(E); pari_free((void*)E);
587 : }
588 : }
589 : else
590 : {
591 1106 : y = gerepileupto(av, QXQXV_to_mod(y, T));
592 1106 : ex = const_col(n, gen_1);
593 : }
594 1176 : gel(rep,1) = y; settyp(y, t_COL);
595 1176 : gel(rep,2) = ex;
596 1176 : }
597 :
598 : /* return the factorization of x in nf */
599 : GEN
600 1330 : nffactor(GEN nf,GEN pol)
601 : {
602 1330 : GEN bad, A, B, y, T, den, rep = cgetg(3, t_MAT);
603 1330 : pari_sp av = avma;
604 : long dA;
605 : pari_timer ti;
606 :
607 1330 : if (DEBUGLEVEL>2) { timer_start(&ti); err_printf("\nEntering nffactor:\n"); }
608 1330 : T = get_nfpol(nf, &nf);
609 1330 : RgX_check_ZX(T,"nffactor");
610 1330 : A = RgX_nffix("nffactor",T,pol,1);
611 1330 : dA = degpol(A);
612 1330 : if (dA <= 0) {
613 0 : avma = (pari_sp)(rep + 3);
614 0 : return (dA == 0)? trivial_fact(): zerofact(varn(pol));
615 : }
616 1330 : if (dA == 1) {
617 : GEN c;
618 98 : A = Q_primpart( QXQX_normalize(A, T) );
619 98 : A = gerepilecopy(av, A); c = gel(A,2);
620 98 : if (typ(c) == t_POL && degpol(c) > 0) gel(A,2) = mkpolmod(c, ZX_copy(T));
621 98 : gel(rep,1) = mkcol(A);
622 98 : gel(rep,2) = mkcol(gen_1); return rep;
623 : }
624 1232 : if (degpol(T) == 1) return gerepileupto(av, QX_factor(simplify_shallow(A)));
625 :
626 1162 : den = get_nfsqff_data(&nf, &T, &A, &B, &bad);
627 1162 : if (DEBUGLEVEL>2) timer_printf(&ti, "squarefree test");
628 1162 : if (RgX_is_ZX(B))
629 : {
630 882 : GEN v = gel(ZX_factor(B), 1);
631 882 : long i, l = lg(v);
632 882 : y = cgetg(1, t_VEC);
633 1806 : for (i = 1; i < l; i++)
634 : {
635 924 : GEN b = gel(v,i); /* irreducible / Q */
636 924 : y = shallowconcat(y, nfsqff(nf, b, 0, den));
637 : }
638 : }
639 : else
640 280 : y = nfsqff(nf,B, 0, den);
641 1162 : if (DEBUGLEVEL>3) err_printf("number of factor(s) found: %ld\n", lg(y)-1);
642 :
643 1162 : fact_from_sqff(rep, A, B, y, T, bad);
644 1162 : return sort_factor_pol(rep, cmp_RgX);
645 : }
646 :
647 : /* assume x scalar or t_COL, G t_MAT */
648 : static GEN
649 23996 : arch_for_T2(GEN G, GEN x)
650 : {
651 47992 : return (typ(x) == t_COL)? RgM_RgC_mul(G,x)
652 23996 : : RgC_Rg_mul(gel(G,1),x);
653 : }
654 :
655 : /* polbase a zkX with t_INT leading coeff; return a bound for T_2(P),
656 : * P | polbase in C[X]. NB: Mignotte bound: A | S ==>
657 : * |a_i| <= binom(d-1, i-1) || S ||_2 + binom(d-1, i) lc(S)
658 : *
659 : * Apply to sigma(S) for all embeddings sigma, then take the L_2 norm over
660 : * sigma, then take the sup over i */
661 : static GEN
662 1015 : nf_Mignotte_bound(GEN nf, GEN polbase)
663 1015 : { GEN lS = leading_coeff(polbase); /* t_INT */
664 : GEN p1, C, N2, binlS, bin;
665 1015 : long prec = nf_get_prec(nf), n = nf_get_degree(nf), r1 = nf_get_r1(nf);
666 1015 : long i, j, d = degpol(polbase);
667 :
668 1015 : binlS = bin = vecbinomial(d-1);
669 1015 : if (!isint1(lS)) binlS = ZC_Z_mul(bin,lS);
670 :
671 1015 : N2 = cgetg(n+1, t_VEC);
672 : for (;;)
673 : {
674 1015 : GEN G = nf_get_G(nf), matGS = cgetg(d+2, t_MAT);
675 :
676 1015 : for (j=0; j<=d; j++) gel(matGS,j+1) = arch_for_T2(G, gel(polbase,j+2));
677 1015 : matGS = shallowtrans(matGS);
678 2583 : for (j=1; j <= r1; j++) /* N2[j] = || sigma_j(S) ||_2 */
679 : {
680 1568 : GEN c = sqrtr( _norml2(gel(matGS,j)) );
681 1568 : gel(N2,j) = c; if (!signe(c)) goto PRECPB;
682 : }
683 2366 : for ( ; j <= n; j+=2)
684 : {
685 1351 : GEN q1 = _norml2(gel(matGS, j));
686 1351 : GEN q2 = _norml2(gel(matGS, j+1));
687 1351 : GEN c = sqrtr( gmul2n(addrr(q1, q2), -1) );
688 1351 : gel(N2,j) = gel(N2,j+1) = c; if (!signe(c)) goto PRECPB;
689 : }
690 1015 : break; /* done */
691 : PRECPB:
692 0 : prec = precdbl(prec);
693 0 : nf = nfnewprec_shallow(nf, prec);
694 0 : if (DEBUGLEVEL>1) pari_warn(warnprec, "nf_factor_bound", prec);
695 0 : }
696 :
697 : /* Take sup over 0 <= i <= d of
698 : * sum_j | binom(d-1, i-1) ||sigma_j(S)||_2 + binom(d-1,i) lc(S) |^2 */
699 :
700 : /* i = 0: n lc(S)^2 */
701 1015 : C = mului(n, sqri(lS));
702 : /* i = d: sum_sigma ||sigma(S)||_2^2 */
703 1015 : p1 = gnorml2(N2); if (gcmp(C, p1) < 0) C = p1;
704 13489 : for (i = 1; i < d; i++)
705 : {
706 12474 : GEN B = gel(bin,i), L = gel(binlS,i+1);
707 12474 : GEN s = sqrr(addri(mulir(B, gel(N2,1)), L)); /* j=1 */
708 12474 : for (j = 2; j <= n; j++) s = addrr(s, sqrr(addri(mulir(B, gel(N2,j)), L)));
709 12474 : if (mpcmp(C, s) < 0) C = s;
710 : }
711 1015 : return C;
712 : }
713 :
714 : /* return a bound for T_2(P), P | polbase
715 : * max |b_i|^2 <= 3^{3/2 + d} / (4 \pi d) [P]_2,
716 : * where [P]_2 is Bombieri's 2-norm
717 : * Sum over conjugates */
718 : static GEN
719 1015 : nf_Beauzamy_bound(GEN nf, GEN polbase)
720 : {
721 : GEN lt, C, s, POL, bin;
722 1015 : long d = degpol(polbase), n = nf_get_degree(nf), prec = nf_get_prec(nf);
723 1015 : bin = vecbinomial(d);
724 1015 : POL = polbase + 2;
725 : /* compute [POL]_2 */
726 : for (;;)
727 : {
728 1015 : GEN G = nf_get_G(nf);
729 : long i;
730 :
731 1015 : s = real_0(prec);
732 15519 : for (i=0; i<=d; i++)
733 : {
734 14504 : GEN c = gel(POL,i);
735 14504 : if (gequal0(c)) continue;
736 9492 : c = _norml2(arch_for_T2(G,c));
737 9492 : if (!signe(c)) goto PRECPB;
738 : /* s += T2(POL[i]) / binomial(d,i) */
739 9492 : s = addrr(s, divri(c, gel(bin,i+1)));
740 : }
741 1015 : break;
742 : PRECPB:
743 0 : prec = precdbl(prec);
744 0 : nf = nfnewprec_shallow(nf, prec);
745 0 : if (DEBUGLEVEL>1) pari_warn(warnprec, "nf_factor_bound", prec);
746 0 : }
747 1015 : lt = leading_coeff(polbase);
748 1015 : s = mulri(s, muliu(sqri(lt), n));
749 1015 : C = powruhalf(stor(3,DEFAULTPREC), 3 + 2*d); /* 3^{3/2 + d} */
750 1015 : return divrr(mulrr(C, s), mulur(d, mppi(DEFAULTPREC)));
751 : }
752 :
753 : static GEN
754 1015 : nf_factor_bound(GEN nf, GEN polbase)
755 : {
756 1015 : pari_sp av = avma;
757 1015 : GEN a = nf_Mignotte_bound(nf, polbase);
758 1015 : GEN b = nf_Beauzamy_bound(nf, polbase);
759 1015 : if (DEBUGLEVEL>2)
760 : {
761 0 : err_printf("Mignotte bound: %Ps\n",a);
762 0 : err_printf("Beauzamy bound: %Ps\n",b);
763 : }
764 1015 : return gerepileupto(av, gmin(a, b));
765 : }
766 :
767 : /* True nf; return Bs: if r a root of sigma_i(P), |r| < Bs[i] */
768 : static GEN
769 3340 : nf_root_bounds(GEN nf, GEN P)
770 : {
771 : long lR, i, j, l, prec, r1;
772 : GEN Ps, R, V;
773 :
774 3340 : if (RgX_is_rational(P)) return polrootsbound(P, NULL);
775 2233 : r1 = nf_get_r1(nf);
776 2233 : P = Q_primpart(P);
777 2233 : prec = ZXX_max_lg(P) + 1;
778 2233 : l = lg(P);
779 2233 : if (nf_get_prec(nf) >= prec)
780 1910 : R = nf_get_roots(nf);
781 : else
782 323 : R = QX_complex_roots(nf_get_pol(nf), prec);
783 2233 : lR = lg(R);
784 2233 : V = cgetg(lR, t_VEC);
785 2233 : Ps = cgetg(l, t_POL); /* sigma (P) */
786 2233 : Ps[1] = P[1];
787 6573 : for (j=1; j<lg(R); j++)
788 : {
789 4340 : GEN r = gel(R,j);
790 4340 : for (i=2; i<l; i++) gel(Ps,i) = poleval(gel(P,i), r);
791 4340 : gel(V,j) = polrootsbound(Ps, NULL);
792 : }
793 2233 : return mkvec2(vecslice(V,1,r1), vecslice(V,r1+1,lg(V)-1));
794 : }
795 :
796 : /* return B such that, if x = sum x_i K.zk[i] in O_K, then ||x||_2^2 <= B T_2(x)
797 : * den = multiplicative bound for denom(x) [usually NULL, for 1, but when we
798 : * use nf_PARTIALFACT K.zk may not generate O_K] */
799 : static GEN
800 3755 : L2_bound(GEN nf, GEN den)
801 : {
802 3755 : GEN M, L, prep, T = nf_get_pol(nf), tozk = nf_get_invzk(nf);
803 3755 : long prec = ZM_max_lg(tozk) + ZX_max_lg(T) + nbits2prec(degpol(T));
804 3755 : (void)initgaloisborne(nf, den? den: gen_1, prec, &L, &prep, NULL);
805 3755 : M = vandermondeinverse(L, RgX_gtofp(T,prec), den, prep);
806 3755 : return RgM_fpnorml2(RgM_mul(tozk,M), DEFAULTPREC);
807 : }
808 :
809 : /* sum_i L[i]^p */
810 : static GEN
811 8512 : normlp(GEN L, long p)
812 : {
813 8512 : long i, l = lg(L);
814 : GEN z;
815 8512 : if (l == 1) return gen_0;
816 4501 : z = gpowgs(gel(L,1), p);
817 4501 : for (i=2; i<l; i++) z = gadd(z, gpowgs(gel(L,i), p));
818 4501 : return z;
819 : }
820 : /* \sum_i deg(sigma_i) L[i]^p in dimension n (L may be a scalar
821 : * or [L1,L2], where Ld corresponds to the archimedean places of degree d) */
822 : static GEN
823 5896 : normTp(GEN L, long p, long n)
824 : {
825 5896 : if (typ(L) != t_VEC) return gmulsg(n, gpowgs(L, p));
826 4256 : return gadd(normlp(gel(L,1),p), gmul2n(normlp(gel(L,2),p), 1));
827 : }
828 :
829 : /* S = S0 + tS1, P = P0 + tP1 (Euclidean div. by t integer). For a true
830 : * factor (vS, vP), we have:
831 : * | S vS + P vP |^2 < Btra
832 : * This implies | S1 vS + P1 vP |^2 < Bhigh, assuming t > sqrt(Btra).
833 : * d = dimension of low part (= [nf:Q])
834 : * n0 = bound for |vS|^2
835 : * */
836 : static double
837 1057 : get_Bhigh(long n0, long d)
838 : {
839 1057 : double sqrtd = sqrt((double)d);
840 1057 : double z = n0*sqrtd + sqrtd/2 * (d * (n0+1));
841 1057 : z = 1. + 0.5 * z; return z * z;
842 : }
843 :
844 : typedef struct {
845 : GEN d;
846 : GEN dPinvS; /* d P^(-1) S [ integral ] */
847 : double **PinvSdbl; /* P^(-1) S as double */
848 : GEN S1, P1; /* S = S0 + S1 q, idem P */
849 : } trace_data;
850 :
851 : /* S1 * u - P1 * round(P^-1 S u). K non-zero coords in u given by ind */
852 : static GEN
853 128464 : get_trace(GEN ind, trace_data *T)
854 : {
855 128464 : long i, j, l, K = lg(ind)-1;
856 : GEN z, s, v;
857 :
858 128464 : s = gel(T->S1, ind[1]);
859 128464 : if (K == 1) return s;
860 :
861 : /* compute s = S1 u */
862 126014 : for (j=2; j<=K; j++) s = ZC_add(s, gel(T->S1, ind[j]));
863 :
864 : /* compute v := - round(P^1 S u) */
865 126014 : l = lg(s);
866 126014 : v = cgetg(l, t_VECSMALL);
867 1720306 : for (i=1; i<l; i++)
868 : {
869 1594292 : double r, t = 0.;
870 : /* quick approximate computation */
871 1594292 : for (j=1; j<=K; j++) t += T->PinvSdbl[ ind[j] ][i];
872 1594292 : r = floor(t + 0.5);
873 1594292 : if (fabs(t + 0.5 - r) < 0.0001)
874 : { /* dubious, compute exactly */
875 196 : z = gen_0;
876 196 : for (j=1; j<=K; j++) z = addii(z, ((GEN**)T->dPinvS)[ ind[j] ][i]);
877 196 : v[i] = - itos( diviiround(z, T->d) );
878 : }
879 : else
880 1594096 : v[i] = - (long)r;
881 : }
882 126014 : return ZC_add(s, ZM_zc_mul(T->P1, v));
883 : }
884 :
885 : static trace_data *
886 2030 : init_trace(trace_data *T, GEN S, nflift_t *L, GEN q)
887 : {
888 2030 : long e = gexpo(S), i,j, l,h;
889 : GEN qgood, S1, invd;
890 :
891 2030 : if (e < 0) return NULL; /* S = 0 */
892 :
893 1876 : qgood = int2n(e - 32); /* single precision check */
894 1876 : if (cmpii(qgood, q) > 0) q = qgood;
895 :
896 1876 : S1 = gdivround(S, q);
897 1876 : if (gequal0(S1)) return NULL;
898 :
899 336 : invd = invr(itor(L->pk, DEFAULTPREC));
900 :
901 336 : T->dPinvS = ZM_mul(L->iprk, S);
902 336 : l = lg(S);
903 336 : h = lgcols(T->dPinvS);
904 336 : T->PinvSdbl = (double**)cgetg(l, t_MAT);
905 3731 : for (j = 1; j < l; j++)
906 : {
907 3395 : double *t = (double *) stack_malloc_align(h * sizeof(double), sizeof(double));
908 3395 : GEN c = gel(T->dPinvS,j);
909 3395 : pari_sp av = avma;
910 3395 : T->PinvSdbl[j] = t;
911 3395 : for (i=1; i < h; i++) t[i] = rtodbl(mulri(invd, gel(c,i)));
912 3395 : avma = av;
913 : }
914 :
915 336 : T->d = L->pk;
916 336 : T->P1 = gdivround(L->prk, q);
917 336 : T->S1 = S1; return T;
918 : }
919 :
920 : static void
921 16842 : update_trace(trace_data *T, long k, long i)
922 : {
923 33684 : if (!T) return;
924 8953 : gel(T->S1,k) = gel(T->S1,i);
925 8953 : gel(T->dPinvS,k) = gel(T->dPinvS,i);
926 8953 : T->PinvSdbl[k] = T->PinvSdbl[i];
927 : }
928 :
929 : /* reduce coeffs mod (T,pk), then center mod pk */
930 : static GEN
931 16863 : FqX_centermod(GEN z, GEN T, GEN pk, GEN pks2)
932 : {
933 : long i, l;
934 : GEN y;
935 16863 : if (!T) return centermod_i(z, pk, pks2);
936 14252 : y = FpXQX_red(z, T, pk); l = lg(y);
937 134505 : for (i = 2; i < l; i++)
938 : {
939 120253 : GEN c = gel(y,i);
940 120253 : if (typ(c) == t_INT)
941 80234 : c = Fp_center_i(c, pk, pks2);
942 : else
943 40019 : c = FpX_center_i(c, pk, pks2);
944 120253 : gel(y,i) = c;
945 : }
946 14252 : return y;
947 : }
948 :
949 : typedef struct {
950 : GEN lt, C, Clt, C2lt, C2ltpol;
951 : } div_data;
952 :
953 : static void
954 3790 : init_div_data(div_data *D, GEN pol, nflift_t *L)
955 : {
956 3790 : GEN C = mul_content(L->topowden, L->dn);
957 3790 : GEN C2lt, Clt, lc = leading_coeff(pol), lt = is_pm1(lc)? NULL: absi(lc);
958 3790 : if (C)
959 : {
960 3790 : GEN C2 = sqri(C);
961 3790 : if (lt) {
962 1029 : C2lt = mulii(C2, lt);
963 1029 : Clt = mulii(C,lt);
964 : } else {
965 2761 : C2lt = C2;
966 2761 : Clt = C;
967 : }
968 : }
969 : else
970 0 : C2lt = Clt = lt;
971 3790 : D->lt = lt;
972 3790 : D->C = C;
973 3790 : D->Clt = Clt;
974 3790 : D->C2lt = C2lt;
975 3790 : D->C2ltpol = C2lt? RgX_Rg_mul(pol, C2lt): pol;
976 3790 : }
977 : static void
978 1750 : update_target(div_data *D, GEN pol)
979 1750 : { D->C2ltpol = D->Clt? RgX_Rg_mul(pol, D->Clt): pol; }
980 :
981 : /* nb = number of modular factors; return a "good" K such that naive
982 : * recombination of up to maxK modular factors is not too costly */
983 : long
984 13532 : cmbf_maxK(long nb)
985 : {
986 13532 : if (nb > 10) return 3;
987 12986 : return nb-1;
988 : }
989 : /* Naive recombination of modular factors: combine up to maxK modular
990 : * factors, degree <= klim
991 : *
992 : * target = polynomial we want to factor
993 : * famod = array of modular factors. Product should be congruent to
994 : * target/lc(target) modulo p^a
995 : * For true factors: S1,S2 <= p^b, with b <= a and p^(b-a) < 2^31 */
996 : /* set *done = 1 if factorisation is known to be complete */
997 : static GEN
998 1015 : nfcmbf(nfcmbf_t *T, long klim, long *pmaxK, int *done)
999 : {
1000 1015 : GEN nf = T->nf, famod = T->fact, bound = T->bound;
1001 1015 : GEN ltdn, nfpol = nf_get_pol(nf);
1002 1015 : long K = 1, cnt = 1, i,j,k, curdeg, lfamod = lg(famod)-1, dnf = degpol(nfpol);
1003 1015 : pari_sp av0 = avma;
1004 1015 : GEN Tpk = T->L->Tpk, pk = T->L->pk, pks2 = shifti(pk,-1);
1005 1015 : GEN ind = cgetg(lfamod+1, t_VECSMALL);
1006 1015 : GEN deg = cgetg(lfamod+1, t_VECSMALL);
1007 1015 : GEN degsofar = cgetg(lfamod+1, t_VECSMALL);
1008 1015 : GEN fa = cgetg(lfamod+1, t_VEC);
1009 1015 : const double Bhigh = get_Bhigh(lfamod, dnf);
1010 : trace_data _T1, _T2, *T1, *T2;
1011 : div_data D;
1012 : pari_timer ti;
1013 :
1014 1015 : timer_start(&ti);
1015 :
1016 1015 : *pmaxK = cmbf_maxK(lfamod);
1017 1015 : init_div_data(&D, T->pol, T->L);
1018 1015 : ltdn = mul_content(D.lt, T->L->dn);
1019 : {
1020 1015 : GEN q = ceil_safe(sqrtr(T->BS_2));
1021 1015 : GEN t1,t2, lt2dn = mul_content(ltdn, D.lt);
1022 1015 : GEN trace1 = cgetg(lfamod+1, t_MAT);
1023 1015 : GEN trace2 = cgetg(lfamod+1, t_MAT);
1024 5369 : for (i=1; i <= lfamod; i++)
1025 : {
1026 4354 : pari_sp av = avma;
1027 4354 : GEN P = gel(famod,i);
1028 4354 : long d = degpol(P);
1029 :
1030 4354 : deg[i] = d; P += 2;
1031 4354 : t1 = gel(P,d-1);/* = - S_1 */
1032 4354 : t2 = Fq_sqr(t1, Tpk, pk);
1033 4354 : if (d > 1) t2 = Fq_sub(t2, gmul2n(gel(P,d-2), 1), Tpk, pk);
1034 : /* t2 = S_2 Newton sum */
1035 4354 : if (ltdn)
1036 : {
1037 154 : t1 = Fq_Fp_mul(t1, ltdn, Tpk, pk);
1038 154 : t2 = Fq_Fp_mul(t2, lt2dn, Tpk, pk);
1039 : }
1040 4354 : gel(trace1,i) = gclone( nf_bestlift(t1, NULL, T->L) );
1041 4354 : gel(trace2,i) = gclone( nf_bestlift(t2, NULL, T->L) ); avma = av;
1042 : }
1043 1015 : T1 = init_trace(&_T1, trace1, T->L, q);
1044 1015 : T2 = init_trace(&_T2, trace2, T->L, q);
1045 5369 : for (i=1; i <= lfamod; i++) {
1046 4354 : gunclone(gel(trace1,i));
1047 4354 : gunclone(gel(trace2,i));
1048 : }
1049 : }
1050 1015 : degsofar[0] = 0; /* sentinel */
1051 :
1052 : /* ind runs through strictly increasing sequences of length K,
1053 : * 1 <= ind[i] <= lfamod */
1054 : nextK:
1055 1463 : if (K > *pmaxK || 2*K > lfamod) goto END;
1056 1253 : if (DEBUGLEVEL > 3)
1057 0 : err_printf("\n### K = %d, %Ps combinations\n", K,binomial(utoipos(lfamod), K));
1058 1253 : setlg(ind, K+1); ind[1] = 1;
1059 1253 : i = 1; curdeg = deg[ind[1]];
1060 : for(;;)
1061 : { /* try all combinations of K factors */
1062 149590 : for (j = i; j < K; j++)
1063 : {
1064 15687 : degsofar[j] = curdeg;
1065 15687 : ind[j+1] = ind[j]+1; curdeg += deg[ind[j+1]];
1066 : }
1067 133903 : if (curdeg <= klim) /* trial divide */
1068 : {
1069 : GEN t, y, q;
1070 : pari_sp av;
1071 :
1072 133903 : av = avma;
1073 133903 : if (T1)
1074 : { /* d-1 test */
1075 45374 : t = get_trace(ind, T1);
1076 45374 : if (rtodbl(_norml2(t)) > Bhigh)
1077 : {
1078 44345 : if (DEBUGLEVEL>6) err_printf(".");
1079 44345 : avma = av; goto NEXT;
1080 : }
1081 : }
1082 89558 : if (T2)
1083 : { /* d-2 test */
1084 83090 : t = get_trace(ind, T2);
1085 83090 : if (rtodbl(_norml2(t)) > Bhigh)
1086 : {
1087 82285 : if (DEBUGLEVEL>3) err_printf("|");
1088 82285 : avma = av; goto NEXT;
1089 : }
1090 : }
1091 7273 : avma = av;
1092 7273 : y = ltdn; /* full computation */
1093 24136 : for (i=1; i<=K; i++)
1094 : {
1095 16863 : GEN q = gel(famod, ind[i]);
1096 16863 : if (y) q = gmul(y, q);
1097 16863 : y = FqX_centermod(q, Tpk, pk, pks2);
1098 : }
1099 7273 : y = nf_pol_lift(y, bound, T->L);
1100 7273 : if (!y)
1101 : {
1102 5530 : if (DEBUGLEVEL>3) err_printf("@");
1103 5530 : avma = av; goto NEXT;
1104 : }
1105 : /* y = topowden*dn*lt*\prod_{i in ind} famod[i] is apparently in O_K[X],
1106 : * in fact in (Z[Y]/nf.pol)[X] due to multiplication by C = topowden*dn.
1107 : * Try out this candidate factor */
1108 1743 : q = RgXQX_divrem(D.C2ltpol, y, nfpol, ONLY_DIVIDES);
1109 1743 : if (!q)
1110 : {
1111 42 : if (DEBUGLEVEL>3) err_printf("*");
1112 42 : avma = av; goto NEXT;
1113 : }
1114 : /* Original T->pol in O_K[X] with leading coeff lt in Z,
1115 : * y = C*lt \prod famod[i] is in O_K[X] with leading coeff in Z
1116 : * q = C^2*lt*pol / y = C * (lt*pol) / (lt*\prod famod[i]) is a
1117 : * K-rational factor, in fact in Z[Y]/nf.pol)[X] as above, with
1118 : * leading term C*lt. */
1119 1701 : update_target(&D, q);
1120 1701 : gel(fa,cnt++) = D.C2lt? RgX_int_normalize(y): y; /* make monic */
1121 12138 : for (i=j=k=1; i <= lfamod; i++)
1122 : { /* remove used factors */
1123 10437 : if (j <= K && i == ind[j]) j++;
1124 : else
1125 : {
1126 8421 : gel(famod,k) = gel(famod,i);
1127 8421 : update_trace(T1, k, i);
1128 8421 : update_trace(T2, k, i);
1129 8421 : deg[k] = deg[i]; k++;
1130 : }
1131 : }
1132 1701 : lfamod -= K;
1133 1701 : *pmaxK = cmbf_maxK(lfamod);
1134 1701 : if (lfamod < 2*K) goto END;
1135 896 : i = 1; curdeg = deg[ind[1]];
1136 896 : if (DEBUGLEVEL > 2)
1137 : {
1138 0 : err_printf("\n"); timer_printf(&ti, "to find factor %Ps",y);
1139 0 : err_printf("remaining modular factor(s): %ld\n", lfamod);
1140 : }
1141 896 : continue;
1142 : }
1143 :
1144 : NEXT:
1145 132202 : for (i = K+1;;)
1146 : {
1147 148022 : if (--i == 0) { K++; goto nextK; }
1148 147574 : if (++ind[i] <= lfamod - K + i)
1149 : {
1150 131754 : curdeg = degsofar[i-1] + deg[ind[i]];
1151 131754 : if (curdeg <= klim) break;
1152 : }
1153 15820 : }
1154 132650 : }
1155 : END:
1156 1015 : *done = 1;
1157 1015 : if (degpol(D.C2ltpol) > 0)
1158 : { /* leftover factor */
1159 1015 : GEN q = D.C2ltpol;
1160 1015 : if (D.C2lt) q = RgX_int_normalize(q);
1161 1015 : if (lfamod >= 2*K)
1162 : { /* restore leading coefficient [#930] */
1163 42 : if (D.lt) q = RgX_Rg_mul(q, D.lt);
1164 42 : *done = 0; /* ... may still be reducible */
1165 : }
1166 1015 : setlg(famod, lfamod+1);
1167 1015 : gel(fa,cnt++) = q;
1168 : }
1169 1015 : if (DEBUGLEVEL>6) err_printf("\n");
1170 1015 : setlg(fa, cnt);
1171 1015 : return gerepilecopy(av0, fa);
1172 : }
1173 :
1174 : static GEN
1175 35 : nf_chk_factors(nfcmbf_t *T, GEN P, GEN M_L, GEN famod, GEN pk)
1176 : {
1177 35 : GEN nf = T->nf, bound = T->bound;
1178 35 : GEN nfT = nf_get_pol(nf);
1179 : long i, r;
1180 35 : GEN pol = P, list, piv, y;
1181 35 : GEN Tpk = T->L->Tpk;
1182 : div_data D;
1183 :
1184 35 : piv = ZM_hnf_knapsack(M_L);
1185 35 : if (!piv) return NULL;
1186 21 : if (DEBUGLEVEL>3) err_printf("ZM_hnf_knapsack output:\n%Ps\n",piv);
1187 :
1188 21 : r = lg(piv)-1;
1189 21 : list = cgetg(r+1, t_VEC);
1190 21 : init_div_data(&D, pol, T->L);
1191 21 : for (i = 1;;)
1192 : {
1193 70 : pari_sp av = avma;
1194 70 : if (DEBUGLEVEL) err_printf("nf_LLL_cmbf: checking factor %ld\n", i);
1195 70 : y = chk_factors_get(D.lt, famod, gel(piv,i), Tpk, pk);
1196 :
1197 70 : if (! (y = nf_pol_lift(y, bound, T->L)) ) return NULL;
1198 70 : y = gerepilecopy(av, y);
1199 : /* y is the candidate factor */
1200 70 : pol = RgXQX_divrem(D.C2ltpol, y, nfT, ONLY_DIVIDES);
1201 70 : if (!pol) return NULL;
1202 :
1203 70 : if (D.C2lt) y = RgX_int_normalize(y);
1204 70 : gel(list,i) = y;
1205 70 : if (++i >= r) break;
1206 :
1207 49 : update_target(&D, pol);
1208 49 : }
1209 21 : gel(list,i) = RgX_int_normalize(pol); return list;
1210 : }
1211 :
1212 : static GEN
1213 25864 : nf_to_Zq(GEN x, GEN T, GEN pk, GEN pks2, GEN proj)
1214 : {
1215 : GEN y;
1216 25864 : if (typ(x) != t_COL) return centermodii(x, pk, pks2);
1217 6090 : if (!T)
1218 : {
1219 6020 : y = ZV_dotproduct(proj, x);
1220 6020 : return centermodii(y, pk, pks2);
1221 : }
1222 70 : y = ZM_ZC_mul(proj, x);
1223 70 : y = RgV_to_RgX(y, varn(T));
1224 70 : return FpX_center_i(FpX_rem(y, T, pk), pk, pks2);
1225 : }
1226 :
1227 : /* Assume P in nfX form, lc(P) != 0 mod p. Reduce P to Zp[X]/(T) mod p^a */
1228 : static GEN
1229 3340 : ZqX(GEN P, GEN pk, GEN T, GEN proj)
1230 : {
1231 3340 : long i, l = lg(P);
1232 3340 : GEN z, pks2 = shifti(pk,-1);
1233 :
1234 3340 : z = cgetg(l,t_POL); z[1] = P[1];
1235 3340 : for (i=2; i<l; i++) gel(z,i) = nf_to_Zq(gel(P,i),T,pk,pks2,proj);
1236 3340 : return normalizepol_lg(z, l);
1237 : }
1238 :
1239 : static GEN
1240 3340 : ZqX_normalize(GEN P, GEN lt, nflift_t *L)
1241 : {
1242 3340 : GEN R = lt? RgX_Rg_mul(P, Fp_inv(lt, L->pk)): P;
1243 3340 : return ZqX(R, L->pk, L->Tpk, L->ZqProj);
1244 : }
1245 :
1246 : /* k allowing to reconstruct x, |x|^2 < C, from x mod pr^k */
1247 : /* return log [ 2sqrt(C/d) * ( (3/2)sqrt(gamma) )^(d-1) ] ^d / log N(pr)
1248 : * cf. Belabas relative van Hoeij algorithm, lemma 3.12 */
1249 : static double
1250 3347 : bestlift_bound(GEN C, long d, double alpha, GEN p, long f)
1251 : {
1252 3347 : const double g = 1 / (alpha - 0.25); /* = 2 if alpha = 3/4 */
1253 3347 : GEN C4 = shiftr(gtofp(C,DEFAULTPREC), 2);
1254 3347 : double t, logp = log(gtodouble(p));
1255 3347 : if (f == d)
1256 : { /* p inert, no LLL fudge factor: p^(2k) / 4 > C */
1257 21 : t = 0.5 * rtodbl(mplog(C4));
1258 21 : return ceil(t / logp);
1259 : }
1260 : /* (1/2)log (4C/d) + (d-1)(log 3/2 sqrt(gamma)) */
1261 3326 : t = 0.5 * rtodbl(mplog(divru(C4,d))) + (d-1) * log(1.5 * sqrt(g));
1262 3326 : return ceil((t * d) / (logp * f));
1263 : }
1264 :
1265 : static GEN
1266 3811 : get_R(GEN M)
1267 : {
1268 : GEN R;
1269 3811 : long i, l, prec = nbits2prec( gexpo(M) + 64 );
1270 :
1271 : for(;;)
1272 : {
1273 3811 : R = gaussred_from_QR(M, prec);
1274 3811 : if (R) break;
1275 0 : prec = precdbl(prec);
1276 0 : }
1277 3811 : l = lg(R);
1278 3811 : for (i=1; i<l; i++) gcoeff(R,i,i) = gen_1;
1279 3811 : return R;
1280 : }
1281 :
1282 : static void
1283 3755 : init_proj(nflift_t *L, GEN prkHNF, GEN nfT)
1284 : {
1285 3755 : if (degpol(L->Tp)>1)
1286 : {
1287 119 : GEN coTp = FpX_div(FpX_red(nfT, L->p), L->Tp, L->p); /* Tp's cofactor */
1288 : GEN z, proj;
1289 119 : z = ZpX_liftfact(nfT, mkvec2(L->Tp, coTp), L->pk, L->p, L->k);
1290 119 : L->Tpk = gel(z,1);
1291 119 : proj = QXQV_to_FpM(L->topow, L->Tpk, L->pk);
1292 119 : if (L->topowden)
1293 119 : proj = FpM_red(ZM_Z_mul(proj, Fp_inv(L->topowden, L->pk)), L->pk);
1294 119 : L->ZqProj = proj;
1295 : }
1296 : else
1297 : {
1298 3636 : L->Tpk = NULL;
1299 3636 : L->ZqProj = dim1proj(prkHNF);
1300 : }
1301 3755 : }
1302 :
1303 : /* Square of the radius of largest ball inscript in PRK's fundamental domain,
1304 : * whose orthogonalized vector's norms are the Bi
1305 : * Rmax ^2 = min 1/4T_i where T_i = sum_j ( s_ij^2 / B_j)
1306 : * For p inert, S = Id, T_i = 1 / p^{2k} and Rmax = p^k / 2 */
1307 : static GEN
1308 3811 : max_radius(GEN PRK, GEN B)
1309 : {
1310 3811 : GEN S, smax = gen_0;
1311 3811 : pari_sp av = avma;
1312 3811 : long i, j, d = lg(PRK)-1;
1313 :
1314 3811 : S = RgM_inv( get_R(PRK) ); if (!S) pari_err_PREC("max_radius");
1315 17654 : for (i=1; i<=d; i++)
1316 : {
1317 13843 : GEN s = gen_0;
1318 154748 : for (j=1; j<=d; j++)
1319 140905 : s = mpadd(s, mpdiv( mpsqr(gcoeff(S,i,j)), gel(B,j)));
1320 13843 : if (mpcmp(s, smax) > 0) smax = s;
1321 : }
1322 3811 : return gerepileupto(av, ginv(gmul2n(smax, 2)));
1323 : }
1324 :
1325 : static void
1326 3755 : bestlift_init(long a, GEN nf, GEN C, nflift_t *L)
1327 : {
1328 3755 : const double alpha = 0.99; /* LLL parameter */
1329 3755 : const long d = nf_get_degree(nf);
1330 3755 : pari_sp av = avma, av2;
1331 3755 : GEN prk, PRK, iPRK, GSmin, T = L->Tp, p = L->p;
1332 3755 : long f = degpol(T);
1333 : pari_timer ti;
1334 :
1335 3755 : if (f == d)
1336 : { /* inert p, much simpler */
1337 21 : long a0 = bestlift_bound(C, d, alpha, p, f);
1338 : GEN q;
1339 21 : if (a < a0) a = a0; /* guarantees GSmin >= C */
1340 21 : if (DEBUGLEVEL>2) err_printf("exponent %ld\n",a);
1341 21 : q = powiu(p,a);
1342 21 : PRK = prk = scalarmat_shallow(q, d);
1343 21 : GSmin = shiftr(itor(q, DEFAULTPREC), -1);
1344 21 : iPRK = matid(d); goto END;
1345 : }
1346 3734 : timer_start(&ti);
1347 3734 : if (!a) a = (long)bestlift_bound(C, d, alpha, p, f);
1348 77 : for (;; avma = av, a += (a==1)? 1: (a>>1)) /* roughly a *= 1.5 */
1349 : {
1350 3811 : GEN B, q = powiu(p,a), Tq = FpXQ_powu(T, a, FpX_red(nf_get_pol(nf), q), q);
1351 3811 : if (DEBUGLEVEL>2) err_printf("exponent %ld\n",a);
1352 3811 : prk = idealhnf_two(nf, mkvec2(q, Tq));
1353 3811 : av2 = avma;
1354 3811 : PRK = ZM_lll_norms(prk, alpha, LLL_INPLACE, &B);
1355 3811 : GSmin = max_radius(PRK, B);
1356 3811 : if (gcmp(GSmin, C) >= 0) break;
1357 77 : }
1358 3734 : gerepileall(av2, 2, &PRK, &GSmin);
1359 3734 : iPRK = ZM_inv(PRK, NULL);
1360 3734 : if (DEBUGLEVEL>2)
1361 0 : err_printf("for this exponent, GSmin = %Ps\nTime reduction: %ld\n",
1362 : GSmin, timer_delay(&ti));
1363 : END:
1364 3755 : L->k = a;
1365 3755 : L->pk = gcoeff(prk,1,1);
1366 3755 : L->prk = PRK;
1367 3755 : L->iprk = iPRK;
1368 3755 : L->GSmin= GSmin;
1369 3755 : init_proj(L, prk, nf_get_pol(nf));
1370 3755 : }
1371 :
1372 : /* Let X = Tra * M_L, Y = bestlift(X) return V s.t Y = X - PRK V
1373 : * and set *eT2 = gexpo(Y) [cf nf_bestlift, but memory efficient] */
1374 : static GEN
1375 252 : get_V(GEN Tra, GEN M_L, GEN PRK, GEN PRKinv, GEN pk, long *eT2)
1376 : {
1377 252 : long i, e = 0, l = lg(M_L);
1378 252 : GEN V = cgetg(l, t_MAT);
1379 252 : *eT2 = 0;
1380 3563 : for (i = 1; i < l; i++)
1381 : { /* cf nf_bestlift(Tra * c) */
1382 3311 : pari_sp av = avma, av2;
1383 3311 : GEN v, T2 = ZM_ZC_mul(Tra, gel(M_L,i));
1384 :
1385 3311 : v = gdivround(ZM_ZC_mul(PRKinv, T2), pk); /* small */
1386 3311 : av2 = avma;
1387 3311 : T2 = ZC_sub(T2, ZM_ZC_mul(PRK, v));
1388 3311 : e = gexpo(T2); if (e > *eT2) *eT2 = e;
1389 3311 : avma = av2;
1390 3311 : gel(V,i) = gerepileupto(av, v); /* small */
1391 : }
1392 252 : return V;
1393 : }
1394 :
1395 : static GEN
1396 42 : nf_LLL_cmbf(nfcmbf_t *T, long rec)
1397 : {
1398 42 : const double BitPerFactor = 0.4; /* nb bits / modular factor */
1399 42 : nflift_t *L = T->L;
1400 42 : GEN famod = T->fact, ZC = T->ZC, Br = T->Br, P = T->pol, dn = T->L->dn;
1401 42 : long dnf = nf_get_degree(T->nf), dP = degpol(P);
1402 : long i, C, tmax, n0;
1403 : GEN lP, Bnorm, Tra, T2, TT, CM_L, m, list, ZERO, Btra;
1404 : double Bhigh;
1405 : pari_sp av, av2;
1406 42 : long ti_LLL = 0, ti_CF = 0;
1407 : pari_timer ti2, TI;
1408 :
1409 42 : lP = absi(leading_coeff(P));
1410 42 : if (is_pm1(lP)) lP = NULL;
1411 :
1412 42 : n0 = lg(famod) - 1;
1413 : /* Lattice: (S PRK), small vector (vS vP). To find k bound for the image,
1414 : * write S = S1 q + S0, P = P1 q + P0
1415 : * |S1 vS + P1 vP|^2 <= Bhigh for all (vS,vP) assoc. to true factors */
1416 42 : Btra = mulrr(ZC, mulur(dP*dP, normTp(Br, 2, dnf)));
1417 42 : Bhigh = get_Bhigh(n0, dnf);
1418 42 : C = (long)ceil(sqrt(Bhigh/n0)) + 1; /* C^2 n0 ~ Bhigh */
1419 42 : Bnorm = dbltor( n0 * C * C + Bhigh );
1420 42 : ZERO = zeromat(n0, dnf);
1421 :
1422 42 : av = avma;
1423 42 : TT = cgetg(n0+1, t_VEC);
1424 42 : Tra = cgetg(n0+1, t_MAT);
1425 42 : for (i=1; i<=n0; i++) TT[i] = 0;
1426 42 : CM_L = scalarmat_s(C, n0);
1427 : /* tmax = current number of traces used (and computed so far) */
1428 189 : for(tmax = 0;; tmax++)
1429 : {
1430 189 : long a, b, bmin, bgood, delta, tnew = tmax + 1, r = lg(CM_L)-1;
1431 : GEN M_L, q, CM_Lp, oldCM_L, S1, P1, VV;
1432 189 : int first = 1;
1433 :
1434 : /* bound for f . S_k(genuine factor) = ZC * bound for T_2(S_tnew) */
1435 189 : Btra = mulrr(ZC, mulur(dP*dP, normTp(Br, 2*tnew, dnf)));
1436 189 : bmin = logint(ceil_safe(sqrtr(Btra)), gen_2) + 1;
1437 189 : if (DEBUGLEVEL>2)
1438 0 : err_printf("\nLLL_cmbf: %ld potential factors (tmax = %ld, bmin = %ld)\n",
1439 : r, tmax, bmin);
1440 :
1441 : /* compute Newton sums (possibly relifting first) */
1442 189 : if (gcmp(L->GSmin, Btra) < 0)
1443 : {
1444 : GEN polred;
1445 :
1446 0 : bestlift_init((L->k)<<1, T->nf, Btra, L);
1447 0 : polred = ZqX_normalize(T->polbase, lP, L);
1448 0 : famod = ZqX_liftfact(polred, famod, L->Tpk, L->pk, L->p, L->k);
1449 0 : for (i=1; i<=n0; i++) TT[i] = 0;
1450 : }
1451 4641 : for (i=1; i<=n0; i++)
1452 : {
1453 4452 : GEN h, lPpow = lP? powiu(lP, tnew): NULL;
1454 4452 : GEN z = polsym_gen(gel(famod,i), gel(TT,i), tnew, L->Tpk, L->pk);
1455 4452 : gel(TT,i) = z;
1456 4452 : h = gel(z,tnew+1);
1457 : /* make Newton sums integral */
1458 4452 : lPpow = mul_content(lPpow, dn);
1459 4452 : if (lPpow)
1460 0 : h = (typ(h) == t_INT)? Fp_mul(h, lPpow, L->pk): FpX_Fp_mul(h, lPpow, L->pk);
1461 4452 : gel(Tra,i) = nf_bestlift(h, NULL, L); /* S_tnew(famod) */
1462 : }
1463 :
1464 : /* compute truncation parameter */
1465 189 : if (DEBUGLEVEL>2) { timer_start(&ti2); timer_start(&TI); }
1466 189 : oldCM_L = CM_L;
1467 189 : av2 = avma;
1468 189 : b = delta = 0; /* -Wall */
1469 : AGAIN:
1470 252 : M_L = Q_div_to_int(CM_L, utoipos(C));
1471 252 : VV = get_V(Tra, M_L, L->prk, L->iprk, L->pk, &a);
1472 252 : if (first)
1473 : { /* initialize lattice, using few p-adic digits for traces */
1474 189 : bgood = (long)(a - maxss(32, (long)(BitPerFactor * r)));
1475 189 : b = maxss(bmin, bgood);
1476 189 : delta = a - b;
1477 : }
1478 : else
1479 : { /* add more p-adic digits and continue reduction */
1480 63 : if (a < b) b = a;
1481 63 : b = maxss(b-delta, bmin);
1482 63 : if (b - delta/2 < bmin) b = bmin; /* near there. Go all the way */
1483 : }
1484 :
1485 : /* restart with truncated entries */
1486 252 : q = int2n(b);
1487 252 : P1 = gdivround(L->prk, q);
1488 252 : S1 = gdivround(Tra, q);
1489 252 : T2 = ZM_sub(ZM_mul(S1, M_L), ZM_mul(P1, VV));
1490 252 : m = vconcat( CM_L, T2 );
1491 252 : if (first)
1492 : {
1493 189 : first = 0;
1494 189 : m = shallowconcat( m, vconcat(ZERO, P1) );
1495 : /* [ C M_L 0 ]
1496 : * m = [ ] square matrix
1497 : * [ T2' PRK ] T2' = Tra * M_L truncated
1498 : */
1499 : }
1500 252 : CM_L = LLL_check_progress(Bnorm, n0, m, b == bmin, /*dbg:*/ &ti_LLL);
1501 252 : if (DEBUGLEVEL>2)
1502 0 : err_printf("LLL_cmbf: (a,b) =%4ld,%4ld; r =%3ld -->%3ld, time = %ld\n",
1503 0 : a,b, lg(m)-1, CM_L? lg(CM_L)-1: 1, timer_delay(&TI));
1504 294 : if (!CM_L) { list = mkcol(RgX_int_normalize(P)); break; }
1505 231 : if (b > bmin)
1506 : {
1507 63 : CM_L = gerepilecopy(av2, CM_L);
1508 63 : goto AGAIN;
1509 : }
1510 168 : if (DEBUGLEVEL>2) timer_printf(&ti2, "for this trace");
1511 :
1512 168 : i = lg(CM_L) - 1;
1513 168 : if (i == r && ZM_equal(CM_L, oldCM_L))
1514 : {
1515 91 : CM_L = oldCM_L;
1516 91 : avma = av2; continue;
1517 : }
1518 :
1519 77 : CM_Lp = FpM_image(CM_L, utoipos(27449)); /* inexpensive test */
1520 77 : if (lg(CM_Lp) != lg(CM_L))
1521 : {
1522 0 : if (DEBUGLEVEL>2) err_printf("LLL_cmbf: rank decrease\n");
1523 0 : CM_L = ZM_hnf(CM_L);
1524 : }
1525 :
1526 77 : if (i <= r && i*rec < n0)
1527 : {
1528 : pari_timer ti;
1529 35 : if (DEBUGLEVEL>2) timer_start(&ti);
1530 35 : list = nf_chk_factors(T, P, Q_div_to_int(CM_L,utoipos(C)), famod, L->pk);
1531 35 : if (DEBUGLEVEL>2) ti_CF += timer_delay(&ti);
1532 35 : if (list) break;
1533 : }
1534 56 : if (gc_needed(av,1))
1535 : {
1536 0 : if(DEBUGMEM>1) pari_warn(warnmem,"nf_LLL_cmbf");
1537 0 : gerepileall(av, L->Tpk? 9: 8,
1538 : &CM_L,&TT,&Tra,&famod,&L->GSmin,&L->pk,&L->prk,&L->iprk,
1539 : &L->Tpk);
1540 : }
1541 56 : else CM_L = gerepilecopy(av2, CM_L);
1542 147 : }
1543 42 : if (DEBUGLEVEL>2)
1544 0 : err_printf("* Time LLL: %ld\n* Time Check Factor: %ld\n",ti_LLL,ti_CF);
1545 42 : return list;
1546 : }
1547 :
1548 : static GEN
1549 1015 : nf_combine_factors(nfcmbf_t *T, GEN polred, long klim)
1550 : {
1551 1015 : nflift_t *L = T->L;
1552 : GEN res;
1553 : long maxK;
1554 : int done;
1555 : pari_timer ti;
1556 :
1557 1015 : if (DEBUGLEVEL>2) timer_start(&ti);
1558 1015 : T->fact = ZqX_liftfact(polred, T->fact, L->Tpk, L->pk, L->p, L->k);
1559 1015 : if (DEBUGLEVEL>2) timer_printf(&ti, "Hensel lift");
1560 1015 : res = nfcmbf(T, klim, &maxK, &done);
1561 1015 : if (DEBUGLEVEL>2) timer_printf(&ti, "Naive recombination");
1562 1015 : if (!done)
1563 : {
1564 42 : long l = lg(res)-1;
1565 : GEN v;
1566 42 : if (l > 1)
1567 : {
1568 7 : T->pol = gel(res,l);
1569 7 : T->polbase = RgX_to_nfX(T->nf, T->pol);
1570 : }
1571 42 : v = nf_LLL_cmbf(T, maxK);
1572 : /* remove last elt, possibly unfactored. Add all new ones. */
1573 42 : setlg(res, l); res = shallowconcat(res, v);
1574 : }
1575 1015 : return res;
1576 : }
1577 :
1578 : static GEN
1579 2325 : nf_DDF_roots(GEN pol, GEN polred, GEN nfpol, long fl, nflift_t *L)
1580 : {
1581 : GEN z, Cltx_r, ltdn;
1582 : long i, m, lz;
1583 : div_data D;
1584 :
1585 2325 : init_div_data(&D, pol, L);
1586 2325 : ltdn = mul_content(D.lt, L->dn);
1587 2325 : z = ZqX_roots(polred, L->Tpk, L->p, L->k);
1588 2325 : Cltx_r = deg1pol_shallow(D.Clt? D.Clt: gen_1, NULL, varn(pol));
1589 2325 : lz = lg(z);
1590 2325 : if (DEBUGLEVEL > 3) err_printf("Checking %ld roots:",lz-1);
1591 7075 : for (m=1,i=1; i<lz; i++)
1592 : {
1593 4750 : GEN r = gel(z,i);
1594 : int dvd;
1595 : pari_sp av;
1596 4750 : if (DEBUGLEVEL > 3) err_printf(" %ld",i);
1597 : /* lt*dn*topowden * r = Clt * r */
1598 4750 : r = nf_bestlift_to_pol(ltdn? gmul(ltdn,r): r, NULL, L);
1599 4750 : av = avma;
1600 4750 : gel(Cltx_r,2) = gneg(r); /* check P(r) == 0 */
1601 4750 : dvd = ZXQX_dvd(D.C2ltpol, Cltx_r, nfpol); /* integral */
1602 4750 : avma = av;
1603 : /* don't go on with q, usually much larger that C2ltpol */
1604 4750 : if (dvd) {
1605 4533 : if (D.Clt) r = gdiv(r, D.Clt);
1606 4533 : gel(z,m++) = r;
1607 : }
1608 217 : else if (fl == ROOTS_SPLIT) return cgetg(1, t_VEC);
1609 : }
1610 2325 : if (DEBUGLEVEL > 3) err_printf(" done\n");
1611 2325 : z[0] = evaltyp(t_VEC) | evallg(m);
1612 2325 : return z;
1613 : }
1614 :
1615 : /* returns a few factors of T in Fp of degree <= maxf, NULL if none exist */
1616 : static GEN
1617 85314 : get_good_factor(GEN T, ulong p, long maxf)
1618 : {
1619 85314 : pari_sp av = avma;
1620 85314 : GEN r, R = gel(Flx_factor(ZX_to_Flx(T,p),p), 1);
1621 85314 : if (maxf == 1)
1622 : { /* degree 1 factors are best */
1623 82206 : r = gel(R,1);
1624 82206 : if (degpol(r) == 1) return mkvec(r);
1625 : }
1626 : else
1627 : { /* otherwise, pick factor of largish degree */
1628 3108 : long i, j, dr, d = 0, l = lg(R);
1629 : GEN v;
1630 3108 : if (l == 2) return mkvec(gel(R,1)); /* inert is fine */
1631 2765 : v = cgetg(l, t_VEC);
1632 19649 : for (i = j = 1; i < l; i++)
1633 : {
1634 17416 : r = gel(R,i); dr = degpol(r);
1635 17416 : if (dr > maxf) break;
1636 16884 : if (dr != d) { gel(v,j++) = r; d = dr; }
1637 : }
1638 2765 : setlg(v,j); if (j > 1) return v;
1639 : }
1640 54982 : avma = av; return NULL; /* failure */
1641 : }
1642 :
1643 : /* n = number of modular factors, f = residue degree; nold/fold current best
1644 : * return 1 if new values are "better" than old ones */
1645 : static int
1646 23281 : record(long nold, long n, long fold, long f)
1647 : {
1648 23281 : if (!nold) return 1; /* uninitialized */
1649 18744 : if (fold == f) return n < nold;
1650 : /* if f increases, allow increasing n a little */
1651 1575 : if (fold < f) return n <= 20 || n < 1.1*nold;
1652 : /* f decreases, only allow if decreasing n a lot */
1653 637 : return n < 0.7*nold;
1654 : }
1655 : /* Optimization problem: factorization of polynomials over large Fq is slow,
1656 : * BUT bestlift correspondingly faster.
1657 : * Return maximal residue degree to be considered when picking a prime ideal */
1658 : static long
1659 5848 : get_maxf(long nfdeg)
1660 : {
1661 5848 : long maxf = 1;
1662 5848 : if (nfdeg >= 45) maxf =32;
1663 5834 : else if (nfdeg >= 30) maxf =16;
1664 5820 : else if (nfdeg >= 15) maxf = 8;
1665 5848 : return maxf;
1666 : }
1667 : /* number of maximal ideals to test before settling on best prime and number
1668 : * of factors; B = [K:Q]*deg(P) */
1669 : static long
1670 5433 : get_nbprimes(long B)
1671 : {
1672 5433 : if (B <= 128) return 5;
1673 183 : if (B <= 1024) return 20;
1674 35 : if (B <= 2048) return 65;
1675 0 : return 100;
1676 : }
1677 : /* Select a prime ideal pr over which to factor pol.
1678 : * Return the number of factors (or roots, according to flag fl) mod pr.
1679 : * Set:
1680 : * lt: leading term of polbase (t_INT or NULL [ for 1 ])
1681 : * pr: a suitable maximal ideal
1682 : * Fa: factors found mod pr
1683 : * Tp: polynomial defining Fq/Fp */
1684 : static long
1685 5433 : nf_pick_prime(GEN nf, GEN pol, long fl, GEN *lt, GEN *Tp, ulong *pp)
1686 : {
1687 5433 : GEN nfpol = nf_get_pol(nf), bad = mulii(nf_get_disc(nf), nf_get_index(nf));
1688 5433 : long nfdeg = degpol(nfpol), dpol = degpol(pol), nold = 0, fold = 1;
1689 5433 : long maxf = get_maxf(nfdeg), ct = get_nbprimes(nfdeg * dpol);
1690 : ulong p;
1691 : forprime_t S;
1692 : pari_timer ti_pr;
1693 :
1694 5433 : if (DEBUGLEVEL>3) timer_start(&ti_pr);
1695 5433 : *lt = leading_coeff(pol); /* t_INT */
1696 5433 : if (gequal1(*lt)) *lt = NULL;
1697 5433 : *pp = 0;
1698 5433 : *Tp = NULL;
1699 5433 : (void)u_forprime_init(&S, 2, ULONG_MAX);
1700 : /* select pr such that pol has the smallest number of factors, ct attempts */
1701 5433 : while ((p = u_forprime_next(&S)))
1702 : {
1703 : GEN vT;
1704 90718 : long n, i, l, ok = 0;
1705 90718 : ulong ltp = 0;
1706 :
1707 90718 : if (! umodiu(bad,p)) continue;
1708 83091 : if (*lt) { ltp = umodiu(*lt, p); if (!ltp) continue; }
1709 81950 : vT = get_good_factor(nfpol, p, maxf);
1710 81950 : if (!vT) continue;
1711 29917 : l = lg(vT);
1712 58231 : for (i = 1; i < l; i++)
1713 : {
1714 30414 : pari_sp av2 = avma;
1715 30414 : GEN T = gel(vT,i), red = RgX_to_FlxqX(pol, T, p);
1716 30414 : long f = degpol(T);
1717 30414 : if (f == 1)
1718 : { /* degree 1 */
1719 27698 : red = FlxX_to_Flx(red);
1720 27698 : if (ltp) red = Flx_normalize(red, p);
1721 27698 : if (!Flx_is_squarefree(red, p)) { avma = av2; continue; }
1722 22945 : ok = 1;
1723 22945 : n = (fl == FACTORS)? Flx_nbfact(red,p): Flx_nbroots(red,p);
1724 : }
1725 : else
1726 : {
1727 2716 : if (ltp) red = FlxqX_normalize(red, T, p);
1728 2716 : if (!FlxqX_is_squarefree(red, T, p)) { avma = av2; continue; }
1729 2436 : ok = 1;
1730 2436 : n = (fl == FACTORS)? FlxqX_nbfact(red,T,p): FlxqX_nbroots(red,T,p);
1731 : }
1732 25381 : if (fl == ROOTS_SPLIT && n < dpol) return n; /* not split */
1733 25339 : if (n <= 1)
1734 : {
1735 6160 : if (fl == FACTORS) return n; /* irreducible */
1736 6027 : if (!n) return 0; /* no root */
1737 : }
1738 23288 : if (DEBUGLEVEL>3)
1739 0 : err_printf("%3ld %s at prime (%ld,x^%ld+...)\n Time: %ld\n",
1740 : n, (fl == FACTORS)? "factors": "roots", p,f, timer_delay(&ti_pr));
1741 :
1742 23288 : if (fl == ROOTS && f==nfdeg) { *Tp = T; *pp = p; return n; }
1743 23281 : if (record(nold, n, fold, f)) { nold = n; fold = f; *Tp = T; *pp = p; }
1744 17904 : else avma = av2;
1745 : }
1746 27817 : if (ok && --ct <= 0) break;
1747 : }
1748 3333 : if (!nold) pari_err_OVERFLOW("nf_pick_prime [ran out of primes]");
1749 3333 : return nold;
1750 : }
1751 :
1752 : /* Assume lt(T) is a t_INT and T square free. Return t_VEC of irred. factors */
1753 : static GEN
1754 189 : nfsqff_trager(GEN u, GEN T, GEN dent)
1755 : {
1756 189 : long k = 0, i, lx;
1757 189 : GEN U, P, x0, mx0, fa, n = ZX_ZXY_rnfequation(T, u, &k);
1758 : int tmonic;
1759 189 : if (DEBUGLEVEL>4) err_printf("nfsqff_trager: choosing k = %ld\n",k);
1760 :
1761 : /* n guaranteed to be squarefree */
1762 189 : fa = ZX_DDF(Q_primpart(n)); lx = lg(fa);
1763 189 : if (lx == 2) return mkvec(u);
1764 :
1765 126 : tmonic = is_pm1(leading_coeff(T));
1766 126 : P = cgetg(lx,t_VEC);
1767 126 : x0 = deg1pol_shallow(stoi(-k), gen_0, varn(T));
1768 126 : mx0 = deg1pol_shallow(stoi(k), gen_0, varn(T));
1769 126 : U = RgXQX_translate(u, mx0, T);
1770 126 : if (!tmonic) U = Q_primpart(U);
1771 490 : for (i=lx-1; i>0; i--)
1772 : {
1773 364 : GEN f = gel(fa,i), F = nfgcd(U, f, T, dent);
1774 364 : F = RgXQX_translate(F, x0, T);
1775 : /* F = gcd(f, u(t - x0)) [t + x0] = gcd(f(t + x0), u), more efficient */
1776 364 : if (typ(F) != t_POL || degpol(F) == 0)
1777 0 : pari_err_IRREDPOL("factornf [modulus]",T);
1778 364 : gel(P,i) = QXQX_normalize(F, T);
1779 : }
1780 126 : gen_sort_inplace(P, (void*)&cmp_RgX, &gen_cmp_RgX, NULL);
1781 126 : return P;
1782 : }
1783 :
1784 : /* Factor polynomial a on the number field defined by polynomial T, using
1785 : * Trager's trick */
1786 : GEN
1787 14 : polfnf(GEN a, GEN T)
1788 : {
1789 14 : GEN rep = cgetg(3, t_MAT), A, B, y, dent, bad;
1790 : long dA;
1791 : int tmonic;
1792 :
1793 14 : if (typ(a)!=t_POL) pari_err_TYPE("polfnf",a);
1794 14 : if (typ(T)!=t_POL) pari_err_TYPE("polfnf",T);
1795 14 : T = Q_primpart(T); tmonic = is_pm1(leading_coeff(T));
1796 14 : RgX_check_ZX(T,"polfnf");
1797 14 : A = Q_primpart( QXQX_normalize(RgX_nffix("polfnf",T,a,1), T) );
1798 14 : dA = degpol(A);
1799 14 : if (dA <= 0)
1800 : {
1801 0 : avma = (pari_sp)(rep + 3);
1802 0 : return (dA == 0)? trivial_fact(): zerofact(varn(A));
1803 : }
1804 14 : bad = dent = ZX_disc(T);
1805 14 : if (tmonic) dent = indexpartial(T, dent);
1806 14 : (void)nfgcd_all(A,RgX_deriv(A), T, dent, &B);
1807 14 : if (degpol(B) != dA) B = Q_primpart( QXQX_normalize(B, T) );
1808 14 : ensure_lt_INT(B);
1809 14 : y = nfsqff_trager(B, T, dent);
1810 14 : fact_from_sqff(rep, A, B, y, T, bad);
1811 14 : return sort_factor_pol(rep, cmp_RgX);
1812 : }
1813 :
1814 : static int
1815 11496 : nfsqff_use_Trager(long n, long dpol)
1816 : {
1817 11496 : return dpol*3<n;
1818 : }
1819 :
1820 : /* return the factorization of the square-free polynomial pol. Not memory-clean
1821 : The coeffs of pol are in Z_nf and its leading term is a rational integer.
1822 : deg(pol) > 0, deg(nfpol) > 1
1823 : fl is either FACTORS (return factors), or ROOTS / ROOTS_SPLIT (return roots):
1824 : - ROOTS, return only the roots of x in nf
1825 : - ROOTS_SPLIT, as ROOTS if pol splits, [] otherwise
1826 : den is usually 1, otherwise nf.zk is doubtful, and den bounds the
1827 : denominator of an arbitrary element of Z_nf on nf.zk */
1828 : static GEN
1829 7232 : nfsqff(GEN nf, GEN pol, long fl, GEN den)
1830 : {
1831 7232 : long n, nbf, dpol = degpol(pol);
1832 : GEN C0, polbase;
1833 7232 : GEN N2, res, polred, lt, nfpol = typ(nf)==t_POL?nf:nf_get_pol(nf);
1834 : ulong pp;
1835 : nfcmbf_t T;
1836 : nflift_t L;
1837 : pari_timer ti, ti_tot;
1838 :
1839 7232 : if (DEBUGLEVEL>2) { timer_start(&ti); timer_start(&ti_tot); }
1840 7232 : n = degpol(nfpol);
1841 : /* deg = 1 => irreducible */
1842 7232 : if (dpol == 1) {
1843 1624 : if (fl == FACTORS) return mkvec(QXQX_normalize(pol, nfpol));
1844 1596 : return mkvec(gneg(gdiv(gel(pol,2),gel(pol,3))));
1845 : }
1846 5608 : if (typ(nf)==t_POL || nfsqff_use_Trager(n,dpol))
1847 : {
1848 : GEN z;
1849 175 : if (DEBUGLEVEL>2) err_printf("Using Trager's method\n");
1850 175 : if (typ(nf) != t_POL) den = mulii(den, nf_get_index(nf));
1851 175 : z = nfsqff_trager(Q_primpart(pol), nfpol, den);
1852 175 : if (fl != FACTORS) {
1853 147 : long i, l = lg(z);
1854 357 : for (i = 1; i < l; i++)
1855 : {
1856 280 : GEN LT, t = gel(z,i); if (degpol(t) > 1) break;
1857 210 : LT = gel(t,3);
1858 210 : if (typ(LT) == t_POL) LT = gel(LT,2); /* constant */
1859 210 : gel(z,i) = gdiv(gel(t,2), negi(LT));
1860 : }
1861 147 : setlg(z, i);
1862 147 : if (fl == ROOTS_SPLIT && i != l) return cgetg(1,t_VEC);
1863 : }
1864 175 : return z;
1865 : }
1866 :
1867 5433 : polbase = RgX_to_nfX(nf, pol);
1868 5433 : nbf = nf_pick_prime(nf, pol, fl, <, &L.Tp, &pp);
1869 5433 : if (L.Tp)
1870 : {
1871 4544 : L.Tp = Flx_to_ZX(L.Tp);
1872 4544 : L.p = utoi(pp);
1873 : }
1874 :
1875 5433 : if (fl == ROOTS_SPLIT && nbf < dpol) return cgetg(1,t_VEC);
1876 5391 : if (nbf <= 1)
1877 : {
1878 2856 : if (fl == FACTORS) return mkvec(QXQX_normalize(pol, nfpol)); /* irred. */
1879 2723 : if (!nbf) return cgetg(1,t_VEC); /* no root */
1880 : }
1881 :
1882 3340 : if (DEBUGLEVEL>2) {
1883 0 : timer_printf(&ti, "choice of a prime ideal");
1884 0 : err_printf("Prime ideal chosen: (%lu,x^%ld+...)\n", pp, degpol(L.Tp));
1885 : }
1886 3340 : L.tozk = nf_get_invzk(nf);
1887 3340 : L.topow= nf_get_zkprimpart(nf);
1888 3340 : L.topowden = nf_get_zkden(nf);
1889 3340 : if (is_pm1(den)) den = NULL;
1890 3340 : L.dn = den;
1891 3340 : T.ZC = L2_bound(nf, den);
1892 3340 : T.Br = nf_root_bounds(nf, pol); if (lt) T.Br = gmul(T.Br, lt);
1893 :
1894 : /* C0 = bound for T_2(Q_i), Q | P */
1895 3340 : if (fl != FACTORS) C0 = normTp(T.Br, 2, n);
1896 1015 : else C0 = nf_factor_bound(nf, polbase);
1897 3340 : T.bound = mulrr(T.ZC, C0); /* bound for |Q_i|^2 in Z^n on chosen Z-basis */
1898 :
1899 3340 : N2 = mulur(dpol*dpol, normTp(T.Br, 4, n)); /* bound for T_2(lt * S_2) */
1900 3340 : T.BS_2 = mulrr(T.ZC, N2); /* bound for |S_2|^2 on chosen Z-basis */
1901 :
1902 3340 : if (DEBUGLEVEL>2) {
1903 0 : timer_printf(&ti, "bound computation");
1904 0 : err_printf(" 1) T_2 bound for %s: %Ps\n",
1905 : fl == FACTORS?"factor": "root", C0);
1906 0 : err_printf(" 2) Conversion from T_2 --> | |^2 bound : %Ps\n", T.ZC);
1907 0 : err_printf(" 3) Final bound: %Ps\n", T.bound);
1908 : }
1909 :
1910 3340 : bestlift_init(0, nf, T.bound, &L);
1911 3340 : if (DEBUGLEVEL>2) timer_start(&ti);
1912 3340 : polred = ZqX_normalize(polbase, lt, &L); /* monic */
1913 :
1914 3340 : if (fl != FACTORS) {
1915 2325 : GEN z = nf_DDF_roots(pol, polred, nfpol, fl, &L);
1916 2325 : if (lg(z) == 1) return cgetg(1, t_VEC);
1917 2269 : return z;
1918 : }
1919 :
1920 1015 : T.fact = gel(FqX_factor(polred, L.Tp, L.p), 1);
1921 1015 : if (DEBUGLEVEL>2)
1922 0 : timer_printf(&ti, "splitting mod %Ps^%ld", L.p, degpol(L.Tp));
1923 1015 : T.L = &L;
1924 1015 : T.polbase = polbase;
1925 1015 : T.pol = pol;
1926 1015 : T.nf = nf;
1927 1015 : res = nf_combine_factors(&T, polred, dpol-1);
1928 1015 : if (DEBUGLEVEL>2)
1929 0 : err_printf("Total Time: %ld\n===========\n", timer_delay(&ti_tot));
1930 1015 : return res;
1931 : }
1932 :
1933 : /* assume pol monic in nf.zk[X] */
1934 : GEN
1935 84 : nfroots_if_split(GEN *pnf, GEN pol)
1936 : {
1937 84 : GEN T = get_nfpol(*pnf,pnf), den = fix_nf(pnf, &T, &pol);
1938 84 : pari_sp av = avma;
1939 84 : GEN z = nfsqff(*pnf, pol, ROOTS_SPLIT, den);
1940 84 : if (lg(z) == 1) { avma = av; return NULL; }
1941 42 : return gerepilecopy(av, z);
1942 : }
1943 :
1944 : /*******************************************************************/
1945 : /* */
1946 : /* Roots of unity in a number field */
1947 : /* (alternative to nfrootsof1 using factorization in K[X]) */
1948 : /* */
1949 : /*******************************************************************/
1950 : /* Code adapted from nffactor. Structure of the algorithm; only step 1 is
1951 : * specific to roots of unity.
1952 : *
1953 : * [Step 1]: guess roots via ramification. If trivial output this.
1954 : * [Step 2]: select prime [p] unramified and ideal [pr] above
1955 : * [Step 3]: evaluate the maximal exponent [k] such that the fondamental domain
1956 : * of a LLL-reduction of [prk] = pr^k contains a ball of radius larger
1957 : * than the norm of any root of unity.
1958 : * [Step 3]: select a heuristic exponent,
1959 : * LLL reduce prk=pr^k and verify the exponent is sufficient,
1960 : * otherwise try a larger one.
1961 : * [Step 4]: factor the cyclotomic polynomial mod [pr],
1962 : * Hensel lift to pr^k and find the representative in the ball
1963 : * If there is it is a primitive root */
1964 :
1965 : /* Choose prime ideal unramified with "large" inertia degree */
1966 : static void
1967 415 : nf_pick_prime_for_units(GEN nf, nflift_t *L)
1968 : {
1969 415 : GEN nfpol = nf_get_pol(nf), bad = mulii(nf_get_disc(nf), nf_get_index(nf));
1970 415 : GEN ap = NULL, r = NULL;
1971 415 : long nfdeg = degpol(nfpol), maxf = get_maxf(nfdeg);
1972 : ulong pp;
1973 : forprime_t S;
1974 :
1975 415 : (void)u_forprime_init(&S, 2, ULONG_MAX);
1976 415 : while ( (pp = u_forprime_next(&S)) )
1977 : {
1978 4451 : if (! umodiu(bad,pp)) continue;
1979 3364 : r = get_good_factor(nfpol, pp, maxf);
1980 3364 : if (r) break;
1981 : }
1982 415 : if (!r) pari_err_OVERFLOW("nf_pick_prime [ran out of primes]");
1983 415 : r = gel(r,lg(r)-1); /* largest inertia degree */
1984 415 : ap = utoipos(pp);
1985 415 : L->p = ap;
1986 415 : L->Tp = Flx_to_ZX(r);
1987 415 : L->tozk = nf_get_invzk(nf);
1988 415 : L->topow = nf_get_zkprimpart(nf);
1989 415 : L->topowden = nf_get_zkden(nf);
1990 415 : }
1991 :
1992 : /* *Heuristic* exponent k such that the fundamental domain of pr^k
1993 : * should contain the ball of radius C */
1994 : static double
1995 415 : mybestlift_bound(GEN C)
1996 : {
1997 415 : C = gtofp(C,DEFAULTPREC);
1998 415 : return ceil(log(gtodouble(C)) / 0.2) + 3;
1999 : }
2000 :
2001 : /* simplified nf_DDF_roots: polcyclo(n) monic in ZX either splits or has no
2002 : * root in nf.
2003 : * Return a root or NULL (no root) */
2004 : static GEN
2005 429 : nfcyclo_root(long n, GEN nfpol, nflift_t *L)
2006 : {
2007 429 : GEN q, r, Cltx_r, pol = polcyclo(n,0), gn = utoipos(n);
2008 : div_data D;
2009 :
2010 429 : init_div_data(&D, pol, L);
2011 429 : (void)Fq_sqrtn(gen_1, gn, L->Tp, L->p, &r);
2012 : /* r primitive n-th root of 1 in Fq */
2013 429 : r = Zq_sqrtnlift(gen_1, gn, r, L->Tpk, L->p, L->k);
2014 : /* lt*dn*topowden * r = Clt * r */
2015 429 : r = nf_bestlift_to_pol(r, NULL, L);
2016 429 : Cltx_r = deg1pol_shallow(D.Clt? D.Clt: gen_1, gneg(r), varn(pol));
2017 : /* check P(r) == 0 */
2018 429 : q = RgXQX_divrem(D.C2ltpol, Cltx_r, nfpol, ONLY_DIVIDES); /* integral */
2019 429 : if (!q) return NULL;
2020 401 : if (D.Clt) r = gdiv(r, D.Clt);
2021 401 : return r;
2022 : }
2023 :
2024 : /* Guesses the number of roots of unity in number field [nf].
2025 : * Computes gcd of N(P)-1 for some primes. The value returned is a proven
2026 : * multiple of the correct value. */
2027 : static long
2028 5840 : guess_roots(GEN nf)
2029 : {
2030 5840 : long c = 0, nfdegree = nf_get_degree(nf), B = nfdegree + 20, l;
2031 5840 : ulong p = 2;
2032 5840 : GEN T = nf_get_pol(nf), D = nf_get_disc(nf), index = nf_get_index(nf);
2033 5840 : GEN nbroots = NULL;
2034 : forprime_t S;
2035 : pari_sp av;
2036 :
2037 5840 : (void)u_forprime_init(&S, 3, ULONG_MAX);
2038 5840 : av = avma;
2039 : /* result must be stationary (counter c) for at least B loops */
2040 162010 : for (l=1; (p = u_forprime_next(&S)); l++)
2041 : {
2042 : GEN old, F, pf_1, Tp;
2043 162010 : long i, nb, gcdf = 0;
2044 :
2045 162010 : if (!umodiu(D,p) || !umodiu(index,p)) continue;
2046 155293 : Tp = ZX_to_Flx(T,p); /* squarefree */
2047 155293 : F = Flx_nbfact_by_degree(Tp, &nb, p);
2048 : /* the gcd of the p^f - 1 is p^(gcd of the f's) - 1 */
2049 524742 : for (i = 1; i <= nfdegree; i++)
2050 438029 : if (F[i]) {
2051 155671 : gcdf = gcdf? cgcd(gcdf, i): i;
2052 155671 : if (gcdf == 1) break;
2053 : }
2054 155293 : pf_1 = subiu(powuu(p, gcdf), 1);
2055 155293 : old = nbroots;
2056 155293 : nbroots = nbroots? gcdii(pf_1, nbroots): pf_1;
2057 155293 : if (DEBUGLEVEL>5)
2058 0 : err_printf("p=%lu; gcf(f(P/p))=%ld; nbroots | %Ps",p, gcdf, nbroots);
2059 : /* if same result go on else reset the stop counter [c] */
2060 155293 : if (old && equalii(nbroots,old))
2061 144332 : { if (!is_bigint(nbroots) && ++c > B) break; }
2062 : else
2063 10961 : c = 0;
2064 : }
2065 5840 : if (!nbroots) pari_err_OVERFLOW("guess_roots [ran out of primes]");
2066 5840 : if (DEBUGLEVEL>5) err_printf("%ld loops\n",l);
2067 5840 : avma = av; return itos(nbroots);
2068 : }
2069 :
2070 : /* T(x) an irreducible ZX. Is it of the form Phi_n(c \pm x) ?
2071 : * Return NULL if not, and a root of 1 of maximal order in Z[x]/(T) otherwise
2072 : *
2073 : * N.B. Set n_squarefree = 1 if n is squarefree, and 0 otherwise.
2074 : * This last parameter is inconvenient, but it allows a cheap
2075 : * stringent test. (n guessed from guess_roots())*/
2076 : static GEN
2077 1127 : ZXirred_is_cyclo_translate(GEN T, long n_squarefree)
2078 : {
2079 1127 : long r, m, d = degpol(T);
2080 1127 : GEN T1, c = divis_rem(gel(T, d+1), d, &r); /* d-1 th coeff divisible by d ? */
2081 : /* The trace coefficient of polcyclo(n) is \pm1 if n is square free, and 0
2082 : * otherwise. */
2083 1127 : if (!n_squarefree)
2084 546 : { if (r) return NULL; }
2085 : else
2086 : {
2087 581 : if (r < -1)
2088 : {
2089 0 : r += d;
2090 0 : c = subiu(c, 1);
2091 : }
2092 581 : else if (r == d-1)
2093 : {
2094 35 : r = -1;
2095 35 : c = addiu(c, 1);
2096 : }
2097 581 : if (r != 1 && r != -1) return NULL;
2098 : }
2099 1078 : if (signe(c)) /* presumably Phi_guess(c \pm x) */
2100 35 : T = RgX_translate(T, negi(c));
2101 1078 : if (!n_squarefree) T = RgX_deflate_max(T, &m);
2102 : /* presumably Phi_core(guess)(\pm x), cyclotomic iff original T was */
2103 1078 : T1 = ZX_graeffe(T);
2104 1078 : if (ZX_equal(T, T1)) /* T = Phi_n, n odd */
2105 35 : return deg1pol_shallow(gen_m1, negi(c), varn(T));
2106 1043 : else if (ZX_equal(T1, ZX_z_unscale(T, -1))) /* T = Phi_{2n}, nodd */
2107 1022 : return deg1pol_shallow(gen_1, c, varn(T));
2108 21 : return NULL;
2109 : }
2110 :
2111 : static GEN
2112 6831 : trivroots(void) { return mkvec2(gen_2, gen_m1); }
2113 : /* Number of roots of unity in number field [nf]. */
2114 : GEN
2115 8303 : rootsof1(GEN nf)
2116 : {
2117 : nflift_t L;
2118 : GEN T, q, fa, LP, LE, C0, z, disc;
2119 : pari_timer ti;
2120 : long i, l, nbguessed, nbroots, nfdegree;
2121 : pari_sp av;
2122 :
2123 8303 : nf = checknf(nf);
2124 8303 : if (nf_get_r1(nf)) return trivroots();
2125 :
2126 : /* Step 1 : guess number of roots and discard trivial case 2 */
2127 5840 : if (DEBUGLEVEL>2) timer_start(&ti);
2128 5840 : nbguessed = guess_roots(nf);
2129 5840 : if (DEBUGLEVEL>2)
2130 0 : timer_printf(&ti, "guessing roots of 1 [guess = %ld]", nbguessed);
2131 5840 : if (nbguessed == 2) return trivroots();
2132 :
2133 1472 : nfdegree = nf_get_degree(nf);
2134 1472 : fa = factoru(nbguessed);
2135 1472 : LP = gel(fa,1); l = lg(LP);
2136 1472 : LE = gel(fa,2);
2137 1472 : disc = nf_get_disc(nf);
2138 3841 : for (i = 1; i < l; i++)
2139 : {
2140 2369 : long p = LP[i];
2141 : /* Degree and ramification test: find largest k such that Q(zeta_{p^k})
2142 : * may be a subfield of K. Q(zeta_p^k) has degree (p-1)p^(k-1)
2143 : * and v_p(discriminant) = ((p-1)k-1)p^(k-1); so we must have
2144 : * v_p(disc_K) >= ((p-1)k-1) * n / (p-1) = kn - q, where q = n/(p-1) */
2145 2369 : if (p == 2)
2146 : { /* the test simplifies a little in that case */
2147 : long v, vnf, k;
2148 1472 : if (LE[i] == 1) continue;
2149 631 : vnf = vals(nfdegree);
2150 631 : v = vali(disc);
2151 659 : for (k = minss(LE[i], vnf+1); k >= 1; k--)
2152 659 : if (v >= nfdegree*(k-1)) { nbguessed >>= LE[i]-k; LE[i] = k; break; }
2153 : /* N.B the test above always works for k = 1: LE[i] >= 1 */
2154 : }
2155 : else
2156 : {
2157 : long v, vnf, k;
2158 897 : ulong r, q = udivuu_rem(nfdegree, p-1, &r);
2159 897 : if (r) { nbguessed /= upowuu(p, LE[i]); LE[i] = 0; continue; }
2160 : /* q = n/(p-1) */
2161 897 : vnf = u_lval(q, p);
2162 897 : v = Z_lval(disc, p);
2163 897 : for (k = minss(LE[i], vnf+1); k >= 0; k--)
2164 897 : if (v >= nfdegree*k-(long)q)
2165 897 : { nbguessed /= upowuu(p, LE[i]-k); LE[i] = k; break; }
2166 : /* N.B the test above always works for k = 0: LE[i] >= 0 */
2167 : }
2168 : }
2169 1472 : if (DEBUGLEVEL>2)
2170 0 : timer_printf(&ti, "after ramification conditions [guess = %ld]", nbguessed);
2171 1472 : if (nbguessed == 2) return trivroots();
2172 1472 : av = avma;
2173 :
2174 : /* Step 1.5 : test if nf.pol == subst(polcyclo(nbguessed), x, \pm x+c) */
2175 1472 : T = nf_get_pol(nf);
2176 1472 : if (eulerphiu_fact(fa) == (ulong)nfdegree)
2177 : {
2178 1127 : z = ZXirred_is_cyclo_translate(T, uissquarefree_fact(fa));
2179 1127 : if (DEBUGLEVEL>2) timer_printf(&ti, "checking for cyclotomic polynomial");
2180 1127 : if (z)
2181 : {
2182 1057 : z = nf_to_scalar_or_basis(nf,z);
2183 1057 : return gerepilecopy(av, mkvec2(utoipos(nbguessed), z));
2184 : }
2185 70 : avma = av;
2186 : }
2187 :
2188 : /* Step 2 : choose a prime ideal for local lifting */
2189 415 : nf_pick_prime_for_units(nf, &L);
2190 415 : if (DEBUGLEVEL>2)
2191 0 : timer_printf(&ti, "choosing prime %Ps, degree %ld",
2192 0 : L.p, L.Tp? degpol(L.Tp): 1);
2193 :
2194 : /* Step 3 : compute a reduced pr^k allowing lifting of local solutions */
2195 : /* evaluate maximum L2 norm of a root of unity in nf */
2196 415 : C0 = gmulsg(nfdegree, L2_bound(nf, gen_1));
2197 : /* lift and reduce pr^k */
2198 415 : if (DEBUGLEVEL>2) err_printf("Lift pr^k; GSmin wanted: %Ps\n",C0);
2199 415 : bestlift_init((long)mybestlift_bound(C0), nf, C0, &L);
2200 415 : L.dn = NULL;
2201 415 : if (DEBUGLEVEL>2) timer_start(&ti);
2202 :
2203 : /* Step 4 : actual computation of roots */
2204 415 : nbroots = 2; z = gen_m1;
2205 415 : q = powiu(L.p,degpol(L.Tp));
2206 1174 : for (i = 1; i < l; i++)
2207 : { /* for all prime power factors of nbguessed, find a p^k-th root of unity */
2208 759 : long k, p = LP[i];
2209 1117 : for (k = minss(LE[i], Z_lval(subiu(q,1UL),p)); k > 0; k--)
2210 : { /* find p^k-th roots */
2211 759 : pari_sp av = avma;
2212 759 : long pk = upowuu(p,k);
2213 : GEN r;
2214 759 : if (pk==2) continue; /* no need to test second roots ! */
2215 429 : r = nfcyclo_root(pk, T, &L);
2216 429 : if (DEBUGLEVEL>2) timer_printf(&ti, "for factoring Phi_%ld^%ld", p,k);
2217 429 : if (r) {
2218 401 : if (DEBUGLEVEL>2) err_printf(" %s root of unity found\n",uordinal(pk));
2219 401 : if (p==2) { nbroots = pk; z = r; }
2220 323 : else { nbroots *= pk; z = nfmul(nf, z,r); }
2221 401 : break;
2222 : }
2223 28 : avma = av;
2224 28 : if (DEBUGLEVEL) pari_warn(warner,"rootsof1: wrong guess");
2225 : }
2226 : }
2227 415 : return gerepilecopy(av, mkvec2(utoi(nbroots), z));
2228 : }
2229 :
2230 : static long
2231 0 : zk_equal1(GEN y)
2232 : {
2233 0 : if (typ(y) == t_INT) return equali1(y);
2234 0 : return equali1(gel(y,1)) && ZV_isscalar(y);
2235 : }
2236 : /* x^w = 1 */
2237 : static GEN
2238 0 : is_primitive_root(GEN nf, GEN fa, GEN x, long w)
2239 : {
2240 0 : GEN P = gel(fa,1);
2241 0 : long i, l = lg(P);
2242 :
2243 0 : for (i = 1; i < l; i++)
2244 : {
2245 0 : long p = itos(gel(P,i));
2246 0 : GEN y = nfpow_u(nf,x, w/p);
2247 0 : if (zk_equal1(y) > 0) /* y = 1 */
2248 : {
2249 0 : if (p != 2 || !equali1(gcoeff(fa,i,2))) return NULL;
2250 0 : x = gneg_i(x);
2251 : }
2252 : }
2253 0 : return x;
2254 : }
2255 : GEN
2256 0 : rootsof1_kannan(GEN nf)
2257 : {
2258 0 : pari_sp av = avma;
2259 : long N, k, i, ws, prec;
2260 : GEN z, y, d, list, w;
2261 :
2262 0 : nf = checknf(nf);
2263 0 : if ( nf_get_r1(nf) ) return trivroots();
2264 :
2265 0 : N = nf_get_degree(nf); prec = nf_get_prec(nf);
2266 : for (;;)
2267 : {
2268 0 : GEN R = R_from_QR(nf_get_G(nf), prec);
2269 0 : if (R)
2270 : {
2271 0 : y = fincke_pohst(mkvec(R), utoipos(N), N * N, 0, NULL);
2272 0 : if (y) break;
2273 : }
2274 0 : prec = precdbl(prec);
2275 0 : if (DEBUGLEVEL) pari_warn(warnprec,"rootsof1",prec);
2276 0 : nf = nfnewprec_shallow(nf,prec);
2277 0 : }
2278 0 : if (itos(ground(gel(y,2))) != N) pari_err_BUG("rootsof1 (bug1)");
2279 0 : w = gel(y,1); ws = itos(w);
2280 0 : if (ws == 2) { avma = av; return trivroots(); }
2281 :
2282 0 : d = Z_factor(w); list = gel(y,3); k = lg(list);
2283 0 : for (i=1; i<k; i++)
2284 : {
2285 0 : z = is_primitive_root(nf, d, gel(list,i), ws);
2286 0 : if (z) return gerepilecopy(av, mkvec2(w, z));
2287 : }
2288 0 : pari_err_BUG("rootsof1");
2289 : return NULL; /* LCOV_EXCL_LINE */
2290 : }
|