Annotation of OpenXM_contrib/pari-2.2/src/basemath/polarit1.c, Revision 1.2
1.2 ! noro 1: /* $Id: polarit1.c,v 1.114 2002/09/11 02:29:15 karim Exp $
1.1 noro 2:
3: Copyright (C) 2000 The PARI group.
4:
5: This file is part of the PARI/GP package.
6:
7: PARI/GP is free software; you can redistribute it and/or modify it under the
8: terms of the GNU General Public License as published by the Free Software
9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
10: ANY WARRANTY WHATSOEVER.
11:
12: Check the License for details. You should have received a copy of it, along
13: with the package; see the file 'COPYING'. If not, write to the Free Software
14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
15:
16: /***********************************************************************/
17: /** **/
18: /** ARITHMETIC OPERATIONS ON POLYNOMIALS **/
19: /** (first part) **/
20: /** **/
21: /***********************************************************************/
22: #include "pari.h"
23: extern GEN get_bas_den(GEN bas);
1.2 ! noro 24: extern GEN get_mul_table(GEN x,GEN bas,GEN invbas);
1.1 noro 25: extern GEN pol_to_monic(GEN pol, GEN *lead);
26:
1.2 ! noro 27: #define lswap(x,y) { long _t=x; x=y; y=_t; }
! 28: #define swap(x,y) { GEN _t=x; x=y; y=_t; }
! 29:
1.1 noro 30: /* see splitgen() for how to use these two */
31: GEN
32: setloop(GEN a)
33: {
1.2 ! noro 34: a=icopy(a); (void)new_chunk(2); /* dummy to get two cells of extra space */
1.1 noro 35: return a;
36: }
37:
38: /* assume a > 0 */
39: GEN
40: incpos(GEN a)
41: {
42: long i,l=lgefint(a);
43:
44: for (i=l-1; i>1; i--)
45: if (++a[i]) return a;
46: i=l+1; a--; /* use extra cell */
47: a[0]=evaltyp(1) | evallg(i);
48: a[1]=evalsigne(1) | evallgefint(i);
49: return a;
50: }
51:
52: GEN
53: incloop(GEN a)
54: {
55: long i,l;
56:
57: switch(signe(a))
58: {
59: case 0:
60: a--; /* use extra cell */
61: a[0]=evaltyp(t_INT) | evallg(3);
62: a[1]=evalsigne(1) | evallgefint(3);
63: a[2]=1; return a;
64:
65: case -1:
66: l=lgefint(a);
67: for (i=l-1; i>1; i--)
68: if (a[i]--) break;
69: if (a[2] == 0)
70: {
71: a++; /* save one cell */
72: a[0] = evaltyp(t_INT) | evallg(2);
73: a[1] = evalsigne(0) | evallgefint(2);
74: }
75: return a;
76:
77: default:
78: return incpos(a);
79: }
80: }
81:
82: /*******************************************************************/
83: /* */
84: /* DIVISIBILITE */
85: /* Return 1 if y | x, 0 otherwise */
86: /* */
87: /*******************************************************************/
88:
89: int
90: gdivise(GEN x, GEN y)
91: {
1.2 ! noro 92: gpmem_t av=avma;
1.1 noro 93: x=gmod(x,y); avma=av; return gcmp0(x);
94: }
95:
96: int
97: poldivis(GEN x, GEN y, GEN *z)
98: {
1.2 ! noro 99: gpmem_t av = avma;
1.1 noro 100: GEN p1 = poldivres(x,y,ONLY_DIVIDES);
101: if (p1) { *z = p1; return 1; }
102: avma=av; return 0;
103: }
104:
105: /*******************************************************************/
106: /* */
107: /* POLYNOMIAL EUCLIDEAN DIVISION */
108: /* */
109: /*******************************************************************/
110: /* Polynomial division x / y:
111: * if z = ONLY_REM return remainder, otherwise return quotient
112: * if z != NULL set *z to remainder
113: * *z is the last object on stack (and thus can be disposed of with cgiv
1.2 ! noro 114: * instead of gerepile) */
1.1 noro 115: GEN
116: poldivres(GEN x, GEN y, GEN *pr)
117: {
1.2 ! noro 118: gpmem_t avy, av, av1;
1.1 noro 119: long ty=typ(y),tx,vx,vy,dx,dy,dz,i,j,sx,lrem;
120: GEN z,p1,rem,y_lead,mod;
121: GEN (*f)(GEN,GEN);
122:
1.2 ! noro 123: f = gdiv;
1.1 noro 124: if (is_scalar_t(ty))
125: {
126: if (pr == ONLY_REM) return gzero;
127: if (pr && pr != ONLY_DIVIDES) *pr=gzero;
128: return f(x,y);
129: }
130: tx=typ(x); vy=gvar9(y);
131: if (is_scalar_t(tx) || gvar9(x)>vy)
132: {
133: if (pr == ONLY_REM) return gcopy(x);
134: if (pr == ONLY_DIVIDES) return gcmp0(x)? gzero: NULL;
135: if (pr) *pr=gcopy(x);
136: return gzero;
137: }
138: if (tx!=t_POL || ty!=t_POL) err(typeer,"euclidean division (poldivres)");
139:
140: vx=varn(x);
141: if (vx<vy)
142: {
143: if (pr && pr != ONLY_DIVIDES)
144: {
145: p1 = zeropol(vx); if (pr == ONLY_REM) return p1;
146: *pr = p1;
147: }
148: return f(x,y);
149: }
150:
1.2 ! noro 151: if (!signe(y)) err(talker,"division by zero in poldivrem");
! 152: dy = degpol(y);
! 153: y_lead = (GEN)y[dy+2];
1.1 noro 154: if (gcmp0(y_lead)) /* normalize denominator if leading term is 0 */
155: {
156: err(warner,"normalizing a polynomial with 0 leading term");
157: for (dy--; dy>=0; dy--)
158: {
159: y_lead = (GEN)y[dy+2];
160: if (!gcmp0(y_lead)) break;
161: }
162: }
163: if (!dy) /* y is constant */
164: {
165: if (pr && pr != ONLY_DIVIDES)
166: {
167: if (pr == ONLY_REM) return zeropol(vx);
168: *pr = zeropol(vx);
169: }
170: return f(x, constant_term(y));
171: }
1.2 ! noro 172: dx = degpol(x);
1.1 noro 173: if (vx>vy || dx<dy)
174: {
175: if (pr)
176: {
177: if (pr == ONLY_DIVIDES) return gcmp0(x)? gzero: NULL;
178: if (pr == ONLY_REM) return gcopy(x);
179: *pr = gcopy(x);
180: }
181: return zeropol(vy);
182: }
1.2 ! noro 183:
! 184: /* x,y in R[X], y non constant */
! 185: dz = dx-dy; av = avma;
1.1 noro 186: p1 = new_chunk(dy+3);
187: for (i=2; i<dy+3; i++)
188: {
189: GEN p2 = (GEN)y[i];
1.2 ! noro 190: /* gneg to avoid gsub's later on */
1.1 noro 191: p1[i] = isexactzero(p2)? 0: (long)gneg_i(p2);
192: }
193: y = p1;
194: switch(typ(y_lead))
195: {
196: case t_INTMOD:
197: case t_POLMOD: y_lead = ginv(y_lead);
198: f = gmul; mod = gmodulcp(gun, (GEN)y_lead[1]);
199: break;
200: default: if (gcmp1(y_lead)) y_lead = NULL;
201: mod = NULL;
202: }
1.2 ! noro 203: avy=avma;
! 204: z = cgetg(dz+3,t_POL);
! 205: z[1] = evalsigne(1) | evallgef(dz+3) | evalvarn(vx);
1.1 noro 206: x += 2; y += 2; z += 2;
207:
1.2 ! noro 208: p1 = (GEN)x[dx];
! 209: z[dz] = y_lead? (long)f(p1,y_lead): lcopy(p1);
1.1 noro 210: for (i=dx-1; i>=dy; i--)
211: {
212: av1=avma; p1=(GEN)x[i];
213: for (j=i-dy+1; j<=i && j<=dz; j++)
1.2 ! noro 214: if (y[i-j] && z[j] != zero) p1 = gadd(p1, gmul((GEN)z[j],(GEN)y[i-j]));
1.1 noro 215: if (y_lead) p1 = f(p1,y_lead);
1.2 ! noro 216:
! 217: if (isexactzero(p1)) { avma=av1; p1 = gzero; }
! 218: else
! 219: p1 = avma==av1? gcopy(p1): gerepileupto(av1,p1);
1.1 noro 220: z[i-dy] = (long)p1;
221: }
222: if (!pr) return gerepileupto(av,z-2);
223:
1.2 ! noro 224: rem = (GEN)avma; av1 = (gpmem_t)new_chunk(dx+3);
1.1 noro 225: for (sx=0; ; i--)
226: {
227: p1 = (GEN)x[i];
228: /* we always enter this loop at least once */
229: for (j=0; j<=i && j<=dz; j++)
1.2 ! noro 230: if (y[i-j] && z[j] != zero) p1 = gadd(p1, gmul((GEN)z[j],(GEN)y[i-j]));
1.1 noro 231: if (mod && avma==av1) p1 = gmul(p1,mod);
232: if (!gcmp0(p1)) { sx = 1; break; } /* remainder is non-zero */
233: if (!isinexactreal(p1) && !isexactzero(p1)) break;
234: if (!i) break;
235: avma=av1;
236: }
237: if (pr == ONLY_DIVIDES)
238: {
239: if (sx) { avma=av; return NULL; }
1.2 ! noro 240: avma = (gpmem_t)rem;
1.1 noro 241: return gerepileupto(av,z-2);
242: }
243: lrem=i+3; rem -= lrem;
1.2 ! noro 244: if (avma==av1) { avma = (gpmem_t)rem; p1 = gcopy(p1); }
! 245: else p1 = gerepileupto((gpmem_t)rem,p1);
1.1 noro 246: rem[0]=evaltyp(t_POL) | evallg(lrem);
247: rem[1]=evalsigne(1) | evalvarn(vx) | evallgef(lrem);
248: rem += 2;
249: rem[i]=(long)p1;
250: for (i--; i>=0; i--)
251: {
252: av1=avma; p1 = (GEN)x[i];
253: for (j=0; j<=i && j<=dz; j++)
1.2 ! noro 254: if (y[i-j] && z[j] != zero) p1 = gadd(p1, gmul((GEN)z[j],(GEN)y[i-j]));
1.1 noro 255: if (mod && avma==av1) p1 = gmul(p1,mod);
256: rem[i]=avma==av1? lcopy(p1):lpileupto(av1,p1);
257: }
258: rem -= 2;
1.2 ! noro 259: if (!sx) (void)normalizepol_i(rem, lrem);
! 260: if (pr == ONLY_REM) return gerepileupto(av,rem);
1.1 noro 261: z -= 2;
262: {
263: GEN *gptr[2]; gptr[0]=&z; gptr[1]=&rem;
264: gerepilemanysp(av,avy,gptr,2); *pr = rem; return z;
265: }
266: }
267:
268: /*******************************************************************/
269: /* */
270: /* ROOTS MODULO a prime p (no multiplicities) */
271: /* */
272: /*******************************************************************/
273: static GEN
274: mod(GEN x, GEN y)
275: {
276: GEN z = cgetg(3,t_INTMOD);
277: z[1]=(long)y; z[2]=(long)x; return z;
278: }
279:
280: static long
281: factmod_init(GEN *F, GEN pp, long *p)
282: {
283: GEN f = *F;
284: long i,d;
285: if (typ(f)!=t_POL || typ(pp)!=t_INT) err(typeer,"factmod");
286: if (expi(pp) > BITS_IN_LONG - 3) *p = 0;
287: else
288: {
289: *p = itos(pp);
290: if (*p < 2) err(talker,"not a prime in factmod");
291: }
292: f = gmul(f, mod(gun,pp));
293: if (!signe(f)) err(zeropoler,"factmod");
294: f = lift_intern(f); d = lgef(f);
1.2 ! noro 295: for (i=2; i <d; i++)
1.1 noro 296: if (typ(f[i])!=t_INT) err(impl,"factormod for general polynomials");
297: *F = f; return d-3;
298: }
299:
300: #define mods(x,y) mod(stoi(x),y)
301: static GEN
302: root_mod_2(GEN f)
303: {
304: int z1, z0 = !signe(constant_term(f));
305: long i,n;
306: GEN y;
307:
308: for (i=2, n=1; i < lgef(f); i++)
309: if (signe(f[i])) n++;
310: z1 = n & 1;
311: y = cgetg(z0+z1+1, t_COL); i = 1;
312: if (z0) y[i++] = (long)mods(0,gdeux);
313: if (z1) y[i] = (long)mods(1,gdeux);
314: return y;
315: }
316:
317: #define i_mod4(x) (signe(x)? mod4((GEN)(x)): 0)
318: static GEN
319: root_mod_4(GEN f)
320: {
321: long no,ne;
322: int z0 = !signe(constant_term(f));
323: int z2 = ((i_mod4(constant_term(f)) + 2*i_mod4(f[3])) & 3) == 0;
324: int i,z1,z3;
325: GEN y,p;
326:
327: for (ne=0,i=2; i<lgef(f); i+=2)
328: if (signe(f[i])) ne += mael(f,i,2);
329: for (no=0,i=3; i<lgef(f); i+=2)
330: if (signe(f[i])) no += mael(f,i,2);
331: no &= 3; ne &= 3;
332: z3 = (no == ne);
333: z1 = (no == ((4-ne)&3));
334: y=cgetg(1+z0+z1+z2+z3,t_COL); i = 1; p = stoi(4);
335: if (z0) y[i++] = (long)mods(0,p);
336: if (z1) y[i++] = (long)mods(1,p);
337: if (z2) y[i++] = (long)mods(2,p);
338: if (z3) y[i] = (long)mods(3,p);
339: return y;
340: }
341: #undef i_mod4
342:
343: /* p even, accept p = 4 for p-adic stuff */
344: static GEN
345: root_mod_even(GEN f, long p)
346: {
347: switch(p)
348: {
349: case 2: return root_mod_2(f);
350: case 4: return root_mod_4(f);
351: }
352: err(talker,"not a prime in rootmod");
353: return NULL; /* not reached */
354: }
355:
356: /* by checking f(0..p-1) */
357: GEN
358: rootmod2(GEN f, GEN pp)
359: {
360: GEN g,y,ss,q,r, x_minus_s;
1.2 ! noro 361: long p, d, i, nbrac;
! 362: gpmem_t av = avma, av1;
1.1 noro 363:
364: if (!(d = factmod_init(&f, pp, &p))) { avma=av; return cgetg(1,t_COL); }
365: if (!p) err(talker,"prime too big in rootmod2");
366: if ((p & 1) == 0) { avma = av; return root_mod_even(f,p); }
367: x_minus_s = gadd(polx[varn(f)], stoi(-1));
368:
369: nbrac=1;
370: y=(GEN)gpmalloc((d+1)*sizeof(long));
371: if (gcmp0(constant_term(f))) y[nbrac++] = 0;
372: ss = icopy(gun); av1 = avma;
373: do
374: {
375: mael(x_minus_s,2,2) = ss[2];
376: /* one might do a FFT-type evaluation */
377: q = FpX_divres(f, x_minus_s, pp, &r);
378: if (signe(r)) avma = av1;
379: else
380: {
381: y[nbrac++] = ss[2]; f = q; av1 = avma;
382: }
383: ss[2]++;
384: }
385: while (nbrac<d && p>ss[2]);
386: if (nbrac == 1) { avma=av; return cgetg(1,t_COL); }
387: if (nbrac == d && p != ss[2])
388: {
389: g = mpinvmod((GEN)f[3], pp); setsigne(g,-1);
390: ss = modis(mulii(g, (GEN)f[2]), p);
391: y[nbrac++]=ss[2];
392: }
393: avma=av; g=cgetg(nbrac,t_COL);
394: if (isonstack(pp)) pp = icopy(pp);
395: for (i=1; i<nbrac; i++) g[i]=(long)mods(y[i],pp);
396: free(y); return g;
397: }
398:
1.2 ! noro 399: /* assume x reduced mod p, monic, squarefree. Return one root, or NULL if
! 400: * irreducible */
! 401: static GEN
! 402: quadsolvemod(GEN x, GEN p, int unknown)
! 403: {
! 404: GEN b = (GEN)x[3], c = (GEN)x[2];
! 405: GEN s,u,D;
! 406:
! 407: if (egalii(p, gdeux))
! 408: {
! 409: if (signe(c)) return NULL;
! 410: return gun;
! 411: }
! 412: D = subii(sqri(b), shifti(c,2));
! 413: D = resii(D,p);
! 414: if (unknown && kronecker(D,p) == -1) return NULL;
! 415:
! 416: s = mpsqrtmod(D,p);
! 417: if (!s) err(talker,"not a prime in quadsolvemod");
! 418: u = addis(shifti(p,-1), 1); /* = 1/2 */
! 419: return modii(mulii(u, subii(s,b)), p);
! 420: }
! 421:
! 422: static GEN
! 423: otherroot(GEN x, GEN r, GEN p)
! 424: {
! 425: GEN s = addii((GEN)x[3], r);
! 426: s = subii(p, s); if (signe(s) < 0) s = addii(s,p);
! 427: return s;
! 428: }
! 429:
1.1 noro 430: /* by splitting */
431: GEN
432: rootmod(GEN f, GEN p)
433: {
1.2 ! noro 434: long n, i, j, la, lb;
! 435: gpmem_t av = avma, tetpil;
1.1 noro 436: GEN y,pol,a,b,q,pol0;
437:
438: if (!factmod_init(&f, p, &i)) { avma=av; return cgetg(1,t_COL); }
1.2 ! noro 439: i = modBIL(p);
1.1 noro 440: if ((i & 1) == 0) { avma = av; return root_mod_even(f,i); }
441: i=2; while (!signe(f[i])) i++;
442: if (i == 2) j = 1;
443: else
444: {
445: j = lgef(f) - (i-2);
446: if (j==3) /* f = x^n */
447: {
448: avma = av; y = cgetg(2,t_COL);
449: y[1] = (long)gmodulsg(0,p);
450: return y;
451: }
452: a = cgetg(j, t_POL); /* a = f / x^{v_x(f)} */
453: a[1] = evalsigne(1) | evalvarn(varn(f)) | evallgef(j);
454: f += i-2; for (i=2; i<j; i++) a[i]=f[i];
455: j = 2; f = a;
456: }
457: q = shifti(p,-1);
458: /* take gcd(x^(p-1) - 1, f) by splitting (x^q-1) * (x^q+1) */
459: b = FpXQ_pow(polx[varn(f)],q, f,p);
460: if (lgef(b)<3) err(talker,"not a prime in rootmod");
461: b = ZX_s_add(b,-1); /* b = x^((p-1)/2) - 1 mod f */
462: a = FpX_gcd(f,b, p);
463: b = ZX_s_add(b, 2); /* b = x^((p-1)/2) + 1 mod f */
464: b = FpX_gcd(f,b, p);
465: la = degpol(a);
466: lb = degpol(b); n = la + lb;
467: if (!n)
468: {
469: avma = av; y = cgetg(n+j,t_COL);
470: if (j>1) y[1] = (long)gmodulsg(0,p);
471: return y;
472: }
473: y = cgetg(n+j,t_COL);
474: if (j>1) { y[1] = zero; n++; }
475: y[j] = (long)FpX_normalize(b,p);
476: if (la) y[j+lb] = (long)FpX_normalize(a,p);
477: pol = gadd(polx[varn(f)], gun); pol0 = constant_term(pol);
478: while (j<=n)
1.2 ! noro 479: { /* cf FpX_split_berlekamp */
! 480: a = (GEN)y[j]; la = degpol(a);
1.1 noro 481: if (la==1)
482: y[j++] = lsubii(p, constant_term(a));
483: else if (la==2)
484: {
1.2 ! noro 485: GEN r = quadsolvemod(a, p, 0);
! 486: y[j++] = (long)r;
! 487: y[j++] = (long)otherroot(a,r, p);
1.1 noro 488: }
489: else for (pol0[2]=1; ; pol0[2]++)
490: {
491: b = ZX_s_add(FpXQ_pow(pol,q, a,p), -1); /* pol^(p-1)/2 - 1 */
492: b = FpX_gcd(a,b, p); lb = degpol(b);
1.2 ! noro 493: if (lb && lb < la)
1.1 noro 494: {
495: b = FpX_normalize(b, p);
496: y[j+lb] = (long)FpX_div(a,b, p);
497: y[j] = (long)b; break;
498: }
1.2 ! noro 499: if (pol0[2] == 100 && !BSW_psp(p))
! 500: err(talker, "not a prime in polrootsmod");
1.1 noro 501: }
502: }
503: tetpil = avma; y = gerepile(av,tetpil,sort(y));
504: if (isonstack(p)) p = icopy(p);
505: for (i=1; i<=n; i++) y[i] = (long)mod((GEN)y[i], p);
506: return y;
507: }
508:
509: GEN
510: rootmod0(GEN f, GEN p, long flag)
511: {
512: switch(flag)
513: {
514: case 0: return rootmod(f,p);
515: case 1: return rootmod2(f,p);
516: default: err(flagerr,"polrootsmod");
517: }
518: return NULL; /* not reached */
519: }
520:
521: /*******************************************************************/
522: /* */
523: /* FACTORISATION MODULO p */
524: /* */
525: /*******************************************************************/
1.2 ! noro 526: #define FqX_div(x,y,T,p) FpXQX_divres((x),(y),(T),(p),NULL)
! 527: #define FqX_rem(x,y,T,p) FpXQX_divres((x),(y),(T),(p),ONLY_REM)
! 528: #define FqX_red FpXQX_red
! 529: #define FqX_sqr FpXQX_sqr
1.1 noro 530: static GEN spec_FpXQ_pow(GEN x, GEN p, GEN S);
1.2 ! noro 531: extern GEN pol_to_vec(GEN x, long N);
! 532: extern GEN FqXQ_pow(GEN x, GEN n, GEN S, GEN T, GEN p);
! 533: extern GEN FpXQX_from_Kronecker(GEN z, GEN pol, GEN p);
! 534: extern GEN FpXQX_safegcd(GEN P, GEN Q, GEN T, GEN p);
! 535: extern GEN u_normalizepol(GEN x, long lx);
! 536: extern GEN Fq_pow(GEN x, GEN n, GEN pol, GEN p);
1.1 noro 537: /* Functions giving information on the factorisation. */
538:
539: /* u in Z[X], return kernel of (Frob - Id) over Fp[X] / u */
540: static GEN
1.2 ! noro 541: FpM_Berlekamp_ker(GEN u, GEN p)
1.1 noro 542: {
1.2 ! noro 543: long j,N = degpol(u);
! 544: GEN vker,v,w,Q,p1;
! 545: if (DEBUGLEVEL > 7) (void)timer2();
1.1 noro 546: Q = cgetg(N+1,t_MAT); Q[1] = (long)zerocol(N);
547: w = v = FpXQ_pow(polx[varn(u)],p,u,p);
548: for (j=2; j<=N; j++)
549: {
1.2 ! noro 550: p1 = pol_to_vec(w, N);
1.1 noro 551: p1[j] = laddis((GEN)p1[j], -1);
1.2 ! noro 552: Q[j] = (long)p1;
1.1 noro 553: if (j < N)
554: {
1.2 ! noro 555: gpmem_t av = avma;
1.1 noro 556: w = gerepileupto(av, FpX_res(gmul(w,v), u, p));
557: }
558: }
559: if (DEBUGLEVEL > 7) msgtimer("frobenius");
560: vker = FpM_ker(Q,p);
561: if (DEBUGLEVEL > 7) msgtimer("kernel");
562: return vker;
563: }
564:
1.2 ! noro 565: static GEN
! 566: FqM_Berlekamp_ker(GEN u, GEN T, GEN q, GEN p)
! 567: {
! 568: long j,N = degpol(u);
! 569: GEN vker,v,w,Q,p1;
! 570: if (DEBUGLEVEL > 7) (void)timer2();
! 571: Q = cgetg(N+1,t_MAT); Q[1] = (long)zerocol(N);
! 572: w = v = FqXQ_pow(polx[varn(u)], q, u, T, p);
! 573: for (j=2; j<=N; j++)
! 574: {
! 575: p1 = pol_to_vec(w, N);
! 576: p1[j] = laddgs((GEN)p1[j], -1);
! 577: Q[j] = (long)p1;
! 578: if (j < N)
! 579: {
! 580: gpmem_t av = avma;
! 581: w = gerepileupto(av, FpXQX_divres(FpXQX_mul(w,v, T,p), u,T,p,ONLY_REM));
! 582: }
! 583: }
! 584: if (DEBUGLEVEL > 7) msgtimer("frobenius");
! 585: vker = FqM_ker(Q,T,p);
! 586: if (DEBUGLEVEL > 7) msgtimer("kernel");
! 587: return vker;
! 588: }
! 589:
1.1 noro 590: /* f in ZZ[X] and p a prime number. */
591: long
592: FpX_is_squarefree(GEN f, GEN p)
593: {
1.2 ! noro 594: gpmem_t av = avma;
1.1 noro 595: GEN z;
596: z = FpX_gcd(f,derivpol(f),p);
597: avma = av;
598: return lgef(z)==3;
599: }
600: /* idem
601: * leading term of f must be prime to p.
602: */
603: /* Compute the number of roots in Fp without counting multiplicity
604: * return -1 for 0 polynomial.
605: */
606: long
607: FpX_nbroots(GEN f, GEN p)
608: {
1.2 ! noro 609: long n=lgef(f);
! 610: gpmem_t av = avma;
1.1 noro 611: GEN z;
612: if (n <= 4) return n-3;
613: f = FpX_red(f, p);
614: z = FpXQ_pow(polx[varn(f)], p, f, p);
615: z = FpX_sub(z,polx[varn(f)],NULL);
616: z = FpX_gcd(z,f,p),
617: avma = av; return degpol(z);
618: }
619: long
620: FpX_is_totally_split(GEN f, GEN p)
621: {
1.2 ! noro 622: long n=degpol(f);
! 623: gpmem_t av = avma;
1.1 noro 624: GEN z;
1.2 ! noro 625: if (n <= 1) return 1;
! 626: if (!is_bigint(p) && n > p[2]) return 0;
1.1 noro 627: f = FpX_red(f, p);
628: z = FpXQ_pow(polx[varn(f)], p, f, p);
629: avma = av; return lgef(z)==4 && gcmp1((GEN)z[3]) && !signe(z[2]);
630: }
631: /* u in ZZ[X] and p a prime number.
632: * u must be squarefree mod p.
633: * leading term of u must be prime to p. */
634: long
635: FpX_nbfact(GEN u, GEN p)
636: {
1.2 ! noro 637: gpmem_t av = avma;
! 638: GEN vker = FpM_Berlekamp_ker(u,p);
1.1 noro 639: avma = av; return lg(vker)-1;
640: }
641:
642: /* Please use only use this function when you it is false, or that there is a
643: * lot of factors. If you believe f is irreducible or that it has few factors,
644: * then use `FpX_nbfact(f,p)==1' instead (faster).
645: */
646: static GEN factcantor0(GEN f, GEN pp, long flag);
647: long FpX_is_irred(GEN f, GEN p) { return !!factcantor0(f,p,2); }
648:
649: static GEN modulo;
650: static GEN gsmul(GEN a,GEN b){return FpX_mul(a,b,modulo);}
651: GEN
652: FpV_roots_to_pol(GEN V, GEN p, long v)
653: {
1.2 ! noro 654: gpmem_t ltop=avma;
1.1 noro 655: long i;
656: GEN g=cgetg(lg(V),t_VEC);
657: for(i=1;i<lg(V);i++)
1.2 ! noro 658: g[i]=(long)deg1pol(gun,modii(negi((GEN)V[i]),p),v);
1.1 noro 659: modulo=p;
660: g=divide_conquer_prod(g,&gsmul);
661: return gerepileupto(ltop,g);
662: }
663:
664: /************************************************************/
665: GEN
666: trivfact(void)
667: {
668: GEN y=cgetg(3,t_MAT);
669: y[1]=lgetg(1,t_COL);
670: y[2]=lgetg(1,t_COL); return y;
671: }
672:
673: static GEN
674: try_pow(GEN w0, GEN pol, GEN p, GEN q, long r)
675: {
676: GEN w2, w = FpXQ_pow(w0,q, pol,p);
677: long s;
678: if (gcmp1(w)) return w0;
679: for (s=1; s<r; s++,w=w2)
680: {
681: w2 = gsqr(w);
682: w2 = FpX_res(w2, pol, p);
683: if (gcmp1(w2)) break;
684: }
685: return gcmp_1(w)? NULL: w;
686: }
687:
688: /* INPUT:
689: * m integer (converted to polynomial w in Z[X] by stopoly)
690: * p prime; q = (p^d-1) / 2^r
691: * t[0] polynomial of degree k*d product of k irreducible factors of degree d
692: * t[0] is expected to be normalized (leading coeff = 1)
693: * OUTPUT:
694: * t[0],t[1]...t[k-1] the k factors, normalized
695: */
696: static void
697: split(long m, GEN *t, long d, GEN p, GEN q, long r, GEN S)
698: {
1.2 ! noro 699: long ps, l, v, dv;
! 700: gpmem_t av0, av;
1.1 noro 701: GEN w,w0;
702:
703: dv=degpol(*t); if (dv==d) return;
704: v=varn(*t); av0=avma; ps = p[2];
705: for(av=avma;;avma=av)
706: {
707: if (ps==2)
708: {
1.2 ! noro 709: w0 = w = FpXQ_pow(polx[v], stoi(m-1), *t, gdeux); m += 2;
1.1 noro 710: for (l=1; l<d; l++)
711: w = gadd(w0, spec_FpXQ_pow(w, p, S));
712: }
713: else
714: {
715: w = FpX_res(stopoly(m,ps,v),*t, p);
716: m++; w = try_pow(w,*t,p,q,r);
717: if (!w) continue;
718: w = ZX_s_add(w, -1);
719: }
720: w = FpX_gcd(*t,w, p);
721: l = degpol(w); if (l && l!=dv) break;
722: }
723: w = FpX_normalize(w, p);
724: w = gerepileupto(av0, w);
725: l /= d; t[l]=FpX_div(*t,w,p); *t=w;
726: split(m,t+l,d,p,q,r,S);
727: split(m,t, d,p,q,r,S);
728: }
729:
730: static void
731: splitgen(GEN m, GEN *t, long d, GEN p, GEN q, long r)
732: {
1.2 ! noro 733: long l, v, dv;
! 734: gpmem_t av;
1.1 noro 735: GEN w;
736:
737: dv=degpol(*t); if (dv==d) return;
738: v=varn(*t); m=setloop(m); m=incpos(m);
739: av=avma;
740: for(;; avma=av, m=incpos(m))
741: {
742: w = FpX_res(stopoly_gen(m,p,v),*t, p);
743: w = try_pow(w,*t,p,q,r);
744: if (!w) continue;
745: w = ZX_s_add(w,-1);
746: w = FpX_gcd(*t,w, p); l=degpol(w);
747: if (l && l!=dv) break;
748:
749: }
750: w = FpX_normalize(w, p);
751: w = gerepileupto(av, w);
752: l /= d; t[l]=FpX_div(*t,w,p); *t=w;
753: splitgen(m,t+l,d,p,q,r);
754: splitgen(m,t, d,p,q,r);
755: }
756:
757: /* return S = [ x^p, x^2p, ... x^(n-1)p ] mod (p, T), n = degree(T) > 0 */
758: static GEN
759: init_pow_p_mod_pT(GEN p, GEN T)
760: {
761: long i, n = degpol(T), v = varn(T);
762: GEN p1, S = cgetg(n, t_VEC);
763: if (n == 1) return S;
764: S[1] = (long)FpXQ_pow(polx[v], p, T, p);
765: /* use as many squarings as possible */
766: for (i=2; i < n; i+=2)
1.2 ! noro 767: {
1.1 noro 768: p1 = gsqr((GEN)S[i>>1]);
769: S[i] = (long)FpX_res(p1, T, p);
770: if (i == n-1) break;
771: p1 = gmul((GEN)S[i], (GEN)S[1]);
772: S[i+1] = (long)FpX_res(p1, T, p);
1.2 ! noro 773: }
1.1 noro 774: return S;
1.2 ! noro 775: }
1.1 noro 776:
777: /* compute x^p, S is as above */
778: static GEN
779: spec_FpXQ_pow(GEN x, GEN p, GEN S)
780: {
1.2 ! noro 781: long i, dx = degpol(x);
! 782: gpmem_t av = avma, lim = stack_lim(av, 1);
1.1 noro 783: GEN x0 = x+2, z;
784: z = (GEN)x0[0];
785: if (dx < 0) err(talker, "zero polynomial in FpXQ_pow. %Z not prime", p);
786: for (i = 1; i <= dx; i++)
787: {
788: GEN d, c = (GEN)x0[i]; /* assume coeffs in [0, p-1] */
789: if (!signe(c)) continue;
790: d = (GEN)S[i]; if (!gcmp1(c)) d = gmul(c,d);
791: z = gadd(z, d);
792: if (low_stack(lim, stack_lim(av,1)))
793: {
794: if(DEBUGMEM>1) err(warnmem,"spec_FpXQ_pow");
795: z = gerepileupto(av, z);
796: }
797: }
798: z = FpX_red(z, p);
799: return gerepileupto(av, z);
800: }
801:
802: /* factor f mod pp.
803: * If (flag = 1) return the degrees, not the factors
804: * If (flag = 2) return NULL if f is not irreducible
805: */
806: static GEN
807: factcantor0(GEN f, GEN pp, long flag)
808: {
1.2 ! noro 809: long i, j, k, d, e, vf, p, nbfact;
! 810: gpmem_t tetpil, av = avma;
1.1 noro 811: GEN ex,y,f2,g,g1,u,v,pd,q;
812: GEN *t;
813:
814: if (!(d = factmod_init(&f, pp, &p))) { avma=av; return trivfact(); }
815: /* to hold factors and exponents */
816: t = (GEN*)cgetg(d+1,t_VEC); ex = new_chunk(d+1);
817: vf=varn(f); e = nbfact = 1;
818: for(;;)
819: {
820: f2 = FpX_gcd(f,derivpol(f), pp);
821: if (flag > 1 && lgef(f2) > 3) return NULL;
822: g1 = FpX_div(f,f2,pp);
823: k = 0;
824: while (lgef(g1)>3)
825: {
826: long du,dg;
827: GEN S;
828: k++; if (p && !(k%p)) { k++; f2 = FpX_div(f2,g1,pp); }
829: u = g1; g1 = FpX_gcd(f2,g1, pp);
830: if (lgef(g1)>3)
831: {
832: u = FpX_div( u,g1,pp);
833: f2= FpX_div(f2,g1,pp);
834: }
835: du = degpol(u);
836: if (du <= 0) continue;
837:
838: /* here u is square-free (product of irred. of multiplicity e * k) */
839: S = init_pow_p_mod_pT(pp, u);
840: pd=gun; v=polx[vf];
841: for (d=1; d <= du>>1; d++)
842: {
843: if (!flag) pd = mulii(pd,pp);
844: v = spec_FpXQ_pow(v, pp, S);
845: g = FpX_gcd(gadd(v, gneg(polx[vf])), u, pp);
846: dg = degpol(g);
847: if (dg <= 0) continue;
848:
849: /* Ici g est produit de pol irred ayant tous le meme degre d; */
850: j=nbfact+dg/d;
851:
852: if (flag)
853: {
854: if (flag > 1) return NULL;
855: for ( ; nbfact<j; nbfact++) { t[nbfact]=(GEN)d; ex[nbfact]=e*k; }
856: }
857: else
858: {
859: long r;
860: g = FpX_normalize(g, pp);
861: t[nbfact]=g; q = subis(pd,1); /* also ok for p=2: unused */
862: r = vali(q); q = shifti(q,-r);
863: /* le premier parametre est un entier variable m qui sera
864: * converti en un polynome w dont les coeff sont ses digits en
865: * base p (initialement m = p --> X) pour faire pgcd de g avec
866: * w^(p^d-1)/2 jusqu'a casser. p = 2 is treated separately.
867: */
868: if (p)
869: split(p,t+nbfact,d,pp,q,r,S);
870: else
871: splitgen(pp,t+nbfact,d,pp,q,r);
872: for (; nbfact<j; nbfact++) ex[nbfact]=e*k;
873: }
874: du -= dg;
875: u = FpX_div(u,g,pp);
876: v = FpX_res(v,u,pp);
877: }
878: if (du)
879: {
880: t[nbfact] = flag? (GEN)du: FpX_normalize(u, pp);
881: ex[nbfact++]=e*k;
882: }
883: }
884: j = lgef(f2); if (j==3) break;
885:
886: e*=p; j=(j-3)/p+3; setlg(f,j); setlgef(f,j);
887: for (i=2; i<j; i++) f[i]=f2[p*(i-2)+2];
888: }
889: if (flag > 1) { avma = av; return gun; } /* irreducible */
890: tetpil=avma; y=cgetg(3,t_MAT);
891: if (!flag)
892: {
893: y[1]=(long)t; setlg(t, nbfact);
894: y[2]=(long)ex; (void)sort_factor(y,cmpii);
895: }
896: u=cgetg(nbfact,t_COL); y[1]=(long)u;
897: v=cgetg(nbfact,t_COL); y[2]=(long)v;
898: if (flag)
899: for (j=1; j<nbfact; j++)
900: {
901: u[j] = lstoi((long)t[j]);
902: v[j] = lstoi(ex[j]);
903: }
904: else
905: for (j=1; j<nbfact; j++)
906: {
907: u[j] = (long)FpX(t[j], pp);
908: v[j] = lstoi(ex[j]);
909: }
910: return gerepile(av,tetpil,y);
911: }
912:
913: GEN
914: factcantor(GEN f, GEN p)
915: {
916: return factcantor0(f,p,0);
917: }
918:
919: GEN
920: simplefactmod(GEN f, GEN p)
921: {
922: return factcantor0(f,p,1);
923: }
924:
925: GEN
1.2 ! noro 926: col_to_ff(GEN x, long v)
! 927: {
! 928: long i, k = lg(x);
! 929: GEN p;
! 930:
! 931: while (--k && gcmp0((GEN)x[k]));
! 932: if (k <= 1) return k? (GEN)x[1]: gzero;
! 933: i = k+2; p = cgetg(i,t_POL);
! 934: p[1] = evalsigne(1) | evallgef(i) | evalvarn(v);
! 935: x--; for (k=2; k<i; k++) p[k] = x[k];
! 936: return p;
! 937: }
! 938:
! 939: GEN
! 940: vec_to_pol(GEN x, long v)
! 941: {
! 942: long i, k = lg(x);
! 943: GEN p;
! 944:
! 945: while (--k && gcmp0((GEN)x[k]));
! 946: if (!k) return zeropol(v);
! 947: i = k+2; p = cgetg(i,t_POL);
! 948: p[1] = evalsigne(1) | evallgef(i) | evalvarn(v);
! 949: x--; for (k=2; k<i; k++) p[k] = x[k];
! 950: return p;
! 951: }
! 952:
! 953: GEN
! 954: u_vec_to_pol(GEN x)
! 955: {
! 956: long i, k = lg(x);
! 957: GEN p;
! 958:
! 959: while (--k && !x[k]);
! 960: if (!k) return u_zeropol();
! 961: i = k+2; p = cgetg(i,t_POL);
! 962: p[1] = evalsigne(1) | evallgef(i) | evalvarn(0);
! 963: x--; for (k=2; k<i; k++) p[k] = x[k];
! 964: return p;
! 965: }
! 966:
! 967: #if 0
! 968: static GEN
! 969: u_FpM_FpV_mul(GEN x, GEN y, ulong p)
1.1 noro 970: {
1.2 ! noro 971: long i,k,l,lx=lg(x), ly=lg(y);
! 972: GEN z;
! 973: if (lx != ly) err(operi,"* [mod p]",x,y);
! 974: if (lx==1) return cgetg(1,t_VECSMALL);
! 975: l = lg(x[1]);
! 976: z = cgetg(l,t_VECSMALL);
! 977: for (i=1; i<l; i++)
! 978: {
! 979: ulong p1 = 0;
! 980: for (k=1; k<lx; k++)
! 981: {
! 982: p1 += coeff(x,i,k) * y[k];
! 983: if (p1 & HIGHBIT) p1 %= p;
! 984: }
! 985: z[i] = p1 % p;
! 986: }
! 987: return z;
! 988: }
! 989: #endif
1.1 noro 990:
1.2 ! noro 991: /* u_vec_to_pol(u_FpM_FpV_mul(x, u_pol_to_vec(y), p)) */
! 992: GEN
! 993: u_FpM_FpX_mul(GEN x, GEN y, ulong p)
! 994: {
! 995: long i,k,l, ly=lgef(y)-1;
! 996: GEN z;
! 997: if (ly==1) return u_zeropol();
! 998: l = lg(x[1]);
! 999: y++;
! 1000: z = vecsmall_const(l,0) + 1;
! 1001: for (k=1; k<ly; k++)
1.1 noro 1002: {
1.2 ! noro 1003: GEN c;
! 1004: if (!y[k]) continue;
! 1005: c = (GEN)x[k];
! 1006: if (y[k] == 1)
! 1007: for (i=1; i<l; i++)
! 1008: {
! 1009: z[i] += c[i];
! 1010: if (z[i] & HIGHBIT) z[i] %= p;
! 1011: }
! 1012: else
! 1013: for (i=1; i<l; i++)
! 1014: {
! 1015: z[i] += c[i] * y[k];
! 1016: if (z[i] & HIGHBIT) z[i] %= p;
! 1017: }
! 1018: }
! 1019: for (i=1; i<l; i++) z[i] %= p;
! 1020: while (--l && !z[l]);
! 1021: if (!l) return u_zeropol();
! 1022: *z-- = evalsigne(1) | evallgef(l+2) | evalvarn(0);
! 1023: return z;
! 1024: }
1.1 noro 1025:
1.2 ! noro 1026: /* return the (N-dimensional) vector of coeffs of p */
! 1027: GEN
! 1028: pol_to_vec(GEN x, long N)
! 1029: {
! 1030: long i, l;
! 1031: GEN z = cgetg(N+1,t_COL);
! 1032: if (typ(x) != t_POL)
! 1033: {
! 1034: z[1] = (long)x;
! 1035: for (i=2; i<=N; i++) z[i]=zero;
! 1036: return z;
1.1 noro 1037: }
1.2 ! noro 1038: l = lgef(x)-1; x++;
! 1039: for (i=1; i<l ; i++) z[i]=x[i];
! 1040: for ( ; i<=N; i++) z[i]=zero;
! 1041: return z;
! 1042: }
! 1043:
! 1044: /* return the (N-dimensional) vector of coeffs of p */
! 1045: GEN
! 1046: u_pol_to_vec(GEN x, long N)
! 1047: {
! 1048: long i, l;
! 1049: GEN z = cgetg(N+1,t_VECSMALL);
! 1050: if (typ(x) != t_VECSMALL) err(typeer,"u_pol_to_vec");
! 1051: l = lgef(x)-1; x++;
! 1052: for (i=1; i<l ; i++) z[i]=x[i];
! 1053: for ( ; i<=N; i++) z[i]=0;
! 1054: return z;
! 1055: }
! 1056:
! 1057: /* vector of polynomials (in v) whose coeffs are given by the columns of x */
! 1058: GEN
! 1059: mat_to_vecpol(GEN x, long v)
! 1060: {
! 1061: long j, lx = lg(x);
! 1062: GEN y = cgetg(lx, t_VEC);
! 1063: for (j=1; j<lx; j++) y[j] = (long)vec_to_pol((GEN)x[j], v);
1.1 noro 1064: return y;
1065: }
1066:
1.2 ! noro 1067: /* matrix whose entries are given by the coeffs of the polynomials in
1.1 noro 1068: * vector v (considered as degree n-1 polynomials) */
1069: GEN
1070: vecpol_to_mat(GEN v, long n)
1071: {
1.2 ! noro 1072: long j, N = lg(v);
! 1073: GEN y = cgetg(N, t_MAT);
1.1 noro 1074: if (typ(v) != t_VEC) err(typeer,"vecpol_to_mat");
1.2 ! noro 1075: for (j=1; j<N; j++) y[j] = (long)pol_to_vec((GEN)v[j], n);
1.1 noro 1076: return y;
1077: }
1.2 ! noro 1078:
1.1 noro 1079: /* polynomial (in v) of polynomials (in w) whose coeffs are given by the columns of x */
1080: GEN
1081: mat_to_polpol(GEN x, long v,long w)
1082: {
1.2 ! noro 1083: long j, lx = lg(x);
1.1 noro 1084: GEN y = cgetg(lx+1, t_POL);
1085: y[1]=evalsigne(1) | evallgef(lx+1) | evalvarn(v);
1086: y++;
1.2 ! noro 1087: for (j=1; j<lx; j++) y[j] = (long)vec_to_pol((GEN)x[j], w);
! 1088: return normalizepol_i(--y, lx+1);
1.1 noro 1089: }
1090:
1091: /* matrix whose entries are given by the coeffs of the polynomial v in
1092: * two variables (considered as degree n polynomials) */
1093: GEN
1094: polpol_to_mat(GEN v, long n)
1095: {
1.2 ! noro 1096: long j, N = lgef(v)-1;
! 1097: GEN y = cgetg(N, t_MAT);
1.1 noro 1098: if (typ(v) != t_POL) err(typeer,"polpol_to_mat");
1.2 ! noro 1099: v++;
! 1100: for (j=1; j<N; j++) y[j] = (long)pol_to_vec((GEN)v[j], n);
! 1101: return y;
! 1102: }
! 1103:
! 1104: /* P(X,Y) --> P(Y,X), n-1 is the degree in Y */
! 1105: GEN
! 1106: swap_polpol(GEN x, long n, long w)
! 1107: {
! 1108: long j, lx = lgef(x), ly = n+3;
! 1109: long v=varn(x);
! 1110: GEN y = cgetg(ly, t_POL);
! 1111: y[1]=evalsigne(1) | evallgef(ly) | evalvarn(v);
! 1112: for (j=2; j<ly; j++)
1.1 noro 1113: {
1.2 ! noro 1114: long k;
! 1115: GEN p1=cgetg(lx,t_POL);
! 1116: p1[1] = evalsigne(1) | evallgef(lx) | evalvarn(w);
! 1117: for (k=2; k<lx; k++)
! 1118: if( j<lgef(x[k]))
! 1119: p1[k] = mael(x,k,j);
! 1120: else
! 1121: p1[k] = zero;
! 1122: y[j] = (long)normalizepol_i(p1,lx);
1.1 noro 1123: }
1.2 ! noro 1124: return normalizepol_i(y,ly);
1.1 noro 1125: }
1126:
1127: /* set x <-- x + c*y mod p */
1128: static void
1.2 ! noro 1129: u_FpX_addmul(GEN x, GEN y, long c, long p)
1.1 noro 1130: {
1131: long i,lx,ly,l;
1132: if (!c) return;
1.2 ! noro 1133: lx = lgef(x);
! 1134: ly = lgef(y); l = min(lx,ly);
1.1 noro 1135: if (p & ~MAXHALFULONG)
1136: {
1.2 ! noro 1137: for (i=2; i<l; i++) x[i] = ((ulong)x[i]+ (ulong)mulssmod(c,y[i],p)) % p;
! 1138: if (l == lx)
! 1139: for ( ; i<ly; i++) x[i] = mulssmod(c,y[i],p);
1.1 noro 1140: }
1141: else
1142: {
1.2 ! noro 1143: for (i=2; i<l; i++) x[i] = ((ulong)x[i] + (ulong)(c*y[i])) % p;
! 1144: if (l == lx)
! 1145: for ( ; i<ly; i++) x[i] = (c*y[i]) % p;
1.1 noro 1146: }
1.2 ! noro 1147: (void)u_normalizepol(x,i);
! 1148: }
! 1149:
! 1150: static long
! 1151: small_rand(long p)
! 1152: {
! 1153: return (p==2)? ((mymyrand() & 0x1000) == 0): mymyrand() % p;
! 1154: }
! 1155:
! 1156: GEN
! 1157: FpX_rand(long d1, long v, GEN p)
! 1158: {
! 1159: long i, d = d1+2;
! 1160: GEN y;
! 1161: y = cgetg(d,t_POL); y[1] = evalsigne(1) | evalvarn(v);
! 1162: for (i=2; i<d; i++) y[i] = (long)genrand(p);
! 1163: (void)normalizepol_i(y,d); return y;
1.1 noro 1164: }
1165:
1.2 ! noro 1166: /* return a random polynomial in F_q[v], degree < d1 */
! 1167: GEN
! 1168: FqX_rand(long d1, long v, GEN T, GEN p)
! 1169: {
! 1170: long i, d = d1+2, k = degpol(T), w = varn(T);
! 1171: GEN y;
! 1172: y = cgetg(d,t_POL); y[1] = evalsigne(1) | evalvarn(v);
! 1173: for (i=2; i<d; i++) y[i] = (long)FpX_rand(k, w, p);
! 1174: (void)normalizepol_i(y,d); return y;
! 1175: }
! 1176:
! 1177: #define set_irred(i) { if ((i)>ir) swap(t[i],t[ir]); ir++;}
! 1178:
1.1 noro 1179: long
1.2 ! noro 1180: FpX_split_berlekamp(GEN *t, GEN p)
1.1 noro 1181: {
1.2 ! noro 1182: GEN u = *t, a,b,po2,vker,pol;
! 1183: long N = degpol(u), d, i, ir, L, la, lb, ps, vu = varn(u);
! 1184: gpmem_t av0 = avma;
! 1185:
! 1186: vker = FpM_Berlekamp_ker(u,p);
1.1 noro 1187: vker = mat_to_vecpol(vker,vu);
1188: d = lg(vker)-1;
1.2 ! noro 1189: ps = is_bigint(p)? 0: p[2];
! 1190: if (ps)
1.1 noro 1191: {
1.2 ! noro 1192: avma = av0; a = cgetg(d+1, t_VEC); /* hack: hidden gerepile */
! 1193: for (i=1; i<=d; i++) a[i] = (long)pol_to_small((GEN)vker[i]);
! 1194: vker = a;
1.1 noro 1195: }
1.2 ! noro 1196: po2 = shifti(p, -1); /* (p-1) / 2 */
1.1 noro 1197: pol = cgetg(N+3,t_POL);
1.2 ! noro 1198: ir = 0;
! 1199: /* t[i] irreducible for i <= ir, still to be treated for i < L */
! 1200: for (L=1; L<d; )
1.1 noro 1201: {
1202: GEN polt;
1.2 ! noro 1203: if (ps)
1.1 noro 1204: {
1.2 ! noro 1205: pol[2] = small_rand(ps); /* vker[1] = 1 */
! 1206: pol[1] = evallgef(pol[2]? 3: 2);
! 1207: for (i=2; i<=d; i++)
! 1208: u_FpX_addmul(pol,(GEN)vker[i],small_rand(ps), ps);
1.1 noro 1209: polt = small_to_pol(pol,vu);
1210: }
1211: else
1212: {
1.2 ! noro 1213: pol[2] = (long)genrand(p);
1.1 noro 1214: pol[1] = evallgef(signe(pol[2])? 3: 2) | evalvarn(vu);
1215: for (i=2; i<=d; i++)
1.2 ! noro 1216: pol = gadd(pol, gmul((GEN)vker[i], genrand(p)));
! 1217: polt = FpX_red(pol,p);
! 1218: }
! 1219: for (i=ir; i<L && L<d; i++)
! 1220: {
! 1221: a = t[i]; la = degpol(a);
! 1222: if (la == 1) { set_irred(i); }
! 1223: else if (la == 2)
! 1224: {
! 1225: GEN r = quadsolvemod(a,p,1);
! 1226: if (r)
! 1227: {
! 1228: t[i] = deg1pol_i(gun, subii(p,r), vu); r = otherroot(a,r,p);
! 1229: t[L] = deg1pol_i(gun, subii(p,r), vu); L++;
! 1230: }
! 1231: set_irred(i);
! 1232: }
! 1233: else
! 1234: {
! 1235: gpmem_t av = avma;
! 1236: b = FpX_res(polt, a, p);
! 1237: if (degpol(b) == 0) { avma=av; continue; }
! 1238: b = ZX_s_add(FpXQ_pow(b,po2, a,p), -1);
! 1239: b = FpX_gcd(a,b, p); lb = degpol(b);
! 1240: if (lb && lb < la)
! 1241: {
! 1242: b = FpX_normalize(b, p);
! 1243: t[L] = FpX_div(a,b,p);
! 1244: t[i]= b; L++;
! 1245: }
! 1246: else avma = av;
! 1247: }
1.1 noro 1248: }
1.2 ! noro 1249: }
! 1250: return d;
! 1251: }
! 1252:
! 1253: static GEN
! 1254: FqX_deriv(GEN f, GEN T, GEN p)
! 1255: {
! 1256: return FqX_red(derivpol(f), T, p);
! 1257: }
! 1258: GEN
! 1259: FqX_gcd(GEN P, GEN Q, GEN T, GEN p)
! 1260: {
! 1261: GEN g = T? FpXQX_safegcd(P,Q,T,p): FpX_gcd(P,Q,p);
! 1262: if (!g) err(talker,"factmod9: %Z is reducible mod p!", T);
! 1263: return g;
! 1264: }
! 1265: long
! 1266: FqX_is_squarefree(GEN P, GEN T, GEN p)
! 1267: {
! 1268: gpmem_t av = avma;
! 1269: GEN z = FqX_gcd(P, derivpol(P), T, p);
! 1270: avma = av;
! 1271: return degpol(z)==0;
! 1272:
! 1273: }
! 1274:
! 1275: long
! 1276: FqX_split_berlekamp(GEN *t, GEN q, GEN T, GEN p)
! 1277: {
! 1278: GEN u = *t, a,b,qo2,vker,pol;
! 1279: long N = degpol(u), vu = varn(u), vT = varn(T), dT = degpol(T);
! 1280: long d, i, ir, L, la, lb;
! 1281:
! 1282: vker = FqM_Berlekamp_ker(u,T,q,p);
! 1283: vker = mat_to_vecpol(vker,vu);
! 1284: d = lg(vker)-1;
! 1285: qo2 = shifti(q, -1); /* (q-1) / 2 */
! 1286: pol = cgetg(N+3,t_POL);
! 1287: ir = 0;
! 1288: /* t[i] irreducible for i < ir, still to be treated for i < L */
! 1289: for (L=1; L<d; )
! 1290: {
! 1291: GEN polt;
! 1292: pol[2] = (long)FpX_rand(dT,vT,p);
! 1293: pol[1] = evallgef(signe(pol[2])? 3: 2) | evalvarn(vu);
! 1294: for (i=2; i<=d; i++)
! 1295: pol = gadd(pol, gmul((GEN)vker[i], FpX_rand(dT,vT,p)));
! 1296: polt = FqX_red(pol,T,p);
! 1297: for (i=ir; i<L && L<d; i++)
1.1 noro 1298: {
1.2 ! noro 1299: a = t[i]; la = degpol(a);
! 1300: if (la == 1) { set_irred(i); }
! 1301: else
1.1 noro 1302: {
1.2 ! noro 1303: gpmem_t av = avma;
! 1304: b = FqX_rem(polt, a, T,p);
! 1305: if (!degpol(b)) { avma=av; continue; }
! 1306: b = FqXQ_pow(b,qo2, a,T,p);
! 1307: if (!degpol(b)) { avma=av; continue; }
! 1308: b[2] = ladd((GEN)b[2], gun);
! 1309: b = FqX_gcd(a,b, T,p); lb = degpol(b);
! 1310: if (lb && lb < la)
1.1 noro 1311: {
1.2 ! noro 1312: b = FpXQX_normalize(b, T,p);
! 1313: t[L] = FqX_div(a,b,T,p);
! 1314: t[i]= b; L++;
1.1 noro 1315: }
1316: else avma = av;
1317: }
1318: }
1319: }
1320: return d;
1321: }
1322:
1323: GEN
1324: factmod0(GEN f, GEN pp)
1325: {
1.2 ! noro 1326: long i, j, k, e, p, N, nbfact, d;
! 1327: gpmem_t av = avma, tetpil;
1.1 noro 1328: GEN pps2,ex,y,f2,p1,g1,u, *t;
1329:
1330: if (!(d = factmod_init(&f, pp, &p))) { avma=av; return trivfact(); }
1331: /* to hold factors and exponents */
1332: t = (GEN*)cgetg(d+1,t_VEC); ex = cgetg(d+1,t_VECSMALL);
1333: e = nbfact = 1;
1334: pps2 = shifti(pp,-1);
1335:
1336: for(;;)
1337: {
1338: f2 = FpX_gcd(f,derivpol(f), pp);
1339: g1 = lgef(f2)==3? f: FpX_div(f,f2,pp);
1340: k = 0;
1341: while (lgef(g1)>3)
1342: {
1343: k++; if (p && !(k%p)) { k++; f2 = FpX_div(f2,g1,pp); }
1344: p1 = FpX_gcd(f2,g1, pp); u = g1; g1 = p1;
1.2 ! noro 1345: if (degpol(p1))
1.1 noro 1346: {
1347: u = FpX_div( u,p1,pp);
1348: f2= FpX_div(f2,p1,pp);
1349: }
1.2 ! noro 1350: /* u is square-free (product of irred. of multiplicity e * k) */
1.1 noro 1351: N = degpol(u);
1352: if (N)
1353: {
1354: t[nbfact] = FpX_normalize(u,pp);
1.2 ! noro 1355: d = (N==1)? 1: FpX_split_berlekamp(t+nbfact, pp);
1.1 noro 1356: for (j=0; j<d; j++) ex[nbfact+j] = e*k;
1357: nbfact += d;
1358: }
1359: }
1360: if (!p) break;
1361: j=(degpol(f2))/p+3; if (j==3) break;
1362:
1363: e*=p; setlg(f,j); setlgef(f,j);
1364: for (i=2; i<j; i++) f[i] = f2[p*(i-2)+2];
1365: }
1366: tetpil=avma; y=cgetg(3,t_VEC);
1367: setlg((GEN)t, nbfact);
1368: setlg(ex, nbfact);
1369: y[1]=lcopy((GEN)t);
1370: y[2]=lcopy(ex);
1371: (void)sort_factor(y,cmpii);
1372: return gerepile(av,tetpil,y);
1373: }
1374: GEN
1375: factmod(GEN f, GEN pp)
1376: {
1.2 ! noro 1377: gpmem_t tetpil, av=avma;
1.1 noro 1378: long nbfact;
1379: long j;
1380: GEN y,u,v;
1381: GEN z=factmod0(f,pp),t=(GEN)z[1],ex=(GEN)z[2];
1382: nbfact=lg(t);
1383: tetpil=avma; y=cgetg(3,t_MAT);
1384: u=cgetg(nbfact,t_COL); y[1]=(long)u;
1385: v=cgetg(nbfact,t_COL); y[2]=(long)v;
1386: for (j=1; j<nbfact; j++)
1387: {
1388: u[j] = (long)FpX((GEN)t[j], pp);
1389: v[j] = lstoi(ex[j]);
1390: }
1391: return gerepile(av,tetpil,y);
1392: }
1393: GEN
1394: factormod0(GEN f, GEN p, long flag)
1395: {
1396: switch(flag)
1397: {
1398: case 0: return factmod(f,p);
1399: case 1: return simplefactmod(f,p);
1400: default: err(flagerr,"factormod");
1401: }
1402: return NULL; /* not reached */
1403: }
1404:
1405: /*******************************************************************/
1406: /* */
1407: /* Recherche de racines p-adiques */
1408: /* */
1409: /*******************************************************************/
1410: /* make f suitable for [root|factor]padic */
1411: static GEN
1412: padic_pol_to_int(GEN f)
1413: {
1414: long i, l = lgef(f);
1.2 ! noro 1415: GEN c = content(f);
! 1416: if (gcmp0(c)) /* O(p^n) can occur */
! 1417: {
! 1418: if (typ(c) != t_PADIC) err(typeer,"padic_pol_to_int");
! 1419: f = gdiv(f, gpowgs((GEN)c[2], valp(c)));
! 1420: }
! 1421: else
! 1422: f = gdiv(f,c);
1.1 noro 1423: for (i=2; i<l; i++)
1424: switch(typ(f[i]))
1425: {
1426: case t_INT: break;
1427: case t_PADIC: f[i] = ltrunc((GEN)f[i]); break;
1428: default: err(talker,"incorrect coeffs in padic_pol_to_int");
1429: }
1430: return f;
1431: }
1432:
1.2 ! noro 1433: /* return invlead * (x + O(pr)), x in Z or Z_p, pr = p^r. May return gzero */
1.1 noro 1434: static GEN
1435: int_to_padic(GEN x, GEN p, GEN pr, long r, GEN invlead)
1436: {
1437: GEN p1,y;
1.2 ! noro 1438: long v, sx;
! 1439: gpmem_t av = avma;
1.1 noro 1440:
1441: if (typ(x) == t_PADIC)
1442: {
1443: v = valp(x);
1444: if (r >= precp(x) + v) return invlead? gmul(x, invlead): gcopy(x);
1445: sx = !gcmp0(x);
1446: p1 = (GEN)x[4];
1447: }
1448: else
1449: {
1450: sx = signe(x);
1451: if (!sx) return gzero;
1452: v = pvaluation(x,p,&p1);
1453: }
1454: y = cgetg(5,t_PADIC);
1455: if (sx && v < r)
1456: {
1457: y[4] = lmodii(p1,pr); r -= v;
1458: }
1.2 ! noro 1459: else
1.1 noro 1460: {
1461: y[4] = zero; v = r; r = 0;
1462: }
1.2 ! noro 1463: y[3] = (long)pr;
1.1 noro 1464: y[2] = (long)p;
1465: y[1] = evalprecp(r)|evalvalp(v);
1466: return invlead? gerepileupto(av, gmul(invlead,y)): y;
1467: }
1468:
1.2 ! noro 1469: /* as above. always return a t_PADIC */
! 1470: static GEN
! 1471: strict_int_to_padic(GEN x, GEN p, GEN pr, long r, GEN invlead)
! 1472: {
! 1473: GEN y = int_to_padic(x, p, pr, r, invlead);
! 1474: if (y == gzero) y = ggrandocp(p,r);
! 1475: return y;
! 1476: }
! 1477:
1.1 noro 1478: /* return (x + O(p^r)) normalized (multiply by a unit such that leading coeff
1479: * is a power of p), x in Z[X] (or Z_p[X]) */
1480: static GEN
1481: pol_to_padic(GEN x, GEN pr, GEN p, long r)
1482: {
1483: long v = 0,i,lx = lgef(x);
1484: GEN z = cgetg(lx,t_POL), lead = leading_term(x);
1485:
1486: if (gcmp1(lead)) lead = NULL;
1487: else
1488: {
1.2 ! noro 1489: gpmem_t av = avma;
1.1 noro 1490: v = ggval(lead,p);
1491: if (v) lead = gdiv(lead, gpowgs(p,v));
1492: lead = int_to_padic(lead,p,pr,r,NULL);
1493: lead = gerepileupto(av, ginv(lead));
1494: }
1495: for (i=lx-1; i>1; i--)
1496: z[i] = (long)int_to_padic((GEN)x[i],p,pr,r,lead);
1497: z[1] = x[1]; return z;
1498: }
1499:
1500: static GEN
1501: padic_trivfact(GEN x, GEN p, long r)
1502: {
1.2 ! noro 1503: GEN y = cgetg(3,t_MAT);
! 1504: p = icopy(p);
! 1505: y[1]=(long)_col(pol_to_padic(x,gpowgs(p,r),p,r));
! 1506: y[2]=(long)_col(gun); return y;
1.1 noro 1507: }
1508:
1.2 ! noro 1509: /* Assume x reduced mod p. q = p^e (simplified version of int_to_padic).
! 1510: * If p = 2, is defined (and reduced) mod 4 [from rootmod] */
1.1 noro 1511: GEN
1.2 ! noro 1512: Fp_to_Zp(GEN x, GEN p, GEN q, long e)
! 1513: {
! 1514: GEN y = cgetg(5, t_PADIC);
! 1515: if (egalii(p, x)) /* implies p = x = 2 */
! 1516: {
! 1517: x = gun; q = shifti(q, -1);
! 1518: y[1] = evalprecp(e-1) | evalvalp(1);
! 1519: }
! 1520: else if (!signe(x)) y[1] = evalprecp(0) | evalvalp(e);
! 1521: else y[1] = evalprecp(e) | evalvalp(0);
! 1522: y[2] = (long)p;
! 1523: y[3] = (long)q;
! 1524: y[4] = (long)x; return y;
! 1525: }
! 1526:
! 1527: /* f != 0 in Z[X], primitive, a t_PADIC s.t f(a) = 0 mod p */
! 1528: static GEN
! 1529: apprgen_i(GEN f, GEN a)
1.1 noro 1530: {
1.2 ! noro 1531: GEN fp,u,p,q,P,res,a0,rac;
! 1532: long prec,i,j,k;
! 1533:
! 1534: prec = gcmp0(a)? valp(a): precp(a);
! 1535: if (prec <= 1) return _vec(a);
! 1536: fp = derivpol(f); u = ggcd(f,fp);
! 1537: if (degpol(u) > 0) { f = gdeuc(f,u); fp = derivpol(f); }
! 1538: p = (GEN)a[2];
! 1539: P = egalii(p,gdeux)? stoi(4): p;
! 1540: a0= gmod(a, P);
! 1541: #if 0 /* assumption */
! 1542: if (!gcmp0(FpX_eval(f,a0,P))) err(rootper2);
! 1543: #endif
! 1544: if (!gcmp0(FpX_eval(fp,a0,p))) /* simple zero */
! 1545: {
! 1546: res = rootpadiclift(f, a0, p, prec);
! 1547: res = strict_int_to_padic(res,p,gpowgs(p,prec),prec,NULL);
! 1548: return _vec(res);
! 1549: }
1.1 noro 1550:
1.2 ! noro 1551: f = poleval(f, gadd(a, gmul(P,polx[varn(f)])));
1.1 noro 1552: f = padic_pol_to_int(f);
1.2 ! noro 1553: f = gdiv(f, gpowgs(p,ggval(f, p)));
! 1554:
! 1555: res = cgetg(degpol(f)+1,t_VEC);
! 1556: q = gpowgs(p,prec);
! 1557: rac = lift_intern(rootmod(f, P));
! 1558: for (j=i=1; i<lg(rac); i++)
1.1 noro 1559: {
1.2 ! noro 1560: u = apprgen_i(f, Fp_to_Zp((GEN)rac[i], p,q,prec));
! 1561: for (k=1; k<lg(u); k++) res[j++] = ladd(a, gmul(P,(GEN)u[k]));
1.1 noro 1562: }
1.2 ! noro 1563: setlg(res,j); return res;
! 1564: }
! 1565:
! 1566: /* a t_PADIC, return vector of p-adic roots of f equal to a (mod p)
! 1567: * We assume 1) f(a) = 0 mod p (mod 4 if p=2).
! 1568: * 2) leading coeff prime to p. */
! 1569: GEN
! 1570: apprgen(GEN f, GEN a)
! 1571: {
! 1572: gpmem_t av = avma;
! 1573: if (typ(f) != t_POL) err(notpoler,"apprgen");
! 1574: if (gcmp0(f)) err(zeropoler,"apprgen");
! 1575: if (typ(a) != t_PADIC) err(rootper1);
! 1576: return gerepilecopy(av, apprgen_i(padic_pol_to_int(f), a));
! 1577: }
1.1 noro 1578:
1.2 ! noro 1579: static GEN
! 1580: rootpadic_i(GEN f, GEN p, long prec)
! 1581: {
! 1582: GEN fp,y,z,q,rac;
! 1583: long lx,i,j,k;
! 1584:
! 1585: fp = derivpol(f); z = ggcd(f,fp);
! 1586: if (degpol(z) > 0) { f = gdeuc(f,z); fp = derivpol(f); }
! 1587: rac = rootmod(f, (egalii(p,gdeux) && prec>=2)? stoi(4): p);
! 1588: rac = lift_intern(rac); lx = lg(rac);
! 1589: if (prec==1)
1.1 noro 1590: {
1.2 ! noro 1591: y = cgetg(lx,t_COL);
! 1592: for (i=1; i<lx; i++)
! 1593: y[i] = (long)Fp_to_Zp((GEN)rac[i],p,p,1);
! 1594: return y;
1.1 noro 1595: }
1.2 ! noro 1596: y = cgetg(degpol(f)+1,t_COL);
! 1597: q = gpowgs(p,prec);
! 1598: for (j=i=1; i<lx; i++)
1.1 noro 1599: {
1.2 ! noro 1600: z = apprgen_i(f, Fp_to_Zp((GEN)rac[i], p,q,prec));
! 1601: for (k=1; k<lg(z); k++,j++) y[j] = z[k];
1.1 noro 1602: }
1.2 ! noro 1603: setlg(y,j); return y;
! 1604: }
! 1605:
! 1606: /* reverse x in place */
! 1607: static void
! 1608: polreverse(GEN x)
! 1609: {
! 1610: long i, j;
! 1611: if (typ(x) != t_POL) err(typeer,"polreverse");
! 1612: for (i=2, j=lgef(x)-1; i<j; i++, j--) lswap(x[i], x[j]);
! 1613: (void)normalizepol(x);
! 1614: }
! 1615:
! 1616: static GEN
! 1617: pnormalize(GEN f, GEN p, long prec, long n, GEN *plead, long *pprec, int *prev)
! 1618: {
! 1619: *plead = leading_term(f);
! 1620: *pprec = prec;
! 1621: *prev = 0;
! 1622: if (!gcmp1(*plead))
1.1 noro 1623: {
1.2 ! noro 1624: long val = ggval(*plead,p), val1 = ggval(constant_term(f),p);
! 1625: if (val1 < val)
1.1 noro 1626: {
1.2 ! noro 1627: *prev = 1; polreverse(f);
! 1628: /* take care of loss of precision from leading coeff of factor
! 1629: * (whose valuation is <= val) */
! 1630: *pprec += val;
! 1631: val = val1;
1.1 noro 1632: }
1.2 ! noro 1633: *pprec += val * n;
1.1 noro 1634: }
1.2 ! noro 1635: return pol_to_monic(f, plead);
1.1 noro 1636: }
1637:
1.2 ! noro 1638: /* return p-adic roots of f, precision prec */
1.1 noro 1639: GEN
1.2 ! noro 1640: rootpadic(GEN f, GEN p, long prec)
1.1 noro 1641: {
1.2 ! noro 1642: gpmem_t av = avma;
! 1643: GEN lead,y;
! 1644: long PREC,i,k;
! 1645: int reverse;
1.1 noro 1646:
1647: if (typ(f)!=t_POL) err(notpoler,"rootpadic");
1648: if (gcmp0(f)) err(zeropoler,"rootpadic");
1.2 ! noro 1649: if (prec <= 0) err(rootper4);
1.1 noro 1650: f = padic_pol_to_int(f);
1.2 ! noro 1651: f = pnormalize(f, p, prec, 1, &lead, &PREC, &reverse);
! 1652:
! 1653: y = rootpadic_i(f,p,PREC);
! 1654: k = lg(y);
! 1655: if (lead)
! 1656: for (i=1; i<k; i++) y[i] = ldiv((GEN)y[i], lead);
! 1657: if (reverse)
! 1658: for (i=1; i<k; i++) y[i] = linv((GEN)y[i]);
! 1659: return gerepilecopy(av, y);
1.1 noro 1660: }
1661: /*************************************************************************/
1662: /* rootpadicfast */
1663: /*************************************************************************/
1664:
1.2 ! noro 1665: /* lift accelerator */
1.1 noro 1666: long hensel_lift_accel(long n, long *pmask)
1667: {
1668: long a,j;
1669: long mask;
1670: mask=0;
1671: for(j=BITS_IN_LONG-1, a=n ;; j--)
1672: {
1673: mask|=(a&1)<<j;
1674: a=(a>>1)+(a&1);
1675: if (a==1) break;
1676: }
1677: *pmask=mask>>j;
1678: return BITS_IN_LONG-j;
1679: }
1680: /*
1681: SPEC:
1682: q is an integer > 1
1683: e>=0
1684: f in ZZ[X], with leading term prime to q.
1685: S must be a simple root mod p for all p|q.
1686:
1687: return roots of f mod q^e, as integers (implicitly mod Q)
1688: */
1689:
1690: /* STANDARD USE
1691: There exists p a prime number and a>0 such that
1.2 ! noro 1692: q=p^a
1.1 noro 1693: f in ZZ[X], with leading term prime to p.
1694: S must be a simple root mod p.
1695:
1696: return p-adics roots of f with prec b, as integers (implicitly mod q^e)
1697: */
1698:
1699: GEN
1700: rootpadiclift(GEN T, GEN S, GEN p, long e)
1701: {
1.2 ! noro 1702: gpmem_t ltop=avma;
1.1 noro 1703: long x;
1704: GEN qold, q, qm1;
1705: GEN W, Tr, Sr, Wr = gzero;
1706: long i, nb, mask;
1707: x = varn(T);
1708: qold = p ; q = p; qm1 = gun;
1709: nb=hensel_lift_accel(e, &mask);
1710: Tr = FpX_red(T,q);
1711: W=FpX_eval(deriv(Tr, x),S,q);
1712: W=mpinvmod(W,q);
1713: for(i=0;i<nb;i++)
1.2 ! noro 1714: {
1.1 noro 1715: qm1 = (mask&(1<<i))?sqri(qm1):mulii(qm1, q);
1716: q = mulii(qm1, p);
1717: Tr = FpX_red(T,q);
1718: Sr = S;
1719: if (i)
1720: {
1721: W = modii(mulii(Wr,FpX_eval(deriv(Tr,x),Sr,qold)),qold);
1722: W = subii(gdeux,W);
1723: W = modii(mulii(Wr, W),qold);
1724: }
1725: Wr = W;
1726: S = subii(Sr, mulii(Wr, FpX_eval(Tr, Sr,q)));
1727: S = modii(S,q);
1728: qold = q;
1729: }
1730: return gerepileupto(ltop,S);
1731: }
1732: /*
1733: * Apply rootpadiclift to all roots in S and trace trick.
1734: * Elements of S must be distinct simple roots mod p for all p|q.
1735: */
1736:
1737: GEN
1738: rootpadicliftroots(GEN f, GEN S, GEN q, long e)
1739: {
1740: GEN y;
1741: long i,n=lg(S);
1742: if (n==1)
1743: return gcopy(S);
1744: y=cgetg(n,typ(S));
1745: for (i=1; i<n-1; i++)
1746: y[i]=(long) rootpadiclift(f, (GEN) S[i], q, e);
1747: if (n!=lgef(f)-2)/* non totally split*/
1748: y[n-1]=(long) rootpadiclift(f, (GEN) S[n-1], q, e);
1749: else/* distinct-->totally split-->use trace trick */
1750: {
1.2 ! noro 1751: gpmem_t av=avma;
1.1 noro 1752: GEN z;
1753: z=(GEN)f[lgef(f)-2];/*-trace(roots)*/
1754: for(i=1; i<n-1;i++)
1755: z=addii(z,(GEN) y[i]);
1756: z=modii(negi(z),gpowgs(q,e));
1757: y[n-1]=lpileupto(av,z);
1758: }
1759: return y;
1760: }
1761: /*
1762: p is a prime number, pr a power of p,
1763:
1764: f in ZZ[X], with leading term prime to p.
1765: f must have no multiple roots mod p.
1766:
1767: return p-adics roots of f with prec pr, as integers (implicitly mod pr)
1.2 ! noro 1768:
1.1 noro 1769: */
1770: GEN
1771: rootpadicfast(GEN f, GEN p, long e)
1772: {
1.2 ! noro 1773: gpmem_t ltop=avma;
1.1 noro 1774: GEN S,y;
1775: S=lift(rootmod(f,p));/*no multiplicity*/
1776: if (lg(S)==1)/*no roots*/
1777: {
1778: avma=ltop;
1779: return cgetg(1,t_COL);
1780: }
1781: S=gclone(S);
1782: avma=ltop;
1783: y=rootpadicliftroots(f,S,p,e);
1784: gunclone(S);
1785: return y;
1786: }
1787: /* Same as rootpadiclift for the polynomial X^n-a,
1.2 ! noro 1788: * but here, n can be much larger.
1.1 noro 1789: * TODO: generalize to sparse polynomials.
1790: */
1791: GEN
1792: padicsqrtnlift(GEN a, GEN n, GEN S, GEN p, long e)
1793: {
1.2 ! noro 1794: gpmem_t ltop=avma;
1.1 noro 1795: GEN qold, q, qm1;
1796: GEN W, Sr, Wr = gzero;
1797: long i, nb, mask;
1798: qold = p ; q = p; qm1 = gun;
1799: nb = hensel_lift_accel(e, &mask);
1800: W = modii(mulii(n,powmodulo(S,subii(n,gun),q)),q);
1801: W = mpinvmod(W,q);
1802: for(i=0;i<nb;i++)
1.2 ! noro 1803: {
1.1 noro 1804: qm1 = (mask&(1<<i))?sqri(qm1):mulii(qm1, q);
1805: q = mulii(qm1, p);
1806: Sr = S;
1807: if (i)
1808: {
1809: W = modii(mulii(Wr,mulii(n,powmodulo(Sr,subii(n,gun),qold))),qold);
1810: W = subii(gdeux,W);
1811: W = modii(mulii(Wr, W),qold);
1812: }
1813: Wr = W;
1814: S = subii(Sr, mulii(Wr, subii(powmodulo(Sr,n,q),a)));
1815: S = modii(S,q);
1816: qold = q;
1817: }
1818: return gerepileupto(ltop,S);
1819: }
1820: /**************************************************************************/
1821: static long
1822: getprec(GEN x, long prec, GEN *p)
1823: {
1824: long i,e;
1825: GEN p1;
1826:
1827: for (i = lgef(x)-1; i>1; i--)
1828: {
1829: p1=(GEN)x[i];
1830: if (typ(p1)==t_PADIC)
1831: {
1832: e=valp(p1); if (signe(p1[4])) e += precp(p1);
1833: if (e<prec) prec = e; *p = (GEN)p1[2];
1834: }
1835: }
1836: return prec;
1837: }
1838:
1.2 ! noro 1839: /* a belongs to finite extension of Q_p, return all roots of f equal to a
! 1840: * mod p. We assume f(a) = 0 (mod p) [mod 4 if p=2] */
1.1 noro 1841: GEN
1842: apprgen9(GEN f, GEN a)
1843: {
1.2 ! noro 1844: GEN fp,p1,p,pro,x,x2,u,ip,T,vecg;
! 1845: long v, ps_1, i, j, k, n, prec, d, va, fl2;
! 1846: gpmem_t av=avma, tetpil;
1.1 noro 1847:
1848: if (typ(f)!=t_POL) err(notpoler,"apprgen9");
1849: if (gcmp0(f)) err(zeropoler,"apprgen9");
1850: if (typ(a)==t_PADIC) return apprgen(f,a);
1851: if (typ(a)!=t_POLMOD || typ(a[2])!=t_POL) err(rootper1);
1.2 ! noro 1852:
! 1853: fp = derivpol(f); u = ggcd(f,fp);
! 1854: if (degpol(u) > 0) { f = gdeuc(f,u); fp = derivpol(f); }
! 1855: T = (GEN)a[1];
1.1 noro 1856: prec = getprec((GEN)a[2], BIGINT, &p);
1.2 ! noro 1857: prec = getprec(T, prec, &p);
1.1 noro 1858: if (prec==BIGINT) err(rootper1);
1859:
1.2 ! noro 1860: p1 = poleval(f,a); v = ggval(lift_intern(p1),p); if (v<=0) err(rootper2);
! 1861: fl2 = egalii(p,gdeux);
1.1 noro 1862: if (fl2 && v==1) err(rootper2);
1863: v=ggval(lift_intern(poleval(fp,a)), p);
1864: if (!v)
1865: {
1866: while (!gcmp0(p1))
1867: {
1868: a = gsub(a, gdiv(p1,poleval(fp,a)));
1869: p1 = poleval(f,a);
1870: }
1871: tetpil=avma; pro=cgetg(2,t_COL); pro[1]=lcopy(a);
1872: return gerepile(av,tetpil,pro);
1873: }
1.2 ! noro 1874: n=degpol(f); pro=cgetg(n+1,t_COL);
1.1 noro 1875:
1876: if (is_bigint(p)) err(impl,"apprgen9 for p>=2^31");
1.2 ! noro 1877: x=gmodulcp(ggrandocp(p,prec), T);
1.1 noro 1878: if (fl2)
1879: {
1880: ps_1=3; x2=ggrandocp(p,2); p=stoi(4);
1881: }
1882: else
1883: {
1884: ps_1=itos(p)-1; x2=ggrandocp(p,1);
1885: }
1886: f = poleval(f,gadd(a,gmul(p,polx[varn(f)])));
1.2 ! noro 1887: f = gdiv(f,gpowgs(p,ggval(f,p)));
! 1888:
! 1889: d=degpol(T); vecg=cgetg(d+1,t_COL);
1.1 noro 1890: for (i=1; i<=d; i++)
1891: vecg[i] = (long)setloop(gzero);
1.2 ! noro 1892: va=varn(T); j = 1;
1.1 noro 1893: for(;;) /* loop through F_q */
1894: {
1.2 ! noro 1895: ip=gmodulcp(gtopoly(vecg,va),T);
1.1 noro 1896: if (gcmp0(poleval(f,gadd(ip,x2))))
1897: {
1.2 ! noro 1898: u = apprgen9(f,gadd(ip,x));
! 1899: for (k=1; k<lg(u); k++) pro[j++] = ladd(a, gmul(p,(GEN)u[k]));
1.1 noro 1900: }
1901: for (i=d; i; i--)
1902: {
1903: p1 = (GEN)vecg[i];
1904: if (p1[2] != ps_1) { (void)incloop(p1); break; }
1905: affsi(0, p1);
1906: }
1907: if (!i) break;
1908: }
1.2 ! noro 1909: setlg(pro,j); return gerepilecopy(av,pro);
1.1 noro 1910: }
1911:
1.2 ! noro 1912: /*******************************************************************/
! 1913: /* */
! 1914: /* FACTORIZATION in Zp[X] */
! 1915: /* */
! 1916: /*******************************************************************/
! 1917: extern GEN ZX_squff(GEN f, GEN *ex);
! 1918: extern GEN fact_from_DDF(GEN fa, GEN e, long n);
! 1919:
1.1 noro 1920: int
1921: cmp_padic(GEN x, GEN y)
1922: {
1923: long vx, vy;
1924: if (x == gzero) return -1;
1925: if (y == gzero) return 1;
1926: vx = valp(x);
1927: vy = valp(y);
1928: if (vx < vy) return 1;
1929: if (vx > vy) return -1;
1930: return cmpii((GEN)x[4], (GEN)y[4]);
1931: }
1932:
1.2 ! noro 1933: /*******************************/
! 1934: /* Using Buchmann--Lenstra */
! 1935: /*******************************/
! 1936:
! 1937: /* factor T = nf[1] in Zp to precision k */
1.1 noro 1938: static GEN
1.2 ! noro 1939: padicff2(GEN nf,GEN p,long k)
1.1 noro 1940: {
1.2 ! noro 1941: GEN z, mat, D, U,fa, pk, dec_p, Ui, mulx;
! 1942: long i, l;
1.1 noro 1943:
1.2 ! noro 1944: mulx = eltmul_get_table(nf, gmael(nf,8,2)); /* mul by (x mod T) */
! 1945: dec_p = primedec(nf,p);
! 1946: l = lg(dec_p); fa = cgetg(l,t_COL);
! 1947: D = NULL; /* -Wall */
1.1 noro 1948: for (i=1; i<l; i++)
1949: {
1.2 ! noro 1950: GEN P = (GEN)dec_p[i];
! 1951: long e = itos((GEN)P[3]), ef = e * itos((GEN)P[4]);
! 1952: D = smithall(idealpows(nf,P, k*e), &U, NULL);
! 1953: Ui= ginv(U); setlg(Ui, ef+1); /* cf smithrel */
! 1954: U = rowextract_i(U, 1, ef);
! 1955: mat = gmul(U, gmul(mulx, Ui));
! 1956: fa[i] = (long)caradj(mat,0,NULL);
1.1 noro 1957: }
1.2 ! noro 1958: pk = gcoeff(D,1,1); /* = p^k */
! 1959: z = cgetg(l,t_COL); pk = icopy(pk);
1.1 noro 1960: for (i=1; i<l; i++)
1.2 ! noro 1961: z[i] = (long)pol_to_padic((GEN)fa[i],pk,p,k);
! 1962: return z;
1.1 noro 1963: }
1964:
1965: static GEN
1966: padicff(GEN x,GEN p,long pr)
1967: {
1.2 ! noro 1968: GEN q,basden,bas,invbas,mul,dx,dK,nf,fa,g,e;
! 1969: long n=degpol(x);
! 1970: gpmem_t av=avma;
! 1971:
! 1972: nf=cgetg(10,t_VEC); nf[1]=(long)x;
! 1973: fa = cgetg(3,t_MAT);
! 1974: g = cgetg(3,t_COL); fa[1] = (long)g;
! 1975: e = cgetg(3,t_COL); fa[2] = (long)e;
! 1976: dx = ZX_disc(x);
! 1977: g[1] = (long)p; e[1] = lstoi(pvaluation(absi(dx),p,&q));
! 1978: g[2] = (long)q; e[2] = un;
! 1979:
! 1980: bas = nfbasis(x, &dK, 0, fa);
! 1981: nf[3] = (long)dK;
! 1982: nf[4] = divise( diviiexact(dx, dK), p )? (long)p: un;
1.1 noro 1983: basden = get_bas_den(bas);
1984: invbas = QM_inv(vecpol_to_mat(bas,n), gun);
1.2 ! noro 1985: mul = get_mul_table(x,basden,invbas);
1.1 noro 1986: nf[7]=(long)bas;
1987: nf[8]=(long)invbas;
1988: nf[9]=(long)mul; nf[2]=nf[5]=nf[6]=zero;
1989: return gerepileupto(av,padicff2(nf,p,pr));
1990: }
1991:
1992: GEN
1.2 ! noro 1993: factorpadic2(GEN f, GEN p, long prec)
1.1 noro 1994: {
1.2 ! noro 1995: gpmem_t av = avma;
! 1996: GEN fa,ex,y;
! 1997: long n,i,l;
1.1 noro 1998:
1.2 ! noro 1999: if (typ(f)!=t_POL) err(notpoler,"factorpadic");
! 2000: if (gcmp0(f)) err(zeropoler,"factorpadic");
! 2001: if (prec<=0) err(rootper4);
! 2002:
! 2003: n = degpol(f);
! 2004: if (n==0) return trivfact();
! 2005: if (n==1) return padic_trivfact(f,p,prec);
! 2006: if (!gcmp1(leading_term(f)))
1.1 noro 2007: err(impl,"factorpadic2 for non-monic polynomial");
1.2 ! noro 2008: f = padic_pol_to_int(f);
! 2009:
! 2010: fa = ZX_squff(f, &ex);
! 2011: l = lg(fa); n = 0;
! 2012: for (i=1; i<l; i++)
! 2013: {
! 2014: fa[i] = (long)padicff((GEN)fa[i],p,prec);
! 2015: n += lg(fa[i])-1;
! 2016: }
! 2017:
! 2018: y = fact_from_DDF(fa,ex,n);
! 2019: return gerepileupto(av, sort_factor(y, cmp_padic));
1.1 noro 2020: }
2021:
1.2 ! noro 2022: /***********************/
! 2023: /* Using ROUND 4 */
! 2024: /***********************/
1.1 noro 2025: extern GEN Decomp(GEN p,GEN f,long mf,GEN theta,GEN chi,GEN nu,long r);
2026: extern GEN nilord(GEN p, GEN fx, long mf, GEN gx, long flag);
2027: extern GEN hensel_lift_fact(GEN pol, GEN Q, GEN T, GEN p, GEN pev, long e);
2028:
1.2 ! noro 2029: static int
! 2030: expo_is_squarefree(GEN e)
1.1 noro 2031: {
1.2 ! noro 2032: long i, l = lg(e);
! 2033: for (i=1; i<l; i++)
! 2034: if (e[i] != 1) return 0;
! 2035: return 1;
1.1 noro 2036: }
2037:
2038: GEN
2039: factorpadic4(GEN f,GEN p,long prec)
2040: {
1.2 ! noro 2041: gpmem_t av = avma;
! 2042: GEN w,g,poly,y,p1,p2,ex,pols,exps,ppow,lead;
! 2043: long v=varn(f),n=degpol(f),mfx,i,k,j,r,pr;
1.1 noro 2044: int reverse = 0;
2045:
2046: if (typ(f)!=t_POL) err(notpoler,"factorpadic");
2047: if (typ(p)!=t_INT) err(arither1);
2048: if (gcmp0(f)) err(zeropoler,"factorpadic");
2049: if (prec<=0) err(rootper4);
2050:
2051: if (n==0) return trivfact();
1.2 ! noro 2052: if (n==1) return padic_trivfact(f,p,prec);
! 2053: f = padic_pol_to_int(f);
! 2054: f = pnormalize(f, p, prec, n-1, &lead, &pr, &reverse);
1.1 noro 2055:
1.2 ! noro 2056: poly = ZX_squff(f,&ex);
! 2057: pols = cgetg(n+1,t_COL);
! 2058: exps = cgetg(n+1,t_COL); n = lg(poly);
! 2059: for (j=i=1; i<n; i++)
! 2060: {
! 2061: gpmem_t av1 = avma;
! 2062: GEN fx = (GEN)poly[i], fa = factmod0(fx,p);
! 2063: w = (GEN)fa[1];
! 2064: if (expo_is_squarefree((GEN)fa[2]))
1.1 noro 2065: { /* no repeated factors: Hensel lift */
1.2 ! noro 2066: p1 = hensel_lift_fact(fx, w, NULL, p, gpowgs(p,pr), pr);
1.1 noro 2067: p2 = stoi(ex[i]);
2068: for (k=1; k<lg(p1); k++,j++)
2069: {
2070: pols[j] = p1[k];
2071: exps[j] = (long)p2;
2072: }
2073: continue;
2074: }
2075: /* use Round 4 */
1.2 ! noro 2076: mfx = ggval(ZX_disc(fx),p);
1.1 noro 2077: r = lg(w)-1;
1.2 ! noro 2078: g = (GEN)w[r];
1.1 noro 2079: p2 = (r == 1)? nilord(p,fx,mfx,g,pr)
2080: : Decomp(p,fx,mfx,polx[v],fx,g, (pr<=mfx)? mfx+1: pr);
2081: if (p2)
2082: {
1.2 ! noro 2083: p2 = gerepilecopy(av1,p2);
1.1 noro 2084: p1 = (GEN)p2[1];
2085: p2 = (GEN)p2[2];
2086: for (k=1; k<lg(p1); k++,j++)
2087: {
1.2 ! noro 2088: pols[j] = p1[k];
! 2089: exps[j] = lmulis((GEN)p2[k],ex[i]);
1.1 noro 2090: }
2091: }
2092: else
2093: {
1.2 ! noro 2094: avma = av1;
! 2095: pols[j] = (long)fx;
! 2096: exps[j] = lstoi(ex[i]); j++;
1.1 noro 2097: }
2098: }
2099: if (lead)
2100: for (i=1; i<j; i++)
1.2 ! noro 2101: pols[i] = (long)primpart( unscale_pol((GEN)pols[i], lead) );
! 2102: y = cgetg(3,t_MAT);
! 2103: p1 = cgetg(j,t_COL); p = icopy(p); ppow = gpowgs(p,prec);
1.1 noro 2104: for (i=1; i<j; i++)
2105: {
2106: if (reverse) polreverse((GEN)pols[i]);
2107: p1[i] = (long)pol_to_padic((GEN)pols[i],ppow,p,prec);
2108: }
1.2 ! noro 2109: y[1] = (long)p1; setlg(exps,j);
! 2110: y[2] = lcopy(exps);
! 2111: return gerepileupto(av, sort_factor(y, cmp_padic));
1.1 noro 2112: }
2113:
2114: GEN
2115: factorpadic0(GEN f,GEN p,long r,long flag)
2116: {
2117: switch(flag)
2118: {
2119: case 0: return factorpadic4(f,p,r);
2120: case 1: return factorpadic2(f,p,r);
2121: default: err(flagerr,"factorpadic");
2122: }
2123: return NULL; /* not reached */
2124: }
2125:
2126: /*******************************************************************/
2127: /* */
2128: /* FACTORISATION DANS F_q */
2129: /* */
2130: /*******************************************************************/
2131: extern GEN to_Kronecker(GEN P, GEN Q);
1.2 ! noro 2132: static GEN spec_Fq_pow_mod_pol(GEN x, GEN S, GEN T, GEN p);
1.1 noro 2133:
2134: static GEN
1.2 ! noro 2135: to_Fq(GEN x, GEN T, GEN p)
1.1 noro 2136: {
1.2 ! noro 2137: long i,lx, tx = typ(x);
! 2138: GEN z = cgetg(3,t_POLMOD), y;
! 2139:
! 2140: if (tx == t_INT)
! 2141: y = mod(x,p);
1.1 noro 2142: else
1.2 ! noro 2143: {
! 2144: if (tx != t_POL) err(typeer,"to_Fq");
! 2145: lx = lgef(x);
! 2146: y = cgetg(lx,t_POL);
! 2147: y[1] = x[1];
! 2148: if (lx == 2) setsigne(y, 0);
! 2149: else
! 2150: for (i=2; i<lx; i++) y[i] = (long)mod((GEN)x[i], p);
! 2151: }
! 2152: /* assume deg(y) < deg(T) */
! 2153: z[1] = (long)T;
! 2154: z[2] = (long)y; return z;
1.1 noro 2155: }
2156:
2157: static GEN
1.2 ! noro 2158: to_Fq_pol(GEN x, GEN T, GEN p)
1.1 noro 2159: {
1.2 ! noro 2160: long i, lx, tx = typ(x);
! 2161: if (tx != t_POL) err(typeer,"to_Fq_pol");
! 2162: lx = lgef(x);
! 2163: for (i=2; i<lx; i++) x[i] = (long)to_Fq((GEN)x[i],T,p);
! 2164: return x;
1.1 noro 2165: }
2166:
1.2 ! noro 2167: /* assume T a clone */
! 2168: static GEN
! 2169: copy_then_free(GEN T)
1.1 noro 2170: {
1.2 ! noro 2171: GEN t = forcecopy(T); gunclone(T); return t;
1.1 noro 2172: }
2173:
2174: static GEN
1.2 ! noro 2175: to_Fq_fact(GEN t, GEN ex, long nbf, int sort, GEN unfq, gpmem_t av)
1.1 noro 2176: {
1.2 ! noro 2177: GEN T = (GEN)unfq[1]/*clone*/, y = cgetg(3,t_MAT), u,v,p;
! 2178: long j,k, l = lg(t);
1.1 noro 2179:
1.2 ! noro 2180: u = cgetg(nbf,t_COL); y[1] = (long)u;
! 2181: v = cgetg(nbf,t_COL); y[2] = (long)v;
! 2182: for (j=1,k=0; j<l; j++)
! 2183: if (ex[j])
! 2184: {
! 2185: k++;
! 2186: u[k] = (long)simplify((GEN)t[j]); /* may contain pols of degree 0 */
! 2187: v[k] = lstoi(ex[j]);
! 2188: }
! 2189: y = gerepileupto(av, y);
! 2190: if (sort) y = sort_factor(y,cmp_pol);
! 2191: T = copy_then_free(T);
! 2192: p = (GEN)leading_term(T)[1];
! 2193: u = (GEN)y[1];
! 2194: for (j=1; j<nbf; j++) u[j] = (long)to_Fq_pol((GEN)u[j], T,p);
! 2195: return y;
1.1 noro 2196: }
2197:
2198: /* split into r factors of degree d */
2199: static void
1.2 ! noro 2200: FqX_split(GEN *t, long d, GEN q, GEN S, GEN T, GEN p)
1.1 noro 2201: {
1.2 ! noro 2202: long l, v, is2, cnt, dt = degpol(*t), dT = degpol(T);
! 2203: gpmem_t av;
1.1 noro 2204: GEN w,w0;
2205:
2206: if (dt == d) return;
2207: v = varn(*t);
1.2 ! noro 2208: if (DEBUGLEVEL > 6) (void)timer2();
1.1 noro 2209: av = avma; is2 = egalii(p, gdeux);
2210: for(cnt = 1;;cnt++)
2211: { /* splits *t with probability ~ 1 - 2^(1-r) */
1.2 ! noro 2212: w = w0 = FqX_rand(dt,v, T,p);
1.1 noro 2213: for (l=1; l<d; l++) /* sum_{0<i<d} w^(q^i), result in (F_q)^r */
1.2 ! noro 2214: w = gadd(w0, spec_Fq_pow_mod_pol(w, S, T, p));
! 2215: w = FqX_red(w, T,p);
1.1 noro 2216: if (is2)
2217: {
2218: w0 = w;
1.2 ! noro 2219: for (l=1; l<dT; l++) /* sum_{0<i<k} w^(2^i), result in (F_2)^r */
! 2220: {
! 2221: w = FqX_rem(FqX_sqr(w,T,p), *t, T,p);
! 2222: w = FqX_red(gadd(w0,w), NULL,p);
! 2223: }
1.1 noro 2224: }
2225: else
2226: {
1.2 ! noro 2227: w = FqXQ_pow(w, shifti(q,-1), *t, T, p);
1.1 noro 2228: /* w in {-1,0,1}^r */
1.2 ! noro 2229: if (!degpol(w)) continue;
1.1 noro 2230: w[2] = ladd((GEN)w[2], gun);
2231: }
1.2 ! noro 2232: w = FqX_gcd(*t,w, T,p); l = degpol(w);
1.1 noro 2233: if (l && l != dt) break;
2234: avma = av;
2235: }
2236: w = gerepileupto(av,w);
1.2 ! noro 2237: if (DEBUGLEVEL > 6)
! 2238: fprintferr("[FqX_split] splitting time: %ld (%ld trials)\n",timer2(),cnt);
! 2239: l /= d; t[l] = FqX_div(*t,w, T,p); *t = w;
! 2240: FqX_split(t+l,d,q,S,T,p);
! 2241: FqX_split(t ,d,q,S,T,p);
1.1 noro 2242: }
2243:
2244: /* to "compare" (real) scalars and t_INTMODs */
2245: static int
2246: cmp_coeff(GEN x, GEN y)
2247: {
2248: if (typ(x) == t_INTMOD) x = (GEN)x[2];
2249: if (typ(y) == t_INTMOD) y = (GEN)y[2];
2250: return gcmp(x,y);
2251: }
2252:
2253: int
2254: cmp_pol(GEN x, GEN y)
2255: {
2256: long fx[3], fy[3];
2257: long i,lx,ly;
2258: int fl;
2259: if (typ(x) == t_POLMOD) x = (GEN)x[2];
2260: if (typ(y) == t_POLMOD) y = (GEN)y[2];
2261: if (typ(x) == t_POL) lx = lgef(x); else { lx = 3; fx[2] = (long)x; x = fx; }
2262: if (typ(y) == t_POL) ly = lgef(y); else { ly = 3; fy[2] = (long)y; y = fy; }
2263: if (lx > ly) return 1;
2264: if (lx < ly) return -1;
2265: for (i=lx-1; i>1; i--)
2266: if ((fl = cmp_coeff((GEN)x[i], (GEN)y[i]))) return fl;
2267: return 0;
2268: }
2269:
1.2 ! noro 2270: /* assume n > 1, X over FqX */
! 2271: /* return S = [ X^q, X^2q, ... X^(n-1)q ] mod u (in Fq[X]) in Kronecker form */
1.1 noro 2272: static GEN
1.2 ! noro 2273: init_pow_q_mod_pT(GEN X, GEN q, GEN u, GEN T, GEN p)
1.1 noro 2274: {
1.2 ! noro 2275: long i, n = degpol(u);
1.1 noro 2276: GEN p1, S = cgetg(n, t_VEC);
2277:
1.2 ! noro 2278: S[1] = (long)FqXQ_pow(X, q, u, T, p);
1.1 noro 2279: #if 1 /* use as many squarings as possible */
2280: for (i=2; i < n; i+=2)
1.2 ! noro 2281: {
1.1 noro 2282: p1 = gsqr((GEN)S[i>>1]);
1.2 ! noro 2283: S[i] = (long)FqX_rem(p1, u, T,p);
1.1 noro 2284: if (i == n-1) break;
2285: p1 = gmul((GEN)S[i], (GEN)S[1]);
1.2 ! noro 2286: S[i+1] = (long)FqX_rem(p1, u, T,p);
! 2287: }
1.1 noro 2288: #else
2289: for (i=2; i < n; i++)
1.2 ! noro 2290: {
1.1 noro 2291: p1 = gmul((GEN)S[i-1], (GEN)S[1]);
1.2 ! noro 2292: S[i] = (long)FqX_rem(p1, u, T,p);
! 2293: }
1.1 noro 2294: #endif
2295: for (i=1; i < n; i++)
1.2 ! noro 2296: S[i] = (long)to_Kronecker((GEN)S[i], T);
1.1 noro 2297: return S;
2298: }
2299:
2300: /* compute x^q, S is as above */
2301: static GEN
1.2 ! noro 2302: spec_Fq_pow_mod_pol(GEN x, GEN S, GEN T, GEN p)
1.1 noro 2303: {
1.2 ! noro 2304: long i, dx = degpol(x);
! 2305: gpmem_t av = avma, lim = stack_lim(av, 1);
1.1 noro 2306: GEN x0 = x+2, z,c;
2307:
1.2 ! noro 2308: z = c = (GEN)x0[0];
1.1 noro 2309: for (i = 1; i <= dx; i++)
2310: {
2311: GEN d;
2312: c = (GEN)x0[i];
2313: if (gcmp0(c)) continue;
2314: d = (GEN)S[i];
1.2 ! noro 2315: if (!gcmp1(c)) d = gmul(c,d);
1.1 noro 2316: z = gadd(z, d);
2317: if (low_stack(lim, stack_lim(av,1)))
2318: {
2319: if(DEBUGMEM>1) err(warnmem,"spec_Fq_pow_mod_pol");
2320: z = gerepileupto(av, z);
2321: }
2322: }
1.2 ! noro 2323: z = FpXQX_from_Kronecker(z, T, p);
1.1 noro 2324: setvarn(z, varn(x)); return gerepileupto(av, z);
2325: }
2326:
1.2 ! noro 2327: static long
! 2328: isabsolutepol(GEN f)
1.1 noro 2329: {
1.2 ! noro 2330: int i, l = lgef(f);
! 2331: for(i=2; i<l; i++)
1.1 noro 2332: {
1.2 ! noro 2333: GEN c = (GEN)f[i];
! 2334: if (typ(c) == t_POL && degpol(c) > 0) return 0;
1.1 noro 2335: }
1.2 ! noro 2336: return 1;
1.1 noro 2337: }
2338:
2339: GEN
1.2 ! noro 2340: factmod9(GEN f, GEN p, GEN T)
1.1 noro 2341: {
1.2 ! noro 2342: gpmem_t av = avma;
! 2343: long pg, i, j, k, d, e, N, vf, va, nbfact, nbf, pk;
! 2344: GEN S,ex,f2,f3,df1,df2,g1,u,v,q,unfp,unfq, *t;
1.1 noro 2345: GEN frobinv,X;
2346:
1.2 ! noro 2347: if (typ(T)!=t_POL || typ(f)!=t_POL || gcmp0(T)) err(typeer,"factmod9");
! 2348: vf = varn(f);
! 2349: va = varn(T);
! 2350: if (va <= vf)
! 2351: err(talker,"polynomial variable must have higher priority in factorff");
! 2352: unfp = gmodulsg(1,p); T = gmul(unfp,T);
! 2353: unfq = gmodulo(gmul(unfp,polun[va]), T);
! 2354: f = gmul(unfq,f);
! 2355: if (!signe(f)) err(zeropoler,"factmod9");
! 2356: d = degpol(f); if (!d) { avma = av; return trivfact(); }
! 2357:
! 2358: f = simplify(lift_intern(lift_intern(f)));
! 2359: T = lift_intern(T);
! 2360: if (isabsolutepol(f))
! 2361: {
! 2362: GEN z = Fp_factor_rel0(f, p, T);
! 2363: return to_Fq_fact((GEN)z[1],(GEN)z[2],lg(z[1]), 0, unfq,av);
1.1 noro 2364: }
2365:
1.2 ! noro 2366: pg = is_bigint(p)? 0: itos(p);
1.1 noro 2367: S = df2 = NULL; /* gcc -Wall */
2368: t = (GEN*)cgetg(d+1,t_VEC); ex = new_chunk(d+1);
2369:
1.2 ! noro 2370: frobinv = gpowgs(p, degpol(T)-1);
! 2371:
! 2372: X = polx[vf];
! 2373: q = gpowgs(p, degpol(T));
1.1 noro 2374: e = nbfact = 1;
1.2 ! noro 2375: pk = 1;
! 2376: f3 = NULL;
! 2377: df1 = FqX_deriv(f, T, p);
1.1 noro 2378: for(;;)
2379: {
2380: while (gcmp0(df1))
1.2 ! noro 2381: { /* needs d >= p: pg = 0 can't happen */
! 2382: pk *= pg; e = pk;
! 2383: j = (degpol(f))/pg+3; setlg(f,j); setlgef(f,j);
! 2384: for (i=2; i<j; i++)
! 2385: f[i] = (long)Fq_pow((GEN)f[pg*(i-2)+2], frobinv, T,p);
! 2386: df1 = FqX_deriv(f, T, p); f3 = NULL;
1.1 noro 2387: }
1.2 ! noro 2388: f2 = f3? f3: FqX_gcd(f,df1, T,p);
! 2389: if (!degpol(f2)) u = f;
1.1 noro 2390: else
2391: {
1.2 ! noro 2392: g1 = FqX_div(f,f2, T,p); df2 = FqX_deriv(f2, T,p);
! 2393: if (gcmp0(df2)) { u = g1; f3 = f2; }
1.1 noro 2394: else
2395: {
1.2 ! noro 2396: f3 = FqX_gcd(f2,df2, T,p);
! 2397: if (!degpol(f3)) u = FqX_div(g1,f2, T,p);
1.1 noro 2398: else
1.2 ! noro 2399: u = FqX_div(g1, FqX_div(f2,f3, T,p), T,p);
1.1 noro 2400: }
2401: }
2402: /* u is square-free (product of irreducibles of multiplicity e) */
1.2 ! noro 2403:
! 2404: #if 0
! 2405: N = degpol(u);
! 2406: if (N)
! 2407: {
! 2408: t[nbfact] = FpXQX_normalize(u, T,p);
! 2409: d = (N==1)? 1: FqX_split_berlekamp(t+nbfact, q, T, p);
! 2410: for (j=0; j<d; j++) ex[nbfact+j] = e;
! 2411: nbfact += d;
! 2412: }
! 2413: #else
! 2414: {
! 2415: GEN qqd = gun, g;
! 2416: long dg;
! 2417:
! 2418: N = degpol(u); v = X;
! 2419: if (N > 1) S = init_pow_q_mod_pT(X, q, u, T, p);
! 2420: for (d=1; d <= N>>1; d++)
! 2421: {
! 2422: qqd = mulii(qqd,q);
! 2423: v = spec_Fq_pow_mod_pol(v, S, T, p);
! 2424: g = FqX_gcd(gsub(v,X),u, T,p);
1.1 noro 2425: dg = degpol(g);
2426: if (dg <= 0) continue;
2427:
2428: /* all factors of g have degree d */
2429: j = nbfact+dg/d;
2430:
2431: t[nbfact] = g;
1.2 ! noro 2432: FqX_split(t+nbfact,d,q,S,T,p);
! 2433: for (; nbfact<j; nbfact++) ex[nbfact] = e;
! 2434: N -= dg;
! 2435: u = FqX_div(u,g, T,p);
! 2436: v = FqX_rem(v,u, T,p);
1.1 noro 2437: }
1.2 ! noro 2438: if (N) { t[nbfact] = u; ex[nbfact++] = e; }
! 2439: }
! 2440: #endif
! 2441: if (!degpol(f2)) break;
1.1 noro 2442:
1.2 ! noro 2443: f = f2; df1 = df2; e += pk;
1.1 noro 2444: }
2445:
1.2 ! noro 2446: nbf = nbfact; setlg(t, nbfact);
1.1 noro 2447: for (j=1; j<nbfact; j++)
2448: {
1.2 ! noro 2449: t[j] = FpXQX_normalize((GEN)t[j], T,p);
1.1 noro 2450: for (k=1; k<j; k++)
2451: if (ex[k] && gegal(t[j],t[k]))
2452: {
2453: ex[k] += ex[j]; ex[j]=0;
2454: nbf--; break;
2455: }
2456: }
1.2 ! noro 2457: return to_Fq_fact((GEN)t,ex,nbf, 1, unfq,av);
1.1 noro 2458: }
2459: /* See also: Isomorphisms between finite field and relative
2460: * factorization in polarit3.c */
2461:
2462: /*******************************************************************/
2463: /* */
2464: /* RACINES COMPLEXES */
2465: /* l represente la longueur voulue pour les parties */
2466: /* reelles et imaginaires des racines de x */
2467: /* */
2468: /*******************************************************************/
2469: GEN square_free_factorization(GEN pol);
2470: static GEN laguer(GEN pol,long N,GEN y0,GEN EPS,long PREC);
2471: GEN zrhqr(GEN a,long PREC);
2472:
2473: GEN
2474: rootsold(GEN x, long l)
2475: {
1.2 ! noro 2476: long i, j, f, g, gg, fr, deg, ln;
! 2477: gpmem_t av=avma, av0, av1, av2, av3;
1.1 noro 2478: long exc,expmin,m,deg0,k,ti,h,ii,e,e1,emax,v;
2479: GEN y,xc,xd0,xd,xdabs,p1,p2,p3,p4,p5,p6,p7,p8;
2480: GEN p9,p10,p11,p12,p14,p15,pa,pax,pb,pp,pq,ps;
2481:
2482: if (typ(x)!=t_POL) err(typeer,"rootsold");
2483: v=varn(x); deg0=degpol(x); expmin=12 - bit_accuracy(l);
2484: if (!signe(x)) err(zeropoler,"rootsold");
2485: y=cgetg(deg0+1,t_COL); if (!deg0) return y;
2486: for (i=1; i<=deg0; i++)
2487: {
2488: p1=cgetg(3,t_COMPLEX); p1[1]=lgetr(l); p1[2]=lgetr(l); y[i]=(long)p1;
2489: for (j=3; j<l; j++) ((GEN)p1[2])[j]=((GEN)p1[1])[j]=0;
2490: }
2491: g=1; gg=1;
2492: for (i=2; i<=deg0+2; i++)
2493: {
2494: ti=typ(x[i]);
2495: if (ti==t_REAL) gg=0;
2496: else if (ti==t_QUAD)
2497: {
2498: p2=gmael3(x,i,1,2);
2499: if (gsigne(p2)>0) g=0;
2500: } else if (ti != t_INT && ti != t_INTMOD && !is_frac_t(ti)) g=0;
2501: }
1.2 ! noro 2502: av1=avma; p2=cgetg(3,t_COMPLEX);
1.1 noro 2503: p2[1]=lmppi(DEFAULTPREC); p2[2]=ldivrs((GEN)p2[1],10);
2504: p11=cgetg(4,t_POL); p11[1]=evalsigne(1)+evallgef(4);
2505: setvarn(p11,v); p11[3]=un;
2506:
2507: p12=cgetg(5,t_POL); p12[1]=evalsigne(1)+evallgef(5);
2508: setvarn(p12,v); p12[4]=un;
2509: for (i=2; i<=deg0+2 && gcmp0((GEN)x[i]); i++) gaffsg(0,(GEN)y[i-1]);
2510: k=i-2;
2511: if (k!=deg0)
2512: {
2513: if (k)
2514: {
2515: j=deg0+3-k; pax=cgetg(j,t_POL);
2516: pax[1] = evalsigne(1) | evalvarn(v) | evallgef(j);
2517: for (i=2; i<j; i++) pax[i]=x[i+k];
2518: }
2519: else pax=x;
2520: xd0=deriv(pax,v); m=1; pa=pax;
2521: pq = NULL; /* for lint */
2522: if (gg) { pp=ggcd(pax,xd0); h=isnonscalar(pp); if (h) pq=gdeuc(pax,pp); }
2523: else{ pp=gun; h=0; }
2524: do
2525: {
2526: if (h)
2527: {
2528: pa=pp; pb=pq; pp=ggcd(pa,deriv(pa,v)); h=isnonscalar(pp);
2529: if (h) pq=gdeuc(pa,pp); else pq=pa; ps=gdeuc(pb,pq);
2530: }
2531: else ps=pa;
2532: /* calcul des racines d'ordre exactement m */
2533: deg=degpol(ps);
2534: if (deg)
2535: {
1.2 ! noro 2536: av3=avma; e=gexpo((GEN)ps[deg+2]); emax=e;
1.1 noro 2537: for (i=2; i<deg+2; i++)
2538: {
2539: p3=(GEN)(ps[i]);
2540: e1=gexpo(p3); if (e1>emax) emax=e1;
2541: }
1.2 ! noro 2542: e=emax-e; if (e<0) e=0; avma=av3; if (ps!=pax) xd0=deriv(ps,v);
1.1 noro 2543: xdabs=cgetg(deg+2,t_POL); xdabs[1]=xd0[1];
2544: for (i=2; i<deg+2; i++)
2545: {
1.2 ! noro 2546: av3=avma; p3=(GEN)xd0[i];
1.1 noro 2547: p4=gabs(greal(p3),l);
1.2 ! noro 2548: p5=gabs(gimag(p3),l);
! 2549: xdabs[i]=lpileupto(av3, gadd(p4,p5));
1.1 noro 2550: }
1.2 ! noro 2551: av0=avma; xc=gcopy(ps); xd=gcopy(xd0); av2=avma;
1.1 noro 2552: for (i=1; i<=deg; i++)
2553: {
2554: if (i==deg)
2555: {
2556: p1=(GEN)y[k+m*i]; gdivz(gneg_i((GEN)xc[2]),(GEN)xc[3],p1);
2557: p14=(GEN)p1[1]; p15=(GEN)p1[2];
2558: }
2559: else
2560: {
2561: p3=gshift(p2,e); p4=poleval(xc,p3); p5=gnorm(p4); exc=0;
2562: while (exc >= -20)
2563: {
2564: p7 = gneg_i(gdiv(p4, poleval(xd,p3)));
1.2 ! noro 2565: av3 = avma;
1.1 noro 2566: if (gcmp0(p5)) exc = -32;
2567: else exc = expo(gnorm(p7))-expo(gnorm(p3));
1.2 ! noro 2568: avma = av3;
1.1 noro 2569: for (j=1; j<=10; j++)
2570: {
2571: p8=gadd(p3,p7); p9=poleval(xc,p8); p10=gnorm(p9);
2572: if (exc < -20 || cmprr(p10,p5) < 0)
2573: {
2574: GEN *gptr[3];
2575: p3=p8; p4=p9; p5=p10;
2576: gptr[0]=&p3; gptr[1]=&p4; gptr[2]=&p5;
1.2 ! noro 2577: gerepilemanysp(av2,av3,gptr,3);
1.1 noro 2578: break;
2579: }
1.2 ! noro 2580: gshiftz(p7,-2,p7); avma=av3;
1.1 noro 2581: }
2582: if (j > 10)
2583: {
1.2 ! noro 2584: avma=av;
1.1 noro 2585: if (DEBUGLEVEL)
2586: {
2587: fprintferr("too many iterations in rootsold(): ");
2588: fprintferr("using roots2()\n"); flusherr();
2589: }
2590: return roots2(x,l);
2591: }
2592: }
2593: p1=(GEN)y[k+m*i]; setlg(p1[1],3); setlg(p1[2],3); gaffect(p3,p1);
1.2 ! noro 2594: avma=av2; p14=(GEN)p1[1]; p15=(GEN)p1[2];
1.1 noro 2595: for (ln=4; ln<=l; ln=(ln<<1)-2)
2596: {
2597: setlg(p14,ln); setlg(p15,ln);
2598: if (gcmp0(p14)) { settyp(p14,t_INT); p14[1]=2; }
2599: if (gcmp0(p15)) { settyp(p15,t_INT); p15[1]=2; }
2600: p4=poleval(xc,p1);
2601: p5=poleval(xd,p1); p6=gneg_i(gdiv(p4,p5));
2602: settyp(p14,t_REAL); settyp(p15,t_REAL);
1.2 ! noro 2603: gaffect(gadd(p1,p6),p1); avma=av2;
1.1 noro 2604: }
2605: }
2606: setlg(p14,l); setlg(p15,l);
2607: p7=gcopy(p1); p14=(GEN)(p7[1]); p15=(GEN)(p7[2]);
2608: setlg(p14,l+1); setlg(p15,l+1);
2609: if (gcmp0(p14)) { settyp(p14,t_INT); p14[1]=2; }
2610: if (gcmp0(p15)) { settyp(p15,t_INT); p15[1]=2; }
2611: for (ii=1; ii<=5; ii++)
2612: {
2613: p4=poleval(ps,p7); p5=poleval(xd0,p7);
2614: p6=gneg_i(gdiv(p4,p5)); p7=gadd(p7,p6);
2615: p14=(GEN)(p7[1]); p15=(GEN)(p7[2]);
2616: if (gcmp0(p14)) { settyp(p14,t_INT); p14[1]=2; }
2617: if (gcmp0(p15)) { settyp(p15,t_INT); p15[1]=2; }
2618: }
2619: gaffect(p7,p1); p4=poleval(ps,p7);
2620: p6=gdiv(p4,poleval(xdabs,gabs(p7,l)));
2621: if (gexpo(p6)>=expmin)
2622: {
1.2 ! noro 2623: avma=av;
1.1 noro 2624: if (DEBUGLEVEL)
2625: {
2626: fprintferr("internal error in rootsold(): using roots2()\n");
2627: flusherr();
2628: }
2629: return roots2(x,l);
2630: }
1.2 ! noro 2631: avma=av2;
1.1 noro 2632: if (expo(p1[2])<expmin && g)
2633: {
2634: gaffect(gzero,(GEN)p1[2]);
2635: for (j=1; j<m; j++) gaffect(p1,(GEN)y[k+(i-1)*m+j]);
2636: p11[2]=lneg((GEN)p1[1]);
1.2 ! noro 2637: xc=gerepileupto(av0, gdeuc(xc,p11));
1.1 noro 2638: }
2639: else
2640: {
2641: for (j=1; j<m; j++) gaffect(p1,(GEN)y[k+(i-1)*m+j]);
2642: if (g)
2643: {
2644: p1=gconj(p1);
2645: for (j=1; j<=m; j++) gaffect(p1,(GEN)y[k+i*m+j]);
2646: i++;
1.2 ! noro 2647: p12[2]=lnorm(p1); p12[3]=lmulsg(-2,(GEN)p1[1]);
! 2648: xc=gerepileupto(av0, gdeuc(xc,p12));
1.1 noro 2649: }
2650: else
2651: {
1.2 ! noro 2652: p11[2]=lneg(p1);
! 2653: xc=gerepileupto(av0, gdeuc(xc,p11));
1.1 noro 2654: }
2655: }
1.2 ! noro 2656: xd=deriv(xc,v); av2=avma;
1.1 noro 2657: }
2658: k += deg*m;
2659: }
2660: m++;
2661: }
2662: while (k!=deg0);
2663: }
1.2 ! noro 2664: avma=av1;
1.1 noro 2665: for (j=2; j<=deg0; j++)
2666: {
2667: p1 = (GEN)y[j];
2668: if (gcmp0((GEN)p1[2])) fr=0; else fr=1;
2669: for (k=j-1; k>=1; k--)
2670: {
2671: p2 = (GEN)y[k];
2672: if (gcmp0((GEN)p2[2])) f=0; else f=1;
2673: if (f<fr) break;
2674: if (f==fr && gcmp((GEN)p2[1],(GEN)p1[1]) <= 0) break;
2675: y[k+1]=y[k];
2676: }
2677: y[k+1]=(long)p1;
2678: }
2679: return y;
2680: }
2681:
2682: GEN
2683: roots2(GEN pol,long PREC)
2684: {
1.2 ! noro 2685: gpmem_t av = avma;
1.1 noro 2686: long N,flagexactpol,flagrealpol,flagrealrac,ti,i,j;
1.2 ! noro 2687: long nbpol, k, multiqol, deg, nbroot, fr, f;
! 2688: gpmem_t av1;
1.1 noro 2689: GEN p1,p2,rr,EPS,qol,qolbis,x,b,c,*ad,v,tabqol;
2690:
2691: if (typ(pol)!=t_POL) err(typeer,"roots2");
2692: if (!signe(pol)) err(zeropoler,"roots2");
2693: N=degpol(pol);
2694: if (!N) return cgetg(1,t_COL);
2695: if (N==1)
2696: {
2697: p1=gmul(realun(PREC),(GEN)pol[3]);
2698: p2=gneg_i(gdiv((GEN)pol[2],p1));
2699: return gerepilecopy(av,p2);
2700: }
1.2 ! noro 2701: EPS = real2n(12 - bit_accuracy(PREC), 3);
1.1 noro 2702: flagrealpol=1; flagexactpol=1;
2703: for (i=2; i<=N+2; i++)
2704: {
2705: ti=typ(pol[i]);
2706: if (ti!=t_INT && ti!=t_INTMOD && !is_frac_t(ti))
2707: {
2708: flagexactpol=0;
2709: if (ti!=t_REAL) flagrealpol=0;
2710: }
2711: if (ti==t_QUAD)
2712: {
2713: p1=gmael3(pol,i,1,2);
2714: flagrealpol = (gsigne(p1)>0)? 0 : 1;
2715: }
2716: }
2717: rr=cgetg(N+1,t_COL);
2718: for (i=1; i<=N; i++)
2719: {
2720: p1 = cgetc(PREC); rr[i] = (long)p1;
2721: for (j=3; j<PREC; j++) mael(p1,2,j)=mael(p1,1,j)=0;
2722: }
2723: if (flagexactpol) tabqol=square_free_factorization(pol);
2724: else
2725: {
2726: tabqol=cgetg(3,t_MAT);
2727: tabqol[1]=lgetg(2,t_COL); mael(tabqol,1,1)=un;
2728: tabqol[2]=lgetg(2,t_COL); mael(tabqol,2,1)=lcopy(pol);
2729: }
2730: nbpol=lg(tabqol[1])-1; nbroot=0;
2731: for (k=1; k<=nbpol; k++)
2732: {
2733: av1=avma; qol=gmael(tabqol,2,k); qolbis=gcopy(qol);
2734: multiqol=itos(gmael(tabqol,1,k)); deg=degpol(qol);
2735: for (j=deg; j>=1; j--)
2736: {
2737: x=gzero; flagrealrac=0;
2738: if (j==1) x=gneg_i(gdiv((GEN)qolbis[2],(GEN)qolbis[3]));
2739: else
2740: {
2741: x=laguer(qolbis,j,x,EPS,PREC);
2742: if (x == NULL) goto RLAB;
2743: }
2744: if (flagexactpol)
2745: {
2746: x=gprec(x,(long)((PREC-1)*pariK));
2747: x=laguer(qol,deg,x,gmul2n(EPS,-32),PREC+1);
2748: }
2749: else x=laguer(qol,deg,x,EPS,PREC);
2750: if (x == NULL) goto RLAB;
2751:
2752: if (typ(x)==t_COMPLEX &&
2753: gcmp(gabs(gimag(x),PREC),gmul2n(gmul(EPS,gabs(greal(x),PREC)),1))<=0)
2754: { x[2]=zero; flagrealrac=1; }
2755: else if (j==1 && flagrealpol)
2756: { x[2]=zero; flagrealrac=1; }
2757: else if (typ(x)!=t_COMPLEX) flagrealrac=1;
2758:
2759: for (i=1; i<=multiqol; i++) gaffect(x,(GEN)rr[nbroot+i]);
2760: nbroot+=multiqol;
2761: if (!flagrealpol || flagrealrac)
2762: {
2763: ad = (GEN*) new_chunk(j+1);
2764: for (i=0; i<=j; i++) ad[i]=(GEN)qolbis[i+2];
2765: b=(GEN)ad[j];
2766: for (i=j-1; i>=0; i--)
2767: {
2768: c=(GEN)ad[i]; ad[i]=b;
2769: b=gadd(gmul((GEN)rr[nbroot],b),c);
2770: }
2771: v=cgetg(j+1,t_VEC); for (i=1; i<=j; i++) v[i]=(long)ad[j-i];
2772: qolbis=gtopoly(v,varn(qolbis));
2773: if (flagrealpol)
2774: for (i=2; i<=j+1; i++)
2775: if (typ(qolbis[i])==t_COMPLEX) mael(qolbis,i,2)=zero;
2776: }
2777: else
2778: {
2779: ad = (GEN*) new_chunk(j-1); ad[j-2]=(GEN)qolbis[j+2];
2780: p1=gmulsg(2,greal((GEN)rr[nbroot])); p2=gnorm((GEN)rr[nbroot]);
2781: ad[j-3]=gadd((GEN)qolbis[j+1],gmul(p1,ad[j-2]));
2782: for (i=j-2; i>=2; i--)
2783: ad[i-2] = gadd((GEN)qolbis[i+2],gsub(gmul(p1,ad[i-1]),gmul(p2,ad[i])));
2784: v=cgetg(j,t_VEC); for (i=1; i<=j-1; i++) v[i]=(long)ad[j-1-i];
2785: qolbis=gtopoly(v,varn(qolbis));
2786: for (i=2; i<=j; i++)
2787: if (typ(qolbis[i])==t_COMPLEX) mael(qolbis,i,2)=zero;
2788: for (i=1; i<=multiqol; i++)
2789: gaffect(gconj((GEN)rr[nbroot]), (GEN)rr[nbroot+i]);
2790: nbroot+=multiqol; j--;
2791: }
2792: }
2793: avma=av1;
2794: }
2795: for (j=2; j<=N; j++)
2796: {
2797: x=(GEN)rr[j]; if (gcmp0((GEN)x[2])) fr=0; else fr=1;
2798: for (i=j-1; i>=1; i--)
2799: {
2800: if (gcmp0(gmael(rr,i,2))) f=0; else f=1;
2801: if (f<fr) break;
2802: if (f==fr && gcmp(greal((GEN)rr[i]),greal(x)) <= 0) break;
2803: rr[i+1]=rr[i];
2804: }
2805: rr[i+1]=(long)x;
2806: }
2807: return gerepilecopy(av,rr);
2808:
2809: RLAB:
2810: avma = av;
2811: for(i=2;i<=N+2;i++)
2812: {
2813: ti = typ(pol[i]);
2814: if (!is_intreal_t(ti)) err(talker,"too many iterations in roots");
2815: }
2816: if (DEBUGLEVEL)
2817: {
2818: fprintferr("too many iterations in roots2() ( laguer() ): \n");
2819: fprintferr(" real coefficients polynomial, using zrhqr()\n");
2820: flusherr();
2821: }
2822: return zrhqr(pol,PREC);
2823: }
2824:
2825: #define MR 8
2826: #define MT 10
2827:
2828: static GEN
2829: laguer(GEN pol,long N,GEN y0,GEN EPS,long PREC)
2830: {
1.2 ! noro 2831: long MAXIT, iter, j;
! 2832: gpmem_t av = avma, av1;
1.1 noro 2833: GEN rac,erre,I,x,abx,abp,abm,dx,x1,b,d,f,g,h,sq,gp,gm,g2,*ffrac;
2834:
1.2 ! noro 2835: MAXIT = MR*MT; rac = cgetc(PREC);
1.1 noro 2836: av1 = avma;
2837: I=cgetg(3,t_COMPLEX); I[1]=un; I[2]=un;
1.2 ! noro 2838: ffrac = (GEN*)new_chunk(MR+1);
! 2839: ffrac[0] = dbltor(0.0);
! 2840: ffrac[1] = dbltor(0.5);
! 2841: ffrac[2] = dbltor(0.25);
! 2842: ffrac[3] = dbltor(0.75);
! 2843: ffrac[4] = dbltor(0.13);
! 2844: ffrac[5] = dbltor(0.38);
! 2845: ffrac[6] = dbltor(0.62);
! 2846: ffrac[7] = dbltor(0.88);
! 2847: ffrac[8] = dbltor(1.0);
1.1 noro 2848: x=y0;
2849: for (iter=1; iter<=MAXIT; iter++)
2850: {
2851: b=(GEN)pol[N+2]; erre=QuickNormL1(b,PREC);
2852: d=gzero; f=gzero; abx=QuickNormL1(x,PREC);
2853: for (j=N-1; j>=0; j--)
2854: {
1.2 ! noro 2855: f = gadd(gmul(x,f),d);
! 2856: d = gadd(gmul(x,d),b);
! 2857: b = gadd(gmul(x,b), (GEN)pol[j+2]);
! 2858: erre = gadd(QuickNormL1(b,PREC), gmul(abx,erre));
1.1 noro 2859: }
1.2 ! noro 2860: erre = gmul(erre,EPS);
1.1 noro 2861: if (gcmp(QuickNormL1(b,PREC),erre)<=0)
2862: {
2863: gaffect(x,rac); avma = av1; return rac;
2864: }
2865: g=gdiv(d,b); g2=gsqr(g); h=gsub(g2, gmul2n(gdiv(f,b),1));
2866: sq=gsqrt(gmulsg(N-1,gsub(gmulsg(N,h),g2)),PREC);
2867: gp=gadd(g,sq); gm=gsub(g,sq); abp=gnorm(gp); abm=gnorm(gm);
2868: if (gcmp(abp,abm)<0) gp=gcopy(gm);
2869: if (gsigne(gmax(abp,abm))==1)
2870: dx = gdivsg(N,gp);
2871: else
2872: dx = gmul(gadd(gun,abx),gexp(gmulgs(I,iter),PREC));
2873: x1=gsub(x,dx);
2874: if (gcmp(QuickNormL1(gsub(x,x1),PREC),EPS)<0)
2875: {
2876: gaffect(x,rac); avma = av1; return rac;
2877: }
2878: if (iter%MT) x=gcopy(x1); else x=gsub(x,gmul(ffrac[iter/MT],dx));
2879: }
2880: avma=av; return NULL;
2881: }
2882:
2883: #undef MR
2884: #undef MT
2885:
2886: /***********************************************************************/
2887: /** **/
2888: /** ROOTS of a polynomial with REAL coeffs **/
2889: /** **/
2890: /***********************************************************************/
2891: #define RADIX 1L
2892: #define COF 0.95
2893:
2894: /* ONLY FOR REAL COEFFICIENTS MATRIX : replace the matrix x with
2895: a symmetric matrix a with the same eigenvalues */
2896: static GEN
2897: balanc(GEN x)
2898: {
1.2 ! noro 2899: gpmem_t av = avma;
1.1 noro 2900: long last,i,j, sqrdx = (RADIX<<1), n = lg(x);
2901: GEN r,c,cofgen,a;
2902:
2903: a = dummycopy(x);
2904: last = 0; cofgen = dbltor(COF);
2905: while (!last)
2906: {
2907: last = 1;
2908: for (i=1; i<n; i++)
2909: {
2910: r = c = gzero;
2911: for (j=1; j<n; j++)
2912: if (j!=i)
2913: {
2914: c = gadd(c, gabs(gcoeff(a,j,i),0));
2915: r = gadd(r, gabs(gcoeff(a,i,j),0));
2916: }
2917: if (!gcmp0(r) && !gcmp0(c))
2918: {
2919: GEN g, s = gmul(cofgen, gadd(c,r));
2920: long ex = 0;
2921: g = gmul2n(r,-RADIX); while (gcmp(c,g) < 0) {ex++; c=gmul2n(c, sqrdx);}
2922: g = gmul2n(r, RADIX); while (gcmp(c,g) > 0) {ex--; c=gmul2n(c,-sqrdx);}
2923: if (gcmp(gadd(c,r), gmul2n(s,ex)) < 0)
2924: {
2925: last = 0;
2926: for (j=1; j<n; j++) coeff(a,i,j)=lmul2n(gcoeff(a,i,j),-ex);
2927: for (j=1; j<n; j++) coeff(a,j,i)=lmul2n(gcoeff(a,j,i), ex);
2928: }
2929: }
2930: }
2931: }
2932: return gerepilecopy(av, a);
2933: }
2934:
2935: #define SIGN(a,b) ((b)>=0.0 ? fabs(a) : -fabs(a))
2936: static GEN
2937: hqr(GEN mat) /* find all the eigenvalues of the matrix mat */
2938: {
2939: long nn,n,m,l,k,j,its,i,mmin,flj,flk;
2940: double **a,p,q,r,s,t,u,v,w,x,y,z,anorm,*wr,*wi;
2941: const double eps = 0.000001;
2942: GEN eig;
2943:
2944: n=lg(mat)-1; a=(double**)gpmalloc(sizeof(double*)*(n+1));
2945: for (i=1; i<=n; i++) a[i]=(double*)gpmalloc(sizeof(double)*(n+1));
2946: for (j=1; j<=n; j++)
2947: for (i=1; i<=n; i++) a[i][j]=gtodouble((GEN)((GEN)mat[j])[i]);
2948: wr=(double*)gpmalloc(sizeof(double)*(n+1));
2949: wi=(double*)gpmalloc(sizeof(double)*(n+1));
2950:
2951: anorm=fabs(a[1][1]);
2952: for (i=2; i<=n; i++) for (j=(i-1); j<=n; j++) anorm+=fabs(a[i][j]);
1.2 ! noro 2953: nn=n; t=0.;
1.1 noro 2954: if (DEBUGLEVEL>3) { fprintferr("* Finding eigenvalues\n"); flusherr(); }
2955: while (nn>=1)
2956: {
2957: its=0;
2958: do
2959: {
2960: for (l=nn; l>=2; l--)
2961: {
1.2 ! noro 2962: s=fabs(a[l-1][l-1])+fabs(a[l][l]); if (s==0.) s=anorm;
1.1 noro 2963: if ((double)(fabs(a[l][l-1])+s)==s) break;
2964: }
2965: x=a[nn][nn];
1.2 ! noro 2966: if (l==nn){ wr[nn]=x+t; wi[nn--]=0.; }
1.1 noro 2967: else
2968: {
2969: y=a[nn-1][nn-1];
2970: w=a[nn][nn-1]*a[nn-1][nn];
2971: if (l == nn-1)
2972: {
2973: p=0.5*(y-x); q=p*p+w; z=sqrt(fabs(q)); x+=t;
1.2 ! noro 2974: if (q>=0. || fabs(q)<=eps)
1.1 noro 2975: {
2976: z=p+SIGN(z,p); wr[nn-1]=wr[nn]=x+z;
2977: if (fabs(z)>eps) wr[nn]=x-w/z;
1.2 ! noro 2978: wi[nn-1]=wi[nn]=0.;
1.1 noro 2979: }
2980: else{ wr[nn-1]=wr[nn]=x+p; wi[nn-1]=-(wi[nn]=z); }
2981: nn-=2;
2982: }
2983: else
2984: {
1.2 ! noro 2985: p = q = r = 0.; /* for lint */
1.1 noro 2986: if (its==30) err(talker,"too many iterations in hqr");
2987: if (its==10 || its==20)
2988: {
2989: t+=x; for (i=1; i<=nn; i++) a[i][i]-=x;
2990: s = fabs(a[nn][nn-1]) + fabs(a[nn-1][nn-2]);
2991: y=x=0.75*s; w=-0.4375*s*s;
2992: }
2993: its++;
2994: for (m=nn-2; m>=l; m--)
2995: {
2996: z=a[m][m]; r=x-z; s=y-z;
2997: p=(r*s-w)/a[m+1][m]+a[m][m+1];
2998: q=a[m+1][m+1]-z-r-s;
2999: r=a[m+2][m+1]; s=fabs(p)+fabs(q)+fabs(r); p/=s; q/=s; r/=s;
3000: if (m==l) break;
3001: u=fabs(a[m][m-1])*(fabs(q)+fabs(r));
3002: v=fabs(p)*(fabs(a[m-1][m-1])+fabs(z)+fabs(a[m+1][m+1]));
3003: if ((double)(u+v)==v) break;
3004: }
1.2 ! noro 3005: for (i=m+2; i<=nn; i++){ a[i][i-2]=0.; if (i!=(m+2)) a[i][i-3]=0.; }
1.1 noro 3006: for (k=m; k<=nn-1; k++)
3007: {
3008: if (k!=m)
3009: {
3010: p=a[k][k-1]; q=a[k+1][k-1];
1.2 ! noro 3011: r = (k != nn-1)? a[k+2][k-1]: 0.;
1.1 noro 3012: x = fabs(p)+fabs(q)+fabs(r);
1.2 ! noro 3013: if (x != 0.) { p/=x; q/=x; r/=x; }
1.1 noro 3014: }
3015: s = SIGN(sqrt(p*p+q*q+r*r),p);
1.2 ! noro 3016: if (s == 0.) continue;
1.1 noro 3017:
3018: if (k==m)
3019: { if (l!=m) a[k][k-1] = -a[k][k-1]; }
3020: else
3021: a[k][k-1] = -s*x;
3022: p+=s; x=p/s; y=q/s; z=r/s; q/=p; r/=p;
3023: for (j=k; j<=nn; j++)
3024: {
3025: p = a[k][j]+q*a[k+1][j];
3026: if (k != nn-1) { p+=r*a[k+2][j]; a[k+2][j]-=p*z; }
3027: a[k+1][j] -= p*y; a[k][j] -= p*x;
3028: }
3029: mmin = (nn < k+3)? nn: k+3;
3030: for (i=l; i<=mmin; i++)
3031: {
3032: p = x*a[i][k]+y*a[i][k+1];
3033: if (k != nn-1) { p+=z*a[i][k+2]; a[i][k+2]-=p*r; }
3034: a[i][k+1] -= p*q; a[i][k] -= p;
3035: }
3036: }
3037: }
3038: }
3039: }
3040: while (l<nn-1);
3041: }
3042: for (j=2; j<=n; j++) /* ordering the roots */
3043: {
1.2 ! noro 3044: x=wr[j]; y=wi[j]; if (y != 0.) flj=1; else flj=0;
1.1 noro 3045: for (k=j-1; k>=1; k--)
3046: {
1.2 ! noro 3047: if (wi[k] != 0.) flk=1; else flk=0;
1.1 noro 3048: if (flk<flj) break;
3049: if (!flk && !flj && wr[k]<=x) break;
3050: if (flk&&flj&& wr[k]<x) break;
3051: if (flk&&flj&& wr[k]==x && wi[k]>0) break;
3052: wr[k+1]=wr[k]; wi[k+1]=wi[k];
3053: }
3054: wr[k+1]=x; wi[k+1]=y;
3055: }
3056: if (DEBUGLEVEL>3) { fprintferr("* Eigenvalues computed\n"); flusherr(); }
3057: for (i=1; i<=n; i++) free(a[i]); free(a); eig=cgetg(n+1,t_COL);
3058: for (i=1; i<=n; i++)
3059: {
1.2 ! noro 3060: if (wi[i] != 0.)
1.1 noro 3061: {
3062: GEN p1 = cgetg(3,t_COMPLEX);
3063: eig[i]=(long)p1;
3064: p1[1]=(long)dbltor(wr[i]);
3065: p1[2]=(long)dbltor(wi[i]);
3066: }
3067: else eig[i]=(long)dbltor(wr[i]);
3068: }
3069: free(wr); free(wi); return eig;
3070: }
3071:
3072: /* ONLY FOR POLYNOMIAL WITH REAL COEFFICIENTS : give the roots of the
3073: * polynomial a (first, the real roots, then the non real roots) in
3074: * increasing order of their real parts MULTIPLE ROOTS ARE FORBIDDEN.
3075: */
3076: GEN
3077: zrhqr(GEN a,long prec)
3078: {
1.2 ! noro 3079: gpmem_t av = avma;
1.1 noro 3080: long i,j,prec2, n = degpol(a), ex = -bit_accuracy(prec);
3081: GEN aa,b,p1,rt,rr,hess,x,dx,y,newval,oldval;
3082:
1.2 ! noro 3083: hess = cgetg(n+1,t_MAT);
1.1 noro 3084: for (j=1; j<=n; j++)
3085: {
1.2 ! noro 3086: p1 = cgetg(n+1,t_COL); hess[j] = (long)p1;
1.1 noro 3087: p1[1] = lneg(gdiv((GEN)a[n-j+2],(GEN)a[n+2]));
3088: for (i=2; i<=n; i++) p1[i] = (i==(j+1))? un: zero;
3089: }
3090: rt = hqr(balanc(hess));
3091: prec2 = 2*prec; /* polishing the roots */
3092: aa = gprec_w(a, prec2);
3093: b = derivpol(aa); rr = cgetg(n+1,t_COL);
3094: for (i=1; i<=n; i++)
3095: {
3096: x = gprec_w((GEN)rt[i], prec2);
3097: for (oldval=NULL;; oldval=newval, x=y)
3098: { /* Newton iteration */
3099: dx = poleval(b,x);
3100: if (gexpo(dx) < ex)
3101: err(talker,"polynomial has probably multiple roots in zrhqr");
3102: y = gsub(x, gdiv(poleval(aa,x),dx));
3103: newval = gabs(poleval(aa,y),prec2);
3104: if (gexpo(newval) < ex || (oldval && gcmp(newval,oldval) > 0)) break;
3105: }
3106: if (DEBUGLEVEL>3) fprintferr("%ld ",i);
3107: rr[i] = (long)cgetc(prec); gaffect(y, (GEN)rr[i]);
3108: }
3109: if (DEBUGLEVEL>3) { fprintferr("\npolished roots = %Z",rr); flusherr(); }
3110: return gerepilecopy(av, rr);
3111: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>