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