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