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