Annotation of OpenXM_contrib/pari/src/basemath/polarit2.c, Revision 1.1
1.1 ! maekawa 1: /***********************************************************************/
! 2: /** **/
! 3: /** ARITHMETIC OPERATIONS ON POLYNOMIALS **/
! 4: /** (second part) **/
! 5: /** **/
! 6: /***********************************************************************/
! 7: /* $Id: polarit2.c,v 1.2 1999/09/20 13:30:05 karim Exp $ */
! 8: #include "pari.h"
! 9:
! 10: GEN
! 11: polsym(GEN x, long n)
! 12: {
! 13: long av1,av2,dx=lgef(x)-3,i,k;
! 14: GEN s,y,x_lead;
! 15:
! 16: if (n<0) err(impl,"polsym of a negative n");
! 17: if (typ(x) != t_POL) err(typeer,"polsym");
! 18: if (!signe(x)) err(zeropoler,"polsym");
! 19: y=cgetg(n+2,t_COL); y[1]=lstoi(dx);
! 20: x_lead=(GEN)x[dx+2]; if (gcmp1(x_lead)) x_lead=NULL;
! 21: for (k=1; k<=n; k++)
! 22: {
! 23: av1=avma; s = (dx>=k)? gmulsg(k,(GEN)x[dx+2-k]): gzero;
! 24: for (i=1; i<k && i<=dx; i++)
! 25: s = gadd(s,gmul((GEN)y[k-i+1],(GEN)x[dx+2-i]));
! 26: if (x_lead) s = gdiv(s,x_lead);
! 27: av2=avma; y[k+1]=lpile(av1,av2,gneg(s));
! 28: }
! 29: return y;
! 30: }
! 31:
! 32: static int (*polcmp_coeff_cmp)(GEN,GEN);
! 33:
! 34: /* assume x and y are polynomials in the same variable whose coeffs can be
! 35: * compared (used to sort polynomial factorizations)
! 36: */
! 37: static int
! 38: polcmp(GEN x, GEN y)
! 39: {
! 40: long i, lx = lgef(x), ly = lgef(y);
! 41: int fl;
! 42: #if 0 /* for efficiency */
! 43: if (typ(x) != t_POL || typ(y) != t_POL)
! 44: err(talker,"not a polynomial in polcmp");
! 45: #endif
! 46: if (lx > ly) return 1;
! 47: if (lx < ly) return -1;
! 48: for (i=lx-1; i>1; i--)
! 49: if ((fl = polcmp_coeff_cmp((GEN)x[i], (GEN)y[i]))) return fl;
! 50: return 0;
! 51: }
! 52:
! 53: /* sort factorization so that factors appear by decreasing degree, in place */
! 54: GEN
! 55: sort_factor(GEN y, int (*cmp)(GEN,GEN))
! 56: {
! 57: GEN w,c1,c2, p1 = (GEN)y[1], p2 = (GEN)y[2];
! 58: long av=avma, n=lg(p1), i;
! 59: int (*old)(GEN,GEN) = polcmp_coeff_cmp;
! 60:
! 61: c1 = new_chunk(n); c2 = new_chunk(n);
! 62: polcmp_coeff_cmp = cmp;
! 63: w = gen_sort(p1, cmp_IND | cmp_C, polcmp);
! 64: for (i=1; i<n; i++) { c1[i]=p1[w[i]]; c2[i]=p2[w[i]]; }
! 65: for (i=1; i<n; i++) { p1[i]=c1[i]; p2[i]=c2[i]; }
! 66: polcmp_coeff_cmp = old; avma = av; return y;
! 67: }
! 68:
! 69: /* for internal use */
! 70: GEN
! 71: centermod(GEN x, GEN p)
! 72: {
! 73: long av,i,lx;
! 74: GEN y,p1,ps2;
! 75:
! 76: ps2=shifti(p,-1);
! 77: switch(typ(x))
! 78: {
! 79: case t_INT:
! 80: y=modii(x,p);
! 81: if (cmpii(y,ps2)>0) return subii(y,p);
! 82: return y;
! 83:
! 84: case t_POL: lx=lgef(x);
! 85: y=cgetg(lx,t_POL); y[1]=x[1];
! 86: for (i=2; i<lx; i++)
! 87: {
! 88: av=avma; p1=modii((GEN)x[i],p);
! 89: if (cmpii(p1,ps2)>0) p1=subii(p1,p);
! 90: y[i]=lpileupto(av,p1);
! 91: }
! 92: return y;
! 93:
! 94: case t_COL: lx=lg(x);
! 95: y=cgetg(lx,t_COL);
! 96: for (i=1; i<lx; i++)
! 97: {
! 98: p1=modii((GEN)x[i],p);
! 99: if (cmpii(p1,ps2)>0) p1=subii(p1,p);
! 100: y[i]=(long)p1;
! 101: }
! 102: return y;
! 103: }
! 104: return x;
! 105: }
! 106:
! 107: static GEN
! 108: decpol(GEN x, long klim)
! 109: {
! 110: short int pos[200];
! 111: long av=avma,av1,tete,k,kin,i,j,i1,i2,fl,d,nbfact;
! 112: GEN res,p1,p2;
! 113:
! 114: kin=1; res=cgetg(lgef(x)-2,t_VEC); nbfact=0;
! 115: p1=roots(x,DEFAULTPREC); d=lg(p1)-1; if (!klim) klim=d;
! 116: do
! 117: {
! 118: fl=1;
! 119: for (k=kin; k+k <= d && k<=klim; k++)
! 120: {
! 121: for (i=0; i<=k; i++) pos[i]=i;
! 122: do
! 123: {
! 124: av1=avma; p2=gzero; j=0;
! 125: for (i1=1; i1<=k; i1++) p2=gadd(p2,(GEN)p1[pos[i1]]);
! 126: if (gexpo(gimag(p2))<-20 && gexpo(gsub(p2,ground(p2)))<-20)
! 127: {
! 128: p2=gun;
! 129: for (i1=1; i1<=k; i1++)
! 130: p2=gmul(p2,gsub(polx[0],(GEN)p1[pos[i1]]));
! 131: p2 = ground(p2);
! 132: if (gcmp0(gimag(p2)) && gcmp0(gmod(x,p2)))
! 133: {
! 134: res[++nbfact]=(long)p2; x=gdiv(x,p2);
! 135: kin=k; p2=cgetg(d-k+1,t_COL);
! 136: for (i=i1=i2=1; i<=d; i++)
! 137: {
! 138: if (i1<=k && i==pos[i1]) i1++;
! 139: else p2[i2++]=p1[i];
! 140: }
! 141: p1=p2; d-=k; fl=0; break;
! 142: }
! 143: }
! 144: avma=av1; pos[k]++;
! 145: while (pos[k-j] > d-j) { j++; pos[k-j]++; }
! 146: for (i=k-j+1; i<=k; i++) pos[i]=i+pos[k-j]-k+j;
! 147: }
! 148: while (j<k);
! 149: if (!fl) break;
! 150: }
! 151: if (lgef(x)<=3) break;
! 152: }
! 153: while (!fl || (k+k <= d && k<=klim));
! 154: if (lgef(x)>3) res[++nbfact]=(long)x;
! 155: setlg(res,nbfact+1); tete=avma;
! 156: return gerepile(av,tete,greal(res));
! 157: }
! 158:
! 159: /* This code originally by Richard Schroeppel */
! 160:
! 161: /* Note that PARI's idea of the maximum possible coefficient involves the
! 162: * limit on the degree (klim). Consider revising this. If I don't respect
! 163: * the degree limit when testing potential factors, there's the possibility
! 164: * that I might identify a high degree factor that isn't irreducible, because
! 165: * it's lower degree divisors were missed because they had a coefficient
! 166: * outside the Borne limit for klim, but the higher degree factor had it's
! 167: * coefficients within Borne. This would still have the property that any
! 168: * factors of degree <= klim were guaranteed irr, but higher degrees
! 169: * (> 2*klim) might not be irr.
! 170: *
! 171: * The subroutine:
! 172: * fxn points at the first unconsidered factor for the current combination
! 173: * psf is the product-so-far, or 0 for a null product
! 174: * dlim is the degree limit remaining for unconsidered divisors
! 175: * other arguments are "global" and must already be setup
! 176: * as factors are found, they are put in cmbf_fax; the count is kept in
! 177: * cmbf_faxn; and they are divided out of cmbf_target; the degree and
! 178: * leading coefficient are updated; and the constituent modular factors
! 179: * are deleted from cmbf_modfax.
! 180: * exit value is 1 if any factors are found.
! 181: * If psf is 0, all factors made up from pieces at or after fxn will be
! 182: * found & removed. If psf is not 0, only the factor which is a
! 183: * continuation of psf will be found.
! 184: */
! 185: /* setup for calling cmbf = combine_factors */
! 186: static GEN cmbf_target; /* target poly. Assume content removed */
! 187: static GEN cmbf_lc; /* leading coefficient */
! 188: static GEN cmbf_abslc; /* |lc| */
! 189: static GEN cmbf_abslcxtarget;/* abslc * target */
! 190: static GEN cmbf_mod; /* modulus */
! 191: static GEN cmbf_fax; /* result array + one cell for leftover cst. */
! 192: static GEN cmbf_modfax; /* array of modular factors. Each has LC 1.1 based
! 193: indexing. Product should be congruent to a/lc(a). */
! 194: static long cmbf_degree; /* degree(target) */
! 195: static long cmbf_modfaxn; /* number of modular factors */
! 196: static long cmbf_faxn; /* last used cell in fax. # of factors found */
! 197: static GEN cmbf_modhalf;
! 198:
! 199: /* assume same variables, y normalized, non constant */
! 200: static GEN
! 201: polidivis(GEN x, GEN y, GEN bound)
! 202: {
! 203: long dx,dy,dz,i,j,av, vx = varn(x);
! 204: GEN z,p1,y_lead;
! 205:
! 206: dy=lgef(y)-3;
! 207: dx=lgef(x)-3;
! 208: dz=dx-dy; if (dz<0) return NULL;
! 209: z=cgetg(dz+3,t_POL);
! 210: x += 2; y += 2; z += 2;
! 211: y_lead = (GEN)y[dy];
! 212: if (gcmp1(y_lead)) y_lead = NULL;
! 213:
! 214: p1 = (GEN)x[dx];
! 215: z[dz]=y_lead? ldivii(p1,y_lead): licopy(p1);
! 216: for (i=dx-1; i>=dy; i--)
! 217: {
! 218: av=avma; p1=(GEN)x[i];
! 219: for (j=i-dy+1; j<=i && j<=dz; j++)
! 220: p1 = subii(p1, mulii((GEN)z[j],(GEN)y[i-j]));
! 221: if (y_lead) { p1 = gdiv(p1,y_lead); if (typ(p1)!=t_INT) return NULL; }
! 222: if (absi_cmp(p1, bound) > 0) return NULL;
! 223: p1 = gerepileupto(av,p1);
! 224: z[i-dy] = (long)p1;
! 225: }
! 226: av = avma;
! 227: for (;; i--)
! 228: {
! 229: p1 = (GEN)x[i];
! 230: /* we always enter this loop at least once */
! 231: for (j=0; j<=i && j<=dz; j++)
! 232: p1 = subii(p1, mulii((GEN)z[j],(GEN)y[i-j]));
! 233: if (!gcmp0(p1)) return NULL;
! 234: avma = av;
! 235: if (!i) break;
! 236: }
! 237: z -= 2;
! 238: z[1]=evalsigne(1) | evallgef(dz+3) | evalvarn(vx);
! 239: return z;
! 240: }
! 241:
! 242: static int
! 243: try_div(GEN x, GEN y, GEN *q)
! 244: {
! 245: if (resii((GEN)x[2], (GEN)y[2]) != gzero)
! 246: {
! 247: if (DEBUGLEVEL>6) fprintferr(".");
! 248: return 0;
! 249: }
! 250: *q = polidivis(x,y,cmbf_modhalf);
! 251: if (*q) return 1;
! 252: if (DEBUGLEVEL>6) fprintferr("*");
! 253: return 0;
! 254: }
! 255:
! 256: static int
! 257: cmbf(long fxn, GEN psf, long dlim, long hint)
! 258: {
! 259: long newd,av,val2,val=0; /* assume failure */
! 260: GEN newf,newpsf,quo,cont;
! 261:
! 262: if (dlim <= 0 || fxn > cmbf_modfaxn) return 0;
! 263:
! 264: /* first, try deeper factors without considering the current one */
! 265: if (fxn < cmbf_modfaxn)
! 266: {
! 267: val = cmbf(fxn+1,psf,dlim,hint);
! 268: if (val && psf) return val;
! 269: }
! 270:
! 271: /* second, try including the current modular factor in the product */
! 272: newf = (GEN)cmbf_modfax[fxn];
! 273: if (!newf) return val; /* modular factor already used */
! 274:
! 275: newd = lgef(newf)-3; if (newd > dlim) return val;
! 276: av = avma;
! 277: if (!(newd%hint))
! 278: {
! 279: if (!psf) psf = cmbf_abslc;
! 280: newpsf = centermod(gmul(psf,newf),cmbf_mod);
! 281:
! 282: /* try out the new combination */
! 283: if (try_div(cmbf_abslcxtarget, newpsf, &quo))
! 284: {
! 285: /* found a factor */
! 286: cont = content(newpsf);
! 287: if (signe(leading_term(newpsf)) < 0) cont = negi(cont);
! 288: newpsf = gdiv(newpsf,cont);
! 289: cmbf_fax[++cmbf_faxn] = (long)newpsf; /* store factor */
! 290: cmbf_modfax[fxn] = 0; /* remove used modular factor */
! 291: if (DEBUGLEVEL > 2)
! 292: { fprintferr("\n"); msgtimer("to find factor %Z",newpsf); }
! 293: /* fix up target */
! 294: cmbf_target = gdiv(quo,leading_term(newpsf));
! 295: cmbf_degree = lgef(cmbf_target)-3;
! 296: cmbf_lc = (GEN)cmbf_target[cmbf_degree+2];
! 297: cmbf_abslc = absi(cmbf_lc);
! 298: cmbf_abslcxtarget = gmul(cmbf_abslc,cmbf_target);
! 299: return 1;
! 300: }
! 301: }
! 302: /* degree too large, or no more modular factors? */
! 303: if (newd == dlim || fxn == cmbf_modfaxn) return val;
! 304: /* include more factors */
! 305: val2 = cmbf(fxn+1,newpsf,dlim-newd,hint);
! 306: if (val2) cmbf_modfax[fxn] = 0; /* remove used modular factor */
! 307: else avma = av;
! 308: return val || val2;
! 309: }
! 310:
! 311: static long
! 312: min_deg(long jmax,ulong tabbit[])
! 313: {
! 314: long j,k=1,j1=2;
! 315:
! 316: for (j=jmax; j>=0; j--)
! 317: {
! 318: for ( ; k<=15; k++)
! 319: {
! 320: if (tabbit[j]&j1) return ((jmax-j)<<4)+k;
! 321: j1<<=1;
! 322: }
! 323: k=0; j1=1;
! 324: }
! 325: return (jmax<<4)+15;
! 326: }
! 327:
! 328: static void
! 329: dotab(long d,long jmax,ulong *tabkbit,ulong *tmp)
! 330: {
! 331: ulong rem,pro;
! 332: long j,d1,d2;
! 333:
! 334: d1=d>>4; d2=d&15; rem=0;
! 335: for (j=jmax-d1; j>=0; j--)
! 336: {
! 337: pro = tabkbit[j+d1]<<d2;
! 338: tmp[j] = (pro&0xffff)+rem; rem=pro>>16;
! 339: }
! 340: for (j=jmax-d1; j>=0; j--) tabkbit[j] |= tmp[j];
! 341: }
! 342:
! 343: /* lift factorisation mod p to mod p^e = pev */
! 344: GEN
! 345: hensel_lift_fact(GEN pol, GEN fact, GEN p, GEN pev, long e)
! 346: {
! 347: long ev,i, nf = lg(fact);
! 348: GEN aprov = pol, res = cgetg(nf, t_VEC);
! 349:
! 350: for (i=nf-1; i; i--)
! 351: {
! 352: GEN ae,be,u,v,ae2,be2,s,t,pe,pe2,z,g;
! 353: long ltop = avma;
! 354:
! 355: ae = (GEN)fact[i]; /* lead coeff(ae) = 1 */
! 356: be = Fp_poldivres(aprov,ae,p, NULL);
! 357: g = (GEN)Fp_pol_extgcd(ae,be,p,&u,&v)[2]; /* deg g = 0 */
! 358: if (!gcmp1(g))
! 359: {
! 360: g = mpinvmod(g, p);
! 361: u = gmul(u, g);
! 362: v = gmul(v, g);
! 363: }
! 364: for(pe=p,ev=1;;)
! 365: {
! 366: ev<<=1; pe2=(ev>=e)? pev: sqri(pe);
! 367: g = gadd(aprov, gneg_i(gmul(ae,be)));
! 368:
! 369: g = Fp_pol_red(g, pe2); g = gdivexact(g, pe);
! 370: z = Fp_pol_red(gmul(v,g), pe);
! 371: t = Fp_poldivres(z,ae,pe, &s);
! 372: t = gadd(gmul(u,g), gmul(t,be));
! 373: t = Fp_pol_red(t, pe);
! 374: be2 = gadd(be, gmul(t,pe));
! 375: ae2 = gadd(ae, gmul(s,pe)); /* already reduced mod pe2 */
! 376: if (ev>=e) break;
! 377:
! 378: g = gadd(gun, gneg_i(gadd(gmul(u,ae2),gmul(v,be2))));
! 379:
! 380: g = Fp_pol_red(g, pe2); g = gdivexact(g, pe);
! 381: z = Fp_pol_red(gmul(v,g), pe);
! 382: t = Fp_poldivres(z,ae,pe, &s);
! 383: t = gadd(gmul(u,g), gmul(t,be));
! 384: t = Fp_pol_red(t, pe);
! 385: u = gadd(u, gmul(t,pe));
! 386: v = gadd(v, gmul(s,pe));
! 387: pe=pe2; ae=ae2; be=be2;
! 388: }
! 389: ae = gerepileupto(ltop, ae2);
! 390: aprov = Fp_poldivres(aprov,ae,pev, NULL);
! 391: ltop = avma;
! 392: res[i] = (long)ae;
! 393: if (DEBUGLEVEL > 4)
! 394: fprintferr("...lifting factor of degree %3ld. Time = %ld\n",
! 395: lgef(ae)-3,timer2());
! 396: }
! 397: return res;
! 398: }
! 399:
! 400: long split_berlekamp(GEN Q, GEN *t, GEN pp, GEN pps2);
! 401:
! 402: /* assume degree(a) > 0, a(0) != 0, and a squarefree */
! 403: static GEN
! 404: squff(GEN a, long klim, long hint)
! 405: {
! 406: GEN Q,prime,primes2,factorsmodp,p1,p2,y,g,z,w,pe,*tabd,*tabdnew;
! 407: long av=avma,tetpil,va=varn(a),da=lgef(a)-3;
! 408: long chosenp,p,nfacp,lbit,i,j,d,e,np,nmax,lgg,nf,nft;
! 409: ulong *tabbit, *tabkbit, *tmp;
! 410: byteptr pt=diffptr;
! 411: const int NOMBDEP = 5;
! 412:
! 413: if (hint < 0) return decpol(a,klim);
! 414: if (DEBUGLEVEL > 2) timer2();
! 415: lbit=(da>>4)+1; nmax=da+1; i=da>>1;
! 416: if (!klim || klim>i) klim=i;
! 417: tabdnew = (GEN*)new_chunk(nmax);
! 418: tabbit = (ulong*)new_chunk(lbit);
! 419: tabkbit = (ulong*)new_chunk(lbit);
! 420: tmp = (ulong*)new_chunk(lbit);
! 421: p = np = 0; prime = icopy(gun);
! 422: while (np < NOMBDEP)
! 423: {
! 424: GEN minuspolx;
! 425: p += *pt++; if (!*pt) err(primer1);
! 426: if (!smodis((GEN)a[da+2],p)) continue;
! 427: prime[2] = p; z = Fp_pol(a, prime);
! 428: if (gcmp0(discsr(z))) continue;
! 429: z = lift_intern(z);
! 430:
! 431: for (j=0; j<lbit-1; j++) tabkbit[j]=0;
! 432: tabkbit[j]=1;
! 433: d=0; e=da; nfacp=0;
! 434: w = polx[va]; minuspolx = gneg(w);
! 435: while (d < (e>>1))
! 436: {
! 437: d++; w = Fp_pow_mod_pol(w, prime, z, prime);
! 438: g = Fp_pol_gcd(z, gadd(w, minuspolx), prime);
! 439: tabdnew[d]=g; lgg=lgef(g)-3;
! 440: if (lgg>0)
! 441: {
! 442: z = Fp_poldivres(z, g, prime, NULL);
! 443: e = lgef(z)-3;
! 444: w = Fp_poldivres(w, z, prime, ONLY_REM);
! 445: lgg /= d; nfacp += lgg;
! 446: if (DEBUGLEVEL>5)
! 447: fprintferr(" %3ld %s of degree %3ld\n",
! 448: lgg, lgg==1?"factor": "factors",d);
! 449: for (j=1; j<=lgg; j++) dotab(d,lbit-1,tabkbit,tmp);
! 450: }
! 451: }
! 452: if (e>0)
! 453: {
! 454: if (DEBUGLEVEL>5)
! 455: fprintferr(" %3ld factor of degree %3ld\n",1,e);
! 456: tabdnew[e]=z; nfacp++;
! 457: dotab(e,lbit-1,tabkbit,tmp);
! 458: }
! 459: if (np)
! 460: for (j=0; j<lbit; j++) tabbit[j] &= tabkbit[j];
! 461: else
! 462: for (j=0; j<lbit; j++) tabbit[j] = tabkbit[j];
! 463: if (DEBUGLEVEL > 4)
! 464: fprintferr("...tried prime %3ld (%-3ld %s). Time = %ld\n",
! 465: p,nfacp,nfacp==1?"factor": "factors",timer2());
! 466: if (min_deg(lbit-1,tabbit) > klim)
! 467: {
! 468: avma=av; y=cgetg(2,t_COL); y[1]=lcopy(a); return y;
! 469: }
! 470: if (nfacp<nmax)
! 471: {
! 472: nmax=nfacp; tabd=tabdnew; chosenp=p;
! 473: for (j=d+1; j<e; j++) tabd[j]=polun[va];
! 474: tabdnew = (GEN*)new_chunk(da);
! 475: }
! 476: np++;
! 477: }
! 478: prime[2]=chosenp; primes2 = shifti(prime, -1);
! 479: nf=nmax; nft=1;
! 480: y=cgetg(nf+1,t_COL); factorsmodp=cgetg(nf+1,t_COL);
! 481: Q = cgetg(da+1,t_MAT);
! 482: for (i=1; i<=da; i++) Q[i] = lgetg(da+1, t_COL);
! 483: p1 = (GEN)Q[1]; for (i=1; i<=da; i++) p1[i] = zero;
! 484: for (d=1; nft<=nf; d++)
! 485: {
! 486: g=tabd[d]; lgg=lgef(g)-3;
! 487: if (lgg)
! 488: {
! 489: long n = lgg/d;
! 490: factorsmodp[nft] = (long)normalize_mod_p(g, prime);
! 491: if (n==1) nft++;
! 492: else
! 493: {
! 494: (void)split_berlekamp(Q, (GEN*)(factorsmodp+nft),prime,primes2);
! 495: nft += n;
! 496: }
! 497: }
! 498: }
! 499: if (DEBUGLEVEL > 4) msgtimer("splitting mod p = %ld",chosenp);
! 500:
! 501: p1=gzero; for (i=2; i<=da+2; i++) p1=addii(p1,sqri((GEN)a[i]));
! 502: p2=absi((GEN)a[da+2]);
! 503: p1=addii(p2,addsi(1,racine(p1)));
! 504: p1=mulii(p1,binome(stoi(da-1),klim));
! 505: p1=shifti(mulii(p2,p1),1);
! 506: for (e=1,pe=gun; ; e++)
! 507: {
! 508: pe = mulis(pe,chosenp);
! 509: if (cmpii(pe,p1) >= 0) break;
! 510: }
! 511: if (DEBUGLEVEL > 4) fprintferr("coeff bound: %Z\n",p1);
! 512:
! 513: cmbf_target = a;
! 514: cmbf_degree = lgef(a)-3;
! 515: cmbf_lc = (GEN)a[lgef(a)-1];
! 516: cmbf_abslc = absi(cmbf_lc);
! 517: cmbf_abslcxtarget = gmul(cmbf_abslc,a);
! 518: cmbf_mod = pe;
! 519: cmbf_modhalf = shifti(pe,-1);
! 520: cmbf_modfax = hensel_lift_fact(a,factorsmodp,prime,pe,e);
! 521: cmbf_modfaxn = nf;
! 522: cmbf_fax = cgetg(nf+2,t_COL);
! 523: cmbf_faxn = 0;
! 524: /* sorting factors decreasing by degree helps if klim is used
! 525: * If not, can start with first arg of 2 instead of 1, saving some time.
! 526: * Should be sending tabbit through for more efficiency ???
! 527: */
! 528: cmbf(1,NULL,klim,hint); /* The Call */
! 529: if (cmbf_degree)
! 530: {
! 531: if (signe(cmbf_lc)<0) cmbf_target = gneg_i(cmbf_target);
! 532: cmbf_fax[++cmbf_faxn] = (long)cmbf_target; /* leftover factor */
! 533: }
! 534: if (DEBUGLEVEL>6) fprintferr("\n");
! 535: tetpil=avma; y=cgetg(cmbf_faxn+1,t_COL);
! 536: for (i=1; i<=cmbf_faxn; i++) y[i]=lcopy((GEN)cmbf_fax[i]);
! 537: return gerepile(av,tetpil,y);
! 538: }
! 539:
! 540: /* klim=0 habituellement, sauf si l'on ne veut chercher que les facteurs
! 541: * de degre <= klim
! 542: */
! 543: GEN
! 544: factpol(GEN x, long klim, long hint)
! 545: {
! 546: GEN fa,p1,d,t,v,w, y = cgetg(3,t_MAT);
! 547: long av=avma,av2,lx,vx,i,j,k,ex,nbfac,zval;
! 548:
! 549: if (typ(x)!=t_POL) err(notpoler,"factpol");
! 550: if (!signe(x)) err(zeropoler,"factpol");
! 551:
! 552: ex = nbfac = 0;
! 553: p1 = x+2; while (gcmp0((GEN)*p1)) p1++;
! 554: zval = p1 - (x + 2);
! 555: lx = lgef(x) - zval;
! 556: vx = varn(x);
! 557: if (zval)
! 558: {
! 559: x = cgetg(lx, t_POL); p1 -= 2;
! 560: for (i=2; i<lx; i++) x[i] = p1[i];
! 561: x[1] = evalsigne(1)|evalvarn(vx)|evallgef(lx);
! 562: nbfac++;
! 563: }
! 564: /* now x(0) != 0 */
! 565: if (lx==3) goto END;
! 566: p1 = cgetg(1,t_VEC); fa=cgetg(lx,t_VEC);
! 567: for (i=1; i<lx; i++) fa[i] = (long)p1;
! 568: d=content(x); if (gsigne(leading_term(x)) < 0) d = gneg_i(d);
! 569: if (!gcmp1(d)) x=gdiv(x,d);
! 570: if (lx==4) { nbfac++; ex++; fa[1] = (long)concatsp(p1,x); goto END; }
! 571:
! 572: w=derivpol(x); t=modulargcd(x,w);
! 573: if (!gcmp1(t)) { x=gdeuc(x,t); w=gdeuc(w,t); }
! 574: k=1;
! 575: while (k)
! 576: {
! 577: ex++; w=gadd(w, gneg_i(derivpol(x))); k=signe(w);
! 578: if (k) { t=modulargcd(x,w); x=gdeuc(x,t); w=gdeuc(w,t); } else t=x;
! 579: if (lgef(t) > 3)
! 580: {
! 581: fa[ex] = (long)squff(t,klim,hint);
! 582: nbfac += lg(fa[ex])-1;
! 583: }
! 584: }
! 585: END: av2=avma;
! 586: v=cgetg(nbfac+1,t_COL); y[1]=(long)v;
! 587: w=cgetg(nbfac+1,t_COL); y[2]=(long)w;
! 588: if (zval) { v[1]=lpolx[vx]; w[1]=lstoi(zval); k=1; } else k=0;
! 589: for (i=1; i<=ex; i++)
! 590: for (j=1; j<lg(fa[i]); j++)
! 591: {
! 592: k++; v[k]=lcopy(gmael(fa,i,j)); w[k]=lstoi(i);
! 593: }
! 594: gerepilemanyvec(av,av2,y+1,2);
! 595: return sort_factor(y, cmpii);
! 596: }
! 597:
! 598: GEN
! 599: factpol2(GEN x, long klim)
! 600: {
! 601: return factpol(x,klim,-1);
! 602: }
! 603:
! 604: /***********************************************************************/
! 605: /** **/
! 606: /** FACTORISATION **/
! 607: /** **/
! 608: /***********************************************************************/
! 609: #define LT 17
! 610: #define assign_or_fail(x,y) {\
! 611: if (y==NULL) y=x; else if (!gegal(x,y)) return 0;\
! 612: }
! 613: #define tsh 6
! 614: #define typs(x,y) ((x << tsh) | y)
! 615: #define typ1(x) (x >> tsh)
! 616: #define typ2(x) (x & ((1<<tsh)-1))
! 617:
! 618: static long
! 619: poltype(GEN x, GEN *ptp, GEN *ptpol, long *ptpa)
! 620: {
! 621: long t[LT]; /* code pour 0,1,2,3,61,62,63,67,7,81,82,83,86,87,91,93,97 */
! 622: long tx = typ(x),lx,i,j,s,pa=BIGINT;
! 623: GEN pcx=NULL, p=NULL,pol=NULL,p1,p2;
! 624:
! 625: if (is_scalar_t(tx))
! 626: {
! 627: if (tx == t_POLMOD) return 0;
! 628: x = scalarpol(x,0);
! 629: }
! 630: for (i=2; i<LT; i++) t[i]=0; /* t[0..1] unused */
! 631: lx = lgef(x);
! 632: for (i=2; i<lx; i++)
! 633: {
! 634: p1=(GEN)x[i];
! 635: switch(typ(p1))
! 636: {
! 637: case t_INT: case t_FRAC: case t_FRACN:
! 638: break;
! 639: case t_REAL:
! 640: s = precision(p1); if (s < pa) pa = s;
! 641: t[2]=1; break;
! 642: case t_INTMOD:
! 643: assign_or_fail((GEN)p1[1],p);
! 644: t[3]=1; break;
! 645: case t_COMPLEX:
! 646: if (!pcx)
! 647: {
! 648: pcx = cgetg(5,t_POL); /* x^2 + 1 */
! 649: pcx[1] = evalsigne(1)|evalvarn(0)|m_evallgef(5),
! 650: pcx[2]=pcx[4]=un; pcx[3]=zero;
! 651: }
! 652: for (j=1; j<=2; j++)
! 653: {
! 654: p2 = (GEN)p1[j];
! 655: switch(typ(p2))
! 656: {
! 657: case t_INT: case t_FRAC: case t_FRACN:
! 658: assign_or_fail(pcx,pol);
! 659: t[4]=1; break;
! 660: case t_REAL:
! 661: s = precision(p2); if (s < pa) pa = s;
! 662: t[5]=1; break;
! 663: case t_INTMOD:
! 664: assign_or_fail((GEN)p2[1],p);
! 665: assign_or_fail(pcx,pol);
! 666: t[6]=1; break;
! 667: case t_PADIC:
! 668: s = precp(p2) + valp(p2); if (s < pa) pa = s;
! 669: assign_or_fail((GEN)p2[2],p);
! 670: assign_or_fail(pcx,pol);
! 671: t[7]=1; break;
! 672: default: return 0;
! 673: }
! 674: }
! 675: break;
! 676: case t_PADIC:
! 677: s = precp(p1) + valp(p1); if (s < pa) pa = s;
! 678: assign_or_fail((GEN)p1[2],p);
! 679: t[8]=1; break;
! 680: case t_QUAD:
! 681: for (j=2; j<=3; j++)
! 682: {
! 683: p2 = (GEN)p1[j];
! 684: switch(typ(p2))
! 685: {
! 686: case t_INT: case t_FRAC: case t_FRACN:
! 687: assign_or_fail((GEN)p1[1],pol);
! 688: t[9]=1; break;
! 689: case t_REAL:
! 690: s = precision(p2); if (s < pa) pa = s;
! 691: if (gsigne(discsr((GEN)p1[1]))>0) t[10]=1; else t[12]=1;
! 692: break;
! 693: case t_INTMOD:
! 694: assign_or_fail((GEN)p2[1],p);
! 695: assign_or_fail((GEN)p1[1],pol);
! 696: t[11]=1; break;
! 697: case t_PADIC:
! 698: s = precp(p2) + valp(p2); if (s < pa) pa = s;
! 699: assign_or_fail((GEN)p2[2],p);
! 700: assign_or_fail((GEN)p1[1],pol);
! 701: t[13]=1; break;
! 702: default: return 0;
! 703: }
! 704: }
! 705: break;
! 706: case t_POLMOD:
! 707: assign_or_fail((GEN)p1[1],pol);
! 708: for (j=1; j<=2; j++)
! 709: {
! 710: GEN pbis = NULL, polbis = NULL;
! 711: long pabis;
! 712: switch(poltype((GEN)p1[j],&pbis,&polbis,&pabis))
! 713: {
! 714: case t_INT: t[14]=1; break;
! 715: case t_INTMOD: t[15]=1; break;
! 716: case t_PADIC: t[16]=1; if (pabis<pa) pa=pabis; break;
! 717: default: return 0;
! 718: }
! 719: if (pbis) assign_or_fail(pbis,p);
! 720: if (polbis) assign_or_fail(polbis,pol);
! 721: }
! 722: break;
! 723: default: return 0;
! 724: }
! 725: }
! 726: if (t[5]||t[12])
! 727: {
! 728: if (t[3]||t[6]||t[7]||t[8]||t[11]||t[13]||t[14]||t[15]||t[16]) return 0;
! 729: *ptpa=pa; return t_COMPLEX;
! 730: }
! 731: if (t[2]||t[10])
! 732: {
! 733: if (t[3]||t[6]||t[7]||t[8]||t[11]||t[13]||t[14]||t[15]||t[16]) return 0;
! 734: *ptpa=pa; return t[4]?t_COMPLEX:t_REAL;
! 735: }
! 736: if (t[6]||t[11]||t[15])
! 737: {
! 738: *ptpol=pol; *ptp=p;
! 739: i = t[15]? t_POLMOD: (t[11]? t_QUAD: t_COMPLEX);
! 740: return typs(i, t_INTMOD);
! 741: }
! 742: if (t[7]||t[13]||t[16])
! 743: {
! 744: *ptpol=pol; *ptp=p; *ptpa=pa;
! 745: i = t[16]? t_POLMOD: (t[13]? t_QUAD: t_COMPLEX);
! 746: return typs(i, t_PADIC);
! 747: }
! 748: if (t[4]||t[9]||t[14])
! 749: {
! 750: *ptpol=pol;
! 751: i = t[14]? t_POLMOD: (t[9]? t_QUAD: t_COMPLEX);
! 752: return typs(i, t_INT);
! 753: }
! 754: if (t[3]) { *ptp=p; return t_INTMOD; }
! 755: if (t[8]) { *ptp=p; *ptpa=pa; return t_PADIC; }
! 756: return t_INT;
! 757: }
! 758: #undef LT
! 759:
! 760: GEN
! 761: factor0(GEN x,long flag)
! 762: {
! 763: long tx=typ(x);
! 764:
! 765: if (flag<0) return factor(x);
! 766: if (is_matvec_t(tx)) return gboundfact(x,flag);
! 767: if (tx==t_INT || tx==t_FRAC || tx==t_FRACN) return boundfact(x,flag);
! 768: err(talker,"partial factorization is not meaningful here");
! 769: return NULL; /* not reached */
! 770: }
! 771:
! 772: static GEN
! 773: poldeg1(long v, GEN x0, GEN x1)
! 774: {
! 775: GEN x = cgetg(4,t_POL);
! 776: x[1] = evalsigne(1) | evalvarn(v) | evallgef(4);
! 777: x[2] = (long)x0; x[3] = (long)x1; return normalizepol(x);
! 778: }
! 779:
! 780: GEN
! 781: factor(GEN x)
! 782: {
! 783: long tx=typ(x),lx,av,tetpil,i,j,pa,v,r1;
! 784: GEN y,p,p1,p2,p3,p4,p5,pol;
! 785:
! 786: if (is_matvec_t(tx))
! 787: {
! 788: lx=lg(x); y=cgetg(lx,tx);
! 789: for (i=1; i<lx; i++) y[i]=(long)factor((GEN)x[i]);
! 790: return y;
! 791: }
! 792: if (gcmp0(x))
! 793: {
! 794: y=cgetg(3,t_MAT);
! 795: p1=cgetg(2,t_COL); y[1]=(long)p1; p1[1]=zero;
! 796: p2=cgetg(2,t_COL); y[2]=(long)p2; p2[1]=un;
! 797: return y;
! 798: }
! 799: switch(tx)
! 800: {
! 801: case t_INT: return decomp(x);
! 802:
! 803: case t_FRACN:
! 804: av=avma; x=gred(x); /* fall through */
! 805: case t_FRAC:
! 806: if (tx==t_FRAC) av=avma;
! 807: p1 = decomp((GEN)x[1]);
! 808: p2 = decomp((GEN)x[2]);
! 809: p4 = concatsp((GEN)p1[1], (GEN)p2[1]);
! 810: p5 = concatsp((GEN)p1[2], gneg_i((GEN)p2[2]));
! 811: p3 = sindexsort(p4); lx = lg(p3);
! 812: tetpil=avma; y=cgetg(3,t_MAT);
! 813: p1 = cgetg(lx,t_COL); y[1]=(long)p1;
! 814: p2 = cgetg(lx,t_COL); y[2]=(long)p2;
! 815: for (i=1; i<lx; i++)
! 816: {
! 817: p1[i] = licopy((GEN)p4[p3[i]]);
! 818: p2[i] = licopy((GEN)p5[p3[i]]);
! 819: }
! 820: return gerepile(av,tetpil,y);
! 821:
! 822: case t_POL:
! 823: tx=poltype(x,&p,&pol,&pa);
! 824: switch(tx)
! 825: {
! 826: case 0: err(impl,"factor for general polynomials");
! 827: case t_INT: return factpol(x,0,1);
! 828: case t_INTMOD: return factmod(x,p);
! 829:
! 830: case t_COMPLEX: y=cgetg(3,t_MAT); lx=lgef(x)-2; v=varn(x);
! 831: av=avma; p1=roots(x,pa); tetpil=avma;
! 832: p2=cgetg(lx,t_COL);
! 833: for (i=1; i<lx; i++)
! 834: p2[i] = (long)poldeg1(v, gneg((GEN)p1[i]), gun);
! 835: y[1]=lpile(av,tetpil,p2);
! 836: p3=cgetg(lx,t_COL); for (i=1; i<lx; i++) p3[i] = un;
! 837: y[2]=(long)p3; return y;
! 838:
! 839: case t_REAL: y=cgetg(3,t_MAT); lx=lgef(x)-2; v=varn(x);
! 840: av=avma; p1=roots(x,pa); tetpil=avma;
! 841: for(r1=1; r1<lx; r1++)
! 842: if (signe(gmael(p1,r1,2))) break;
! 843: lx=(r1+lx)>>1; p2=cgetg(lx,t_COL);
! 844: for(i=1; i<r1; i++)
! 845: p2[i] = (long)poldeg1(v, negr(gmael(p1,i,1)), gun);
! 846: for( ; i<lx; i++)
! 847: {
! 848: GEN a = (GEN) p1[2*i-r1];
! 849: p = cgetg(5, t_POL); p2[i] = (long)p;
! 850: p[1] = evalsigne(1) | evalvarn(v) | evallgef(5);
! 851: p[2] = lnorm(a);
! 852: p[3] = lmul2n((GEN)a[1],1); setsigne(p[3],-signe(p[3]));
! 853: p[4] = un;
! 854: }
! 855: y[1]=lpile(av,tetpil,p2);
! 856: p3=cgetg(lx,t_COL); for (i=1; i<lx; i++) p3[i] = un;
! 857: y[2]=(long)p3; return y;
! 858:
! 859: case t_PADIC: return factorpadic4(x,p,pa);
! 860:
! 861: default:
! 862: {
! 863: long killv;
! 864: av=avma; x = dummycopy(x); lx=lgef(x);
! 865: pol = dummycopy(pol);
! 866: v = manage_var(4,NULL);
! 867: for(i=2; i<lx; i++)
! 868: {
! 869: p1=(GEN)x[i];
! 870: switch(typ(p1))
! 871: {
! 872: case t_QUAD: p1++;
! 873: case t_COMPLEX:
! 874: p2 = cgetg(3, t_POLMOD); x[i] = (long) p2;
! 875: p2[1] = (long)pol;
! 876: p2[2] = (long)poldeg1(v, (GEN)p1[1],(GEN)p1[2]);
! 877: }
! 878: }
! 879: killv = (avma != (long)pol);
! 880: if (killv) setvarn(pol, fetch_var());
! 881: switch (typ2(tx))
! 882: {
! 883: case t_INT: p1 = polfnf(x,pol); break;
! 884: case t_INTMOD: p1 = factmod9(x,p,pol); break;
! 885: default: err(impl,"factor of general polynomial");
! 886: }
! 887: switch (typ1(tx))
! 888: {
! 889: case t_POLMOD:
! 890: if (killv) delete_var();
! 891: return gerepileupto(av,p1);
! 892: case t_COMPLEX: p5 = gi; break;
! 893: case t_QUAD: p5=cgetg(4,t_QUAD);
! 894: p5[1]=(long)pol; p5[2]=zero; p5[3]=un;
! 895: break;
! 896: default: err(impl,"factor of general polynomial");
! 897: }
! 898: p2=(GEN)p1[1];
! 899: for(i=1; i<lg(p2); i++)
! 900: {
! 901: p3=(GEN)p2[i];
! 902: for(j=2; j<lgef(p3); j++)
! 903: {
! 904: p4=(GEN)p3[j];
! 905: if(typ(p4)==t_POLMOD) p3[j]=lsubst((GEN)p4[2],v,p5);
! 906: }
! 907: }
! 908: if (killv) delete_var();
! 909: tetpil=avma; y=cgetg(3,t_MAT);
! 910: y[1]=lcopy(p2);y[2]=lcopy((GEN)p1[2]);
! 911: return gerepile(av,tetpil,y);
! 912: }
! 913: }
! 914:
! 915: case t_RFRACN:
! 916: av=avma; x=gred_rfrac(x); /* fall through */
! 917: case t_RFRAC:
! 918: if (tx==t_RFRAC) av=avma;
! 919: p1=factor((GEN)x[1]);
! 920: p2=factor((GEN)x[2]); p3=gneg_i((GEN)p2[2]);
! 921: tetpil=avma; y=cgetg(3,t_MAT);
! 922: y[1]=lconcat((GEN)p1[1],(GEN)p2[1]);
! 923: y[2]=lconcat((GEN)p1[2],p3);
! 924: return gerepile(av,tetpil,y);
! 925: }
! 926: err(impl,"general factorization");
! 927: return NULL; /* not reached */
! 928: }
! 929: #undef typ1
! 930: #undef typ2
! 931: #undef typs
! 932: #undef tsh
! 933:
! 934: GEN
! 935: divide_conquer_prod(GEN x, GEN (*mul)(GEN,GEN))
! 936: {
! 937: long i,k,lx = lg(x);
! 938:
! 939: if (lx == 1) return gun;
! 940: if (lx == 2) return gcopy((GEN)x[1]);
! 941: x = dummycopy(x); k = lx;
! 942: while (k > 2)
! 943: {
! 944: if (DEBUGLEVEL>7)
! 945: fprintferr("prod: remaining objects %ld\n",k-1);
! 946: lx = k; k = 1;
! 947: for (i=1; i<lx-1; i+=2)
! 948: x[k++] = (long)mul((GEN)x[i],(GEN)x[i+1]);
! 949: if (i < lx) x[k++] = x[i];
! 950: }
! 951: return (GEN)x[1];
! 952: }
! 953:
! 954: static GEN static_nf;
! 955:
! 956: static GEN
! 957: myidealmul(GEN x, GEN y) { return idealmul(static_nf, x, y); }
! 958:
! 959: static GEN
! 960: myidealpow(GEN x, GEN n) { return idealpow(static_nf, x, n); }
! 961:
! 962: GEN
! 963: factorback(GEN fa, GEN nf)
! 964: {
! 965: long av=avma,k,l,lx;
! 966: GEN ex, x;
! 967: GEN (*_mul)(GEN,GEN);
! 968: GEN (*_pow)(GEN,GEN);
! 969:
! 970: if (typ(fa)!=t_MAT || lg(fa)!=3)
! 971: err(talker,"incorrect factorisation in factorback");
! 972: ex=(GEN)fa[2]; fa=(GEN)fa[1];
! 973: lx = lg(fa); if (lx == 1) return gun;
! 974: x = cgetg(lx,t_VEC);
! 975: if (nf)
! 976: {
! 977: static_nf = nf;
! 978: _mul = &myidealmul;
! 979: _pow = &myidealpow;
! 980: }
! 981: else
! 982: {
! 983: _mul = &gmul;
! 984: _pow = &powgi;
! 985: }
! 986: for (l=1,k=1; k<lx; k++)
! 987: if (signe(ex[k]))
! 988: x[l++] = (long)_pow((GEN)fa[k],(GEN)ex[k]);
! 989: setlg(x,l);
! 990: return gerepileupto(av, divide_conquer_prod(x, _mul));
! 991: }
! 992:
! 993: GEN
! 994: gisirreducible(GEN x)
! 995: {
! 996: long av=avma, tx = typ(x),l,i;
! 997: GEN y;
! 998:
! 999: if (is_matvec_t(tx))
! 1000: {
! 1001: l=lg(x); y=cgetg(l,tx);
! 1002: for (i=1; i<l; i++) y[i]=(long)gisirreducible((GEN)x[i]);
! 1003: return y;
! 1004: }
! 1005: if (is_intreal_t(tx) || is_frac_t(tx)) return gzero;
! 1006: if (tx!=t_POL) err(notpoler,"gisirreducible");
! 1007: l=lgef(x); if (l<=3) return gzero;
! 1008: y=factor(x); avma=av;
! 1009: return (lgef(gcoeff(y,1,1))==l)?gun:gzero;
! 1010: }
! 1011:
! 1012: /*******************************************************************/
! 1013: /* */
! 1014: /* PGCD GENERAL */
! 1015: /* */
! 1016: /*******************************************************************/
! 1017:
! 1018: GEN
! 1019: gcd0(GEN x, GEN y, long flag)
! 1020: {
! 1021: switch(flag)
! 1022: {
! 1023: case 0: return ggcd(x,y);
! 1024: case 1: return modulargcd(x,y);
! 1025: case 2: return srgcd(x,y);
! 1026: default: err(flagerr,"gcd");
! 1027: }
! 1028: return NULL; /* not reached */
! 1029: }
! 1030:
! 1031: /* x is a COMPLEX or a QUAD */
! 1032: static GEN
! 1033: triv_cont_gcd(GEN x, GEN y)
! 1034: {
! 1035: long av = avma, tetpil;
! 1036: GEN p1 = (typ(x)==t_COMPLEX)? ggcd((GEN)x[1],(GEN)x[2])
! 1037: : ggcd((GEN)x[2],(GEN)x[3]);
! 1038: tetpil=avma; return gerepile(av,tetpil,ggcd(p1,y));
! 1039: }
! 1040:
! 1041: static GEN
! 1042: cont_gcd(GEN x, GEN y)
! 1043: {
! 1044: long av = avma, tetpil;
! 1045: GEN p1 = content(x);
! 1046:
! 1047: tetpil=avma; return gerepile(av,tetpil,ggcd(p1,y));
! 1048: }
! 1049:
! 1050: /* y is a PADIC, x a rational number or an INTMOD */
! 1051: static GEN
! 1052: padic_gcd(GEN x, GEN y)
! 1053: {
! 1054: long v = ggval(x,(GEN)y[2]), w = valp(y);
! 1055: if (w < v) v = w;
! 1056: return gpuigs((GEN)y[2], v);
! 1057: }
! 1058:
! 1059: #define fix_frac(z) if (signe(z[2])<0)\
! 1060: {\
! 1061: setsigne(z[1],-signe(z[1]));\
! 1062: setsigne(z[2],1);\
! 1063: }
! 1064:
! 1065: GEN
! 1066: ggcd(GEN x, GEN y)
! 1067: {
! 1068: long l,av,tetpil,i,vx,vy, tx = typ(x), ty = typ(y);
! 1069: GEN p1,z;
! 1070:
! 1071: if (tx>ty) { p1=x; x=y; y=p1; l=tx; tx=ty; ty=l; }
! 1072: if (is_matvec_t(ty))
! 1073: {
! 1074: l=lg(y); z=cgetg(l,ty);
! 1075: for (i=1; i<l; i++) z[i]=lgcd(x,(GEN)y[i]);
! 1076: return z;
! 1077: }
! 1078: if (gcmp0(x)) return gcopy(y);
! 1079: if (gcmp0(y)) return gcopy(x);
! 1080: if (is_const_t(tx))
! 1081: {
! 1082: if (ty == t_FRACN)
! 1083: {
! 1084: if (tx==t_INTMOD)
! 1085: {
! 1086: av=avma; y = gred(y); tetpil=avma;
! 1087: return gerepile(av,tetpil,ggcd(x,y));
! 1088: }
! 1089: ty = t_FRAC;
! 1090: }
! 1091: if (tx == t_FRACN) tx = t_FRAC;
! 1092: if (ty == tx) switch(tx)
! 1093: {
! 1094: case t_INT:
! 1095: return mppgcd(x,y);
! 1096:
! 1097: case t_INTMOD: z=cgetg(3,t_INTMOD);
! 1098: if (egalii((GEN)x[1],(GEN)y[1]))
! 1099: { copyifstack(x[1],z[1]); }
! 1100: else
! 1101: z[1]=lmppgcd((GEN)x[1],(GEN)y[1]);
! 1102: if (gcmp1((GEN)z[1])) z[2]=zero;
! 1103: else
! 1104: {
! 1105: av=avma; p1=mppgcd((GEN)z[1],(GEN)x[2]);
! 1106: if (!gcmp1(p1))
! 1107: {
! 1108: tetpil=avma;
! 1109: p1=gerepile(av,tetpil,mppgcd(p1,(GEN)y[2]));
! 1110: }
! 1111: z[2]=(long)p1;
! 1112: }
! 1113: return z;
! 1114:
! 1115: case t_FRAC: z=cgetg(3,t_FRAC);
! 1116: (void)new_chunk(lgefint(x[2])+lgefint(y[2]));
! 1117: p1 = divii((GEN)y[2], mppgcd((GEN)x[2], (GEN)y[2]));
! 1118: avma = (long)z;
! 1119: z[2] = lmulii(p1, (GEN)x[2]);
! 1120: z[1] = (long)mppgcd((GEN)x[1], (GEN)y[1]);
! 1121: fix_frac(z); return z;
! 1122:
! 1123: case t_COMPLEX:
! 1124: av=avma; p1=gdiv(x,y);
! 1125: if (gcmp0((GEN)p1[2]))
! 1126: {
! 1127: p1=(GEN)p1[1];
! 1128: switch(typ(p1))
! 1129: {
! 1130: case t_INT:
! 1131: avma=av; return gcopy(y);
! 1132: case t_FRAC: case t_FRACN:
! 1133: tetpil=avma; return gerepile(av,tetpil,gdiv(y,(GEN)p1[2]));
! 1134: default: avma=av; return gun;
! 1135: }
! 1136: }
! 1137: avma=av;
! 1138: if (typ(p1[1])==t_INT && typ(p1[2])==t_INT) return gcopy(y);
! 1139: p1=gdiv(y,x); avma=av;
! 1140: if (typ(p1[1])==t_INT && typ(p1[2])==t_INT) return gcopy(x);
! 1141: return triv_cont_gcd(y,x);
! 1142:
! 1143: case t_PADIC:
! 1144: if (!egalii((GEN)x[2],(GEN)y[2])) return gun;
! 1145: return gpuigs((GEN)y[2],min(valp(y),valp(x)));
! 1146:
! 1147: case t_QUAD:
! 1148: av=avma; p1=gdiv(x,y);
! 1149: if (gcmp0((GEN)p1[3]))
! 1150: {
! 1151: p1=(GEN)p1[2];
! 1152: if (typ(p1)==t_INT) { avma=av; return gcopy(y); }
! 1153: tetpil=avma; return gerepile(av,tetpil, gdiv(y,(GEN)p1[2]));
! 1154: }
! 1155: avma=av;
! 1156: if (typ(p1[2])==t_INT && typ(p1[3])==t_INT) return gcopy(y);
! 1157: p1=gdiv(y,x); avma=av;
! 1158: if (typ(p1[2])==t_INT && typ(p1[3])==t_INT) return gcopy(x);
! 1159: return triv_cont_gcd(y,x);
! 1160:
! 1161: default: return gun; /* t_REAL */
! 1162: }
! 1163: if (is_const_t(ty)) switch(tx)
! 1164: {
! 1165: case t_INT:
! 1166: switch(ty)
! 1167: {
! 1168: case t_INTMOD: z=cgetg(3,t_INTMOD);
! 1169: copyifstack(y[1],z[1]); av=avma;
! 1170: p1=mppgcd((GEN)y[1],(GEN)y[2]);
! 1171: if (!gcmp1(p1))
! 1172: { tetpil=avma; p1=gerepile(av,tetpil,mppgcd(x,p1)); }
! 1173: z[2]=(long)p1; return z;
! 1174:
! 1175: case t_FRAC: z=cgetg(3,t_FRAC);
! 1176: z[1]=lmppgcd(x,(GEN)y[1]);
! 1177: z[2]=licopy((GEN)y[2]); return z;
! 1178:
! 1179: case t_COMPLEX: case t_QUAD:
! 1180: return triv_cont_gcd(y,x);
! 1181:
! 1182: case t_PADIC:
! 1183: return padic_gcd(x,y);
! 1184:
! 1185: default: /* t_REAL */
! 1186: return gun;
! 1187: }
! 1188:
! 1189: case t_INTMOD:
! 1190: switch(ty)
! 1191: {
! 1192: case t_FRAC:
! 1193: av=avma; p1=mppgcd((GEN)x[1],(GEN)y[2]); tetpil=avma;
! 1194: if (!gcmp1(p1))
! 1195: err(talker,"non invertible fraction in a gcd with INTMOD");
! 1196: return gerepile(av,tetpil, ggcd((GEN)y[1],x));
! 1197:
! 1198: case t_COMPLEX: case t_QUAD:
! 1199: return triv_cont_gcd(y,x);
! 1200:
! 1201: case t_PADIC:
! 1202: return padic_gcd(x,y);
! 1203: }
! 1204:
! 1205: case t_FRAC:
! 1206: switch(ty)
! 1207: {
! 1208: case t_COMPLEX: case t_QUAD:
! 1209: return triv_cont_gcd(y,x);
! 1210:
! 1211: case t_PADIC:
! 1212: return padic_gcd(x,y);
! 1213: }
! 1214:
! 1215: case t_COMPLEX: /* ty = PADIC or QUAD */
! 1216: return triv_cont_gcd(x,y);
! 1217:
! 1218: case t_PADIC: /* ty = QUAD */
! 1219: return triv_cont_gcd(y,x);
! 1220:
! 1221: default: /* tx = t_REAL */
! 1222: return gun;
! 1223: }
! 1224: return cont_gcd(y,x);
! 1225: }
! 1226:
! 1227: vx=gvar9(x); vy=gvar9(y);
! 1228: if (vy<vx) return cont_gcd(y,x);
! 1229: if (vx<vy) return cont_gcd(x,y);
! 1230: switch(tx)
! 1231: {
! 1232: case t_POLMOD:
! 1233: switch(ty)
! 1234: {
! 1235: case t_POLMOD: z=cgetg(3,t_POLMOD);
! 1236: if (gegal((GEN)x[1],(GEN)y[1]))
! 1237: { copyifstack(x[1],z[1]); }
! 1238: else
! 1239: z[1] = lgcd((GEN)x[1],(GEN)y[1]);
! 1240: if (lgef(z[1])<=3) z[2]=zero;
! 1241: else
! 1242: {
! 1243: av=avma; p1=ggcd((GEN)z[1],(GEN)x[2]);
! 1244: if (lgef(p1)>3)
! 1245: {
! 1246: tetpil=avma;
! 1247: p1=gerepile(av,tetpil,ggcd(p1,(GEN)y[2]));
! 1248: }
! 1249: z[2]=(long)p1;
! 1250: }
! 1251: return z;
! 1252:
! 1253: case t_POL: z=cgetg(3,t_POLMOD);
! 1254: copyifstack(x[1],z[1]); av=avma;
! 1255: p1=ggcd((GEN)x[1],(GEN)x[2]);
! 1256: if (lgef(p1)>3)
! 1257: { tetpil=avma; p1=gerepile(av,tetpil,ggcd(y,p1)); }
! 1258: z[2]=(long)p1; return z;
! 1259:
! 1260: case t_RFRAC:
! 1261: av=avma; p1=ggcd((GEN)x[1],(GEN)y[2]); tetpil=avma;
! 1262: if (!gcmp1(p1))
! 1263: err(talker,"non invertible fraction in a gcd with POLMOD");
! 1264: return gerepile(av,tetpil,ggcd((GEN)y[1],x));
! 1265:
! 1266: case t_RFRACN:
! 1267: av=avma; p1=gred_rfrac(y); tetpil=avma;
! 1268: return gerepile(av,tetpil,ggcd(p1,x));
! 1269: }
! 1270: break;
! 1271:
! 1272: case t_POL:
! 1273: switch(ty)
! 1274: {
! 1275: case t_POL:
! 1276: return srgcd(x,y);
! 1277:
! 1278: case t_SER:
! 1279: return gpuigs(polx[vx],min(valp(y),gval(x,vx)));
! 1280:
! 1281: case t_RFRAC: case t_RFRACN: av=avma; z=cgetg(3,ty);
! 1282: z[1]=lgcd(x,(GEN)y[1]);
! 1283: z[2]=lcopy((GEN)y[2]); return z;
! 1284: }
! 1285: break;
! 1286:
! 1287: case t_SER:
! 1288: switch(ty)
! 1289: {
! 1290: case t_SER:
! 1291: return gpuigs(polx[vx],min(valp(x),valp(y)));
! 1292:
! 1293: case t_RFRAC: case t_RFRACN:
! 1294: return gpuigs(polx[vx],min(valp(x),gval(y,vx)));
! 1295: }
! 1296: break;
! 1297:
! 1298: case t_RFRAC: case t_RFRACN: z=cgetg(3,ty);
! 1299: if (!is_rfrac_t(ty))
! 1300: err(talker,"forbidden gcd rational function with vector/matrix");
! 1301: p1 = gdiv((GEN)y[2], ggcd((GEN)x[2], (GEN)y[2]));
! 1302: tetpil = avma;
! 1303: z[2] = lpile((long)z,tetpil,gmul(p1, (GEN)x[2]));
! 1304: z[1] = lgcd((GEN)x[1], (GEN)y[1]); return z;
! 1305: }
! 1306: err(talker,"gcd vector/matrix with a forbidden type");
! 1307: return NULL; /* not reached */
! 1308: }
! 1309:
! 1310: GEN
! 1311: glcm(GEN x, GEN y)
! 1312: {
! 1313: long av=avma,tx,ty=typ(y),i,l;
! 1314: GEN p1,p2,z;
! 1315:
! 1316: if (is_matvec_t(ty))
! 1317: {
! 1318: l=lg(y); z=cgetg(l,ty);
! 1319: for (i=1; i<l; i++) z[i]=(long)glcm(x,(GEN)y[i]);
! 1320: return z;
! 1321: }
! 1322: tx=typ(x);
! 1323: if (is_matvec_t(tx))
! 1324: {
! 1325: l=lg(x); z=cgetg(l,tx);
! 1326: for (i=1; i<l; i++) z[i]=(long)glcm((GEN)x[i],y);
! 1327: return z;
! 1328: }
! 1329: if (gcmp0(x)) return gzero;
! 1330: if (tx==t_INT && ty==t_INT)
! 1331: {
! 1332: p1 = mppgcd(x,y); if (is_pm1(p1)) { avma = av; return mulii(x,y); }
! 1333: p2 = mulii(divii(y,p1), x);
! 1334: if (signe(p2)<0) setsigne(p2,1);
! 1335: return gerepileupto(av, p2);
! 1336: }
! 1337: p1 = ggcd(x,y); if (gcmp1(p1)) {avma = av; return gmul(x,y); }
! 1338: p2 = gmul(gdiv(y,p1), x);
! 1339: if (typ(p2)==t_INT && signe(p2)<0) setsigne(p2,1);
! 1340: if (typ(p2)==t_POL)
! 1341: {
! 1342: p1=leading_term(p2);
! 1343: if (typ(p1)==t_INT && signe(p1)<0) p2=gneg(p2);
! 1344: }
! 1345: return gerepileupto(av,p2);
! 1346: }
! 1347:
! 1348: static GEN
! 1349: polgcdnun(GEN x, GEN y)
! 1350: {
! 1351: long av1, av = avma, lim = stack_lim(av,1);
! 1352: GEN p1, yorig = y;
! 1353:
! 1354: for(;;)
! 1355: {
! 1356: av1 = avma; p1 = gres(x,y);
! 1357: if (gcmp0(p1))
! 1358: {
! 1359: avma = av1;
! 1360: return (y==yorig)? gcopy(y): gerepileupto(av,y);
! 1361: }
! 1362: x = y; y = p1;
! 1363: if (low_stack(lim,stack_lim(av,1)))
! 1364: {
! 1365: GEN *gptr[2]; x = gcopy(x); gptr[0]=&x; gptr[1]=&y;
! 1366: if(DEBUGMEM>1) err(warnmem,"polgcdnun");
! 1367: gerepilemanysp(av,av1,gptr,2);
! 1368: }
! 1369: }
! 1370: }
! 1371:
! 1372: /* return 1 if coeff explosion is not possible */
! 1373: static int
! 1374: issimplefield(GEN x)
! 1375: {
! 1376: long lx,i;
! 1377: switch(typ(x))
! 1378: {
! 1379: case t_REAL: case t_INTMOD: case t_PADIC: case t_SER:
! 1380: return 1;
! 1381: case t_POL:
! 1382: lx=lgef(x);
! 1383: for (i=2; i<lx; i++)
! 1384: if (!issimplefield((GEN)x[i])) return 0;
! 1385: return 1;
! 1386: case t_COMPLEX: case t_POLMOD:
! 1387: return issimplefield((GEN)x[1]) || issimplefield((GEN)x[2]);
! 1388: }
! 1389: return 0;
! 1390: }
! 1391:
! 1392: static int
! 1393: isrational(GEN x)
! 1394: {
! 1395: long i;
! 1396: for (i=lgef(x)-1; i>1; i--)
! 1397: switch(typ(x[i]))
! 1398: {
! 1399: case t_INT:
! 1400: case t_FRAC: break;
! 1401: default: return 0;
! 1402: }
! 1403: return 1;
! 1404: }
! 1405:
! 1406: static int
! 1407: isinexactfield(GEN x)
! 1408: {
! 1409: long lx,i;
! 1410: switch(typ(x))
! 1411: {
! 1412: case t_REAL: case t_PADIC: case t_SER:
! 1413: return 1;
! 1414: case t_POL:
! 1415: lx=lgef(x);
! 1416: for (i=2; i<lx; i++)
! 1417: if (!isinexactfield((GEN)x[i])) return 0;
! 1418: return 1;
! 1419: case t_COMPLEX: case t_POLMOD:
! 1420: return isinexactfield((GEN)x[1]) || isinexactfield((GEN)x[2]);
! 1421: }
! 1422: return 0;
! 1423: }
! 1424:
! 1425: static GEN
! 1426: gcdmonome(GEN x, GEN y)
! 1427: {
! 1428: long tetpil,av=avma, lx=lgef(x), v=varn(x), e=gval(y,v);
! 1429: GEN p1,p2;
! 1430:
! 1431: if (lx-3<e) e=lx-3;
! 1432: p1=ggcd(leading_term(x),content(y)); p2=gpuigs(polx[v],e);
! 1433: tetpil=avma; return gerepile(av,tetpil,gmul(p1,p2));
! 1434: }
! 1435:
! 1436: /***********************************************************************/
! 1437: /** **/
! 1438: /** BEZOUT GENERAL **/
! 1439: /** **/
! 1440: /***********************************************************************/
! 1441:
! 1442: static GEN
! 1443: polinvinexact(GEN x, GEN y)
! 1444: {
! 1445: long i,dx=lgef(x)-3,dy=lgef(y)-3,lz=dx+dy, av=avma, tetpil;
! 1446: GEN v,z;
! 1447:
! 1448: z=cgetg(dy+2,t_POL); z[1]=y[1];
! 1449: v=cgetg(lz+1,t_COL);
! 1450: for (i=1; i<lz; i++) v[i]=zero;
! 1451: v[lz]=un; v=gauss(sylvestermatrix(y,x),v);
! 1452: for (i=2; i<dy+2; i++) z[i]=v[lz-i+2];
! 1453: z = normalizepol_i(z, dy+2); tetpil = avma;
! 1454: return gerepile(av,tetpil,gcopy(z));
! 1455: }
! 1456:
! 1457: static GEN
! 1458: polinvmod(GEN x, GEN y)
! 1459: {
! 1460: long av,av1,tx,vx=varn(x),vy=varn(y);
! 1461: GEN u,v,d,p1;
! 1462:
! 1463: while (vx!=vy)
! 1464: {
! 1465: if (vx > vy)
! 1466: {
! 1467: d=cgetg(3,t_RFRAC);
! 1468: d[1]=(long)polun[vx];
! 1469: d[2]=lcopy(x); return d;
! 1470: }
! 1471: if (lgef(x)!=3) err(talker,"non-invertible polynomial in polinvmod");
! 1472: x=(GEN)x[2]; vx=gvar(x);
! 1473: }
! 1474: tx=typ(x);
! 1475: if (tx==t_POL)
! 1476: {
! 1477: if (isinexactfield(x) || isinexactfield(y))
! 1478: return polinvinexact(x,y);
! 1479:
! 1480: av=avma; d=subresext(x,y,&u,&v);
! 1481: if (gcmp0(d)) err(talker,"non-invertible polynomial in polinvmod");
! 1482: if (typ(d)==t_POL && varn(d)==vx)
! 1483: {
! 1484: if (lgef(d)>3) err(talker,"non-invertible polynomial in polinvmod");
! 1485: d=(GEN)d[2];
! 1486: }
! 1487: av1=avma; return gerepile(av,av1,gdiv(u,d));
! 1488: }
! 1489: if (!is_rfrac_t(tx)) err(typeer,"polinvmod");
! 1490: av=avma; p1=gmul((GEN)x[1],polinvmod((GEN)x[2],y));
! 1491: av1=avma; return gerepile(av,av1,gmod(p1,y));
! 1492: }
! 1493:
! 1494: GEN
! 1495: gbezout(GEN x, GEN y, GEN *u, GEN *v)
! 1496: {
! 1497: long tx=typ(x),ty=typ(y);
! 1498:
! 1499: if (tx==t_INT && ty==t_INT) return bezout(x,y,u,v);
! 1500: if (!is_extscalar_t(tx) || !is_extscalar_t(ty)) err(typeer,"gbezout");
! 1501: return bezoutpol(x,y,u,v);
! 1502: }
! 1503:
! 1504: GEN
! 1505: vecbezout(GEN x, GEN y)
! 1506: {
! 1507: GEN z=cgetg(4,t_VEC);
! 1508: z[3]=(long)gbezout(x,y,(GEN*)(z+1),(GEN*)(z+2));
! 1509: return z;
! 1510: }
! 1511:
! 1512: GEN
! 1513: vecbezoutres(GEN x, GEN y)
! 1514: {
! 1515: GEN z=cgetg(4,t_VEC);
! 1516: z[3]=(long)subresext(x,y,(GEN*)(z+1),(GEN*)(z+2));
! 1517: return z;
! 1518: }
! 1519:
! 1520: /*******************************************************************/
! 1521: /* */
! 1522: /* CONTENU ET PARTIE PRIMITIVE */
! 1523: /* */
! 1524: /*******************************************************************/
! 1525:
! 1526: GEN
! 1527: content(GEN x)
! 1528: {
! 1529: long av,tetpil,lx,i,tx=typ(x);
! 1530: GEN p1,p2;
! 1531:
! 1532: if (is_scalar_t(tx))
! 1533: return tx==t_POLMOD? content((GEN)x[2]): gcopy(x);
! 1534: av = avma;
! 1535: switch(tx)
! 1536: {
! 1537: case t_RFRAC: case t_RFRACN:
! 1538: p1=content((GEN)x[1]);
! 1539: p2=content((GEN)x[2]); tetpil=avma;
! 1540: return gerepile(av,tetpil,gdiv(p1,p2));
! 1541:
! 1542: case t_VEC: case t_COL: case t_MAT:
! 1543: lx = lg(x); if (lx==1) return gun;
! 1544: p1=content((GEN)x[1]);
! 1545: for (i=2; i<lx; i++) p1 = ggcd(p1,content((GEN)x[i]));
! 1546: return gerepileupto(av,p1);
! 1547:
! 1548: case t_POL:
! 1549: if (!signe(x)) return gzero;
! 1550: lx = lgef(x); break;
! 1551: case t_SER:
! 1552: if (!signe(x)) return gzero;
! 1553: lx = lg(x); break;
! 1554: case t_QFR: case t_QFI:
! 1555: lx = 4; break;
! 1556:
! 1557: default: err(typeer,"content");
! 1558: }
! 1559: for (i=lontyp[tx]; i<lx; i++)
! 1560: if (typ(x[i]) != t_INT) break;
! 1561: lx--; p1=(GEN)x[lx];
! 1562: if (i > lx)
! 1563: { /* integer coeffs */
! 1564: while (lx>lontyp[tx])
! 1565: {
! 1566: lx--; p1=mppgcd(p1,(GEN)x[lx]);
! 1567: if (is_pm1(p1)) { avma=av; return gun; }
! 1568: }
! 1569: }
! 1570: else
! 1571: {
! 1572: while (lx>lontyp[tx])
! 1573: {
! 1574: lx--; p1=ggcd(p1,(GEN)x[lx]);
! 1575: }
! 1576: if (isinexactreal(p1)) { avma=av; return gun; }
! 1577: }
! 1578: return av==avma? gcopy(p1): gerepileupto(av,p1);
! 1579: }
! 1580:
! 1581: /*******************************************************************/
! 1582: /* */
! 1583: /* SOUS RESULTANT */
! 1584: /* */
! 1585: /*******************************************************************/
! 1586: GEN
! 1587: gdivexact(GEN x, GEN y)
! 1588: {
! 1589: long i,lx;
! 1590: GEN z;
! 1591: if (gcmp1(y)) return x;
! 1592: switch(typ(x))
! 1593: {
! 1594: case t_INT:
! 1595: if (typ(y)==t_INT) return divii(x,y);
! 1596: if (!signe(x)) return gzero;
! 1597: break;
! 1598: case t_INTMOD:
! 1599: case t_POLMOD: return gmul(x,ginv(y));
! 1600: case t_POL:
! 1601: switch(typ(y))
! 1602: {
! 1603: case t_INTMOD:
! 1604: case t_POLMOD: return gmul(x,ginv(y));
! 1605: case t_POL:
! 1606: if (varn(x)==varn(y)) return poldivres(x,y, ONLY_DIVIDES_EXACT);
! 1607: }
! 1608: lx = lgef(x); z = cgetg(lx,t_POL);
! 1609: for (i=2; i<lx; i++) z[i]=(long)gdivexact((GEN)x[i],y);
! 1610: z[1]=x[1]; return z;
! 1611: }
! 1612: if (DEBUGLEVEL) err(warner,"missing case in gdivexact");
! 1613: return gdiv(x,y);
! 1614: }
! 1615:
! 1616: static GEN
! 1617: init_resultant(GEN x, GEN y)
! 1618: {
! 1619: long tx,ty;
! 1620: if (gcmp0(x) || gcmp0(y)) return gzero;
! 1621: tx = typ(x); ty = typ(y);
! 1622: if (is_scalar_t(tx) || is_scalar_t(ty))
! 1623: {
! 1624: if (tx==t_POL) return gpuigs(y,lgef(x)-3);
! 1625: if (ty==t_POL) return gpuigs(x,lgef(y)-3);
! 1626: return gun;
! 1627: }
! 1628: if (tx!=t_POL || ty!=t_POL) err(typeer,"subresall");
! 1629: if (varn(x)==varn(y)) return NULL;
! 1630: return (varn(x)<varn(y))? gpuigs(y,lgef(x)-3): gpuigs(x,lgef(y)-3);
! 1631: }
! 1632:
! 1633: /* return coefficients s.t x = x_0 X^n + ... + x_n */
! 1634: static GEN
! 1635: revpol(GEN x)
! 1636: {
! 1637: long i,n = lgef(x)-3;
! 1638: GEN y = cgetg(n+3,t_POL);
! 1639: y[1] = x[1]; x += 2; y += 2;
! 1640: for (i=0; i<=n; i++) y[i] = x[n-i];
! 1641: return y;
! 1642: }
! 1643:
! 1644: /* assume dx >= dy, y non constant */
! 1645: GEN
! 1646: pseudorem(GEN x, GEN y)
! 1647: {
! 1648: long av = avma, av2,lim, vx = varn(x),dx,dy,dz,i,lx, p;
! 1649:
! 1650: if (!signe(y)) err(talker,"euclidean division by zero (pseudorem)");
! 1651: (void)new_chunk(2);
! 1652: dx=lgef(x)-3; x = revpol(x);
! 1653: dy=lgef(y)-3; y = revpol(y); dz=dx-dy; p = dz+1;
! 1654: av2 = avma; lim = stack_lim(av2,1);
! 1655: for (;;)
! 1656: {
! 1657: x[0] = lneg((GEN)x[0]); p--;
! 1658: for (i=1; i<=dy; i++)
! 1659: x[i] = ladd(gmul((GEN)y[0], (GEN)x[i]), gmul((GEN)x[0],(GEN)y[i]));
! 1660: for ( ; i<=dx; i++)
! 1661: x[i] = lmul((GEN)y[0], (GEN)x[i]);
! 1662: do { x++; dx--; } while (dx >= 0 && gcmp0((GEN)x[0]));
! 1663: if (dx < dy) break;
! 1664: if (low_stack(lim,stack_lim(av2,1)))
! 1665: {
! 1666: if(DEBUGMEM>1) err(warnmem,"pseudorem dx = %ld >= %ld",dx,dy);
! 1667: gerepilemanycoeffs(av2,x,dx+1);
! 1668: }
! 1669: }
! 1670: if (dx < 0) return zeropol(vx);
! 1671: lx = dx+3; x -= 2;
! 1672: x[0]=evaltyp(t_POL) | evallg(lx);
! 1673: x[1]=evalsigne(1) | evalvarn(vx) | evallgef(lx);
! 1674: x = revpol(x) - 2;
! 1675: return gerepileupto(av, gmul(x, gpowgs((GEN)y[0], p)));
! 1676: }
! 1677:
! 1678: /* Si sol != NULL:
! 1679: * met dans *sol le dernier polynome non nul de la polynomial remainder
! 1680: * sequence si elle a ete effectuee, 0 sinon
! 1681: */
! 1682: GEN
! 1683: subresall(GEN u, GEN v, GEN *sol)
! 1684: {
! 1685: long degq,av,av2,lim,tetpil,dx,dy,du,dv,dr,signh;
! 1686: GEN g,h,r,p1,p2,p3,p4;
! 1687:
! 1688: if (sol) *sol=gzero;
! 1689: if ((r = init_resultant(u,v))) return r;
! 1690:
! 1691: if (isinexactfield(u) || isinexactfield(v)) return resultant2(u,v);
! 1692: dx=lgef(u); dy=lgef(v); signh=1;
! 1693: if (dx<dy)
! 1694: {
! 1695: p1=u; u=v; v=p1; du=dx; dx=dy; dy=du;
! 1696: if ((dx&1) == 0 && (dy&1) == 0) signh = -signh;
! 1697: }
! 1698: if (dy==3) return gpowgs((GEN)v[2],dx-3);
! 1699: av=avma;
! 1700: p3=content(u); if (gcmp1(p3)) p3=NULL; else u=gdiv(u,p3);
! 1701: p4=content(v); if (gcmp1(p4)) p4=NULL; else v=gdiv(v,p4);
! 1702: g=gun; h=gun; av2 = avma; lim = stack_lim(av2,1);
! 1703: for(;;)
! 1704: {
! 1705: r = pseudorem(u,v); dr = lgef(r);
! 1706: if (dr==2)
! 1707: {
! 1708: if (sol) {avma = (long)(r+2); *sol=gerepileupto(av,v);} else avma = av;
! 1709: return gzero;
! 1710: }
! 1711: du=lgef(u); dv=lgef(v);
! 1712: degq=du-dv; u=v;
! 1713: p1 = g; g = leading_term(u);
! 1714: switch(degq)
! 1715: {
! 1716: case 0: break;
! 1717: case 1:
! 1718: p1 = gmul(h,p1); h = g; break;
! 1719: default:
! 1720: p1 = gmul(gpuigs(h,degq),p1);
! 1721: h = gdivexact(gpuigs(g,degq), gpuigs(h,degq-1));
! 1722: }
! 1723: if ((du&1) == 0 && (dv&1) == 0) signh = -signh;
! 1724: v = gdivexact(r,p1);
! 1725: if (dr==3) break;
! 1726: if (low_stack(lim,stack_lim(av2,1)))
! 1727: {
! 1728: GEN *gptr[4]; gptr[0]=&u; gptr[1]=&v; gptr[2]=&g; gptr[3]=&h;
! 1729: if(DEBUGMEM>1) err(warnmem,"subresall, dr = %ld",dr);
! 1730: gerepilemany(av2,gptr,4);
! 1731: }
! 1732: }
! 1733: if (dv==4) { tetpil=avma; p2=gcopy((GEN)v[2]); }
! 1734: else
! 1735: {
! 1736: if (dv == 3) err(bugparier,"subres");
! 1737: p1=gpuigs((GEN)v[2],dv-3); p2=gpuigs(h,dv-4);
! 1738: tetpil=avma; p2=gdiv(p1,p2);
! 1739: }
! 1740: if (p3) { p1=gpuigs(p3,dy-3); tetpil=avma; p2=gmul(p2,p1); }
! 1741: if (p4) { p1=gpuigs(p4,dx-3); tetpil=avma; p2=gmul(p2,p1); }
! 1742: if (signh<0) { tetpil=avma; p2=gneg(p2); }
! 1743: {
! 1744: GEN *gptr[2]; gptr[0]=&p2; if (sol) { *sol=gcopy(u); gptr[1]=sol; }
! 1745: gerepilemanysp(av,tetpil,gptr,sol?2:1);
! 1746: return p2;
! 1747: }
! 1748: }
! 1749:
! 1750: static GEN
! 1751: scalar_res(GEN x, GEN y, GEN *U, GEN *V)
! 1752: {
! 1753: long dx=lgef(x)-4;
! 1754: *V=gpuigs(y,dx); *U=gzero; return gmul(y,*V);
! 1755: }
! 1756:
! 1757: /* calcule U et V tel que Ux+By=resultant(x,y) */
! 1758: GEN
! 1759: subresext(GEN x, GEN y, GEN *U, GEN *V)
! 1760: {
! 1761: long degq,av,tetpil,tx,ty,dx,dy,du,dv,dr,signh;
! 1762: GEN z,g,h,r,p1,p2,p3,p4,u,v,lpu,um1,uze, *gptr[2];
! 1763:
! 1764: if (gcmp0(x) || gcmp0(y)) { *U = *V = gzero; return gzero; }
! 1765: tx=typ(x); ty=typ(y);
! 1766: if (is_scalar_t(tx) || is_scalar_t(ty))
! 1767: {
! 1768: if (tx==t_POL) return scalar_res(x,y,U,V);
! 1769: if (ty==t_POL) return scalar_res(y,x,V,U);
! 1770: *U=ginv(x); *V=gzero; return gun;
! 1771: }
! 1772: if (tx!=t_POL || ty!=t_POL) err(typeer,"subresext");
! 1773: if (varn(x)!=varn(y))
! 1774: return (varn(x)<varn(y))? scalar_res(x,y,U,V)
! 1775: : scalar_res(y,x,V,U);
! 1776: dx=lgef(x); dy=lgef(y); signh=1;
! 1777: if (dx<dy)
! 1778: {
! 1779: GEN *W = U; U=V; V=W;
! 1780: du=dx; dx=dy; dy=du; p1=x; x=y; y=p1;
! 1781: if ((dx&1) == 0 && (dy&1) == 0) signh = -signh;
! 1782: }
! 1783: if (dy==3)
! 1784: {
! 1785: *V=gpuigs((GEN)y[2],dx-4);
! 1786: *U=gzero; return gmul(*V,(GEN)y[2]);
! 1787: }
! 1788: av=avma;
! 1789: p3=content(x); if (gcmp1(p3)) {p3 = NULL; u=x; } else u=gdiv(x,p3);
! 1790: p4=content(y); if (gcmp1(p4)) {p4 = NULL; v=y; } else v=gdiv(y,p4);
! 1791: g=gun; h=gun; um1=gun; uze=gzero;
! 1792: for(;;)
! 1793: {
! 1794: du=lgef(u); dv=lgef(v); degq=du-dv;
! 1795: lpu=gpuigs((GEN)v[dv-1],degq+1);
! 1796: p1=gmul(lpu,u); p2=poldivres(p1,v,&r);
! 1797: dr=lgef(r); if (dr==2) { *U=gzero; *V=gzero; avma=av; return gzero; }
! 1798:
! 1799: p1=gsub(gmul(lpu,um1),gmul(p2,uze));
! 1800: um1=uze; uze=p1; u=v;
! 1801: p1 = g; g = leading_term(u);
! 1802: switch(degq)
! 1803: {
! 1804: case 0: break;
! 1805: case 1: p1 = gmul(h,p1); h = g; break;
! 1806: default:
! 1807: p1 = gmul(gpuigs(h,degq),p1);
! 1808: h = gdivexact(gpuigs(g,degq), gpuigs(h,degq-1));
! 1809: }
! 1810: if ((du & 1) == 0 && (dv & 1) == 0) signh= -signh;
! 1811: v=gdivexact(r,p1); uze=gdivexact(uze,p1);
! 1812: if (dr==3) break;
! 1813: }
! 1814:
! 1815: p2=(dv==4)?gun:gpuigs(gdiv((GEN)v[2],h),dv-4);
! 1816: if (p3) p2 = gmul(p2,gpuigs(p3,dy-3));
! 1817: if (p4) p2 = gmul(p2,gpuigs(p4,dx-3));
! 1818: if (signh<0) p2=gneg_i(p2);
! 1819: p3 = p3? gdiv(p2,p3): p2;
! 1820:
! 1821: tetpil=avma; z=gmul((GEN)v[2],p2); uze=gmul(uze,p3);
! 1822: gptr[0]=&z; gptr[1]=&uze; gerepilemanysp(av,tetpil,gptr,2);
! 1823:
! 1824: av=avma; p1 = gadd(z, gneg(gmul(uze,x))); tetpil = avma;
! 1825: if (!poldivis(p1,y,&p1)) err(bugparier,"subresext");
! 1826: *U=uze; *V=gerepile(av,tetpil,p1); return z;
! 1827: }
! 1828:
! 1829: static GEN
! 1830: scalar_bezout(GEN x, GEN y, GEN *U, GEN *V)
! 1831: {
! 1832: long v = varn(x);
! 1833: *U=gzero; *V=gdiv(polun[v],y); return polun[v];
! 1834: }
! 1835:
! 1836: static GEN
! 1837: zero_bezout(GEN y, GEN *U, GEN *V)
! 1838: {
! 1839: GEN x=content(y);
! 1840: *U=gzero; *V = gdiv(polun[varn(y)],x); return gmul(y,*V);
! 1841: }
! 1842:
! 1843: /* calcule U et V tel que Ux+Vy=GCD(x,y) par le sous-resultant */
! 1844: GEN
! 1845: bezoutpol(GEN x, GEN y, GEN *U, GEN *V)
! 1846: {
! 1847: long degq,av,tetpil,tx,ty,dx,dy,du,dv,dr;
! 1848: GEN g,h,r,p1,p2,p3,p4,u,v,lpu,um1,uze,vze,xprim,yprim;
! 1849: GEN *gptr[3];
! 1850:
! 1851: if (gcmp0(x)) return zero_bezout(y,U,V);
! 1852: if (gcmp0(y)) return zero_bezout(x,V,U);
! 1853: tx=typ(x); ty=typ(y); av=avma;
! 1854: if (is_scalar_t(tx) || is_scalar_t(ty))
! 1855: {
! 1856: if (tx==t_POL) return scalar_bezout(x,y,U,V);
! 1857: if (ty==t_POL) return scalar_bezout(y,x,V,U);
! 1858: *U=ginv(x); *V=gzero; return polun[0];
! 1859: }
! 1860: if (tx!=t_POL || ty!=t_POL) err(typeer,"bezoutpol");
! 1861: if (varn(x)!=varn(y))
! 1862: return (varn(x)<varn(y))? scalar_bezout(x,y,U,V)
! 1863: : scalar_bezout(y,x,V,U);
! 1864: dx=lgef(x); dy=lgef(y);
! 1865: if (dx<dy)
! 1866: {
! 1867: GEN *W=U; U=V; V=W;
! 1868: p1=x; x=y; y=p1; du=dx; dx=dy; dy=du;
! 1869: }
! 1870: if (dy==3) return scalar_bezout(x,y,U,V);
! 1871:
! 1872: p3=content(x); u=gdiv(x,p3);
! 1873: p4=content(y); v=gdiv(y,p4);
! 1874: xprim=u; yprim=v; g=gun; h=gun; um1=gun; uze=gzero;
! 1875: for(;;)
! 1876: {
! 1877: du=lgef(u); dv=lgef(v); degq=du-dv;
! 1878: lpu=gpuigs((GEN)v[dv-1],degq+1);
! 1879: p1=gmul(lpu,u); p2=poldivres(p1,v,&r);
! 1880: dr=lgef(r); if (dr<=2) break;
! 1881: p1=gsub(gmul(lpu,um1),gmul(p2,uze)); um1=uze; uze=p1;
! 1882:
! 1883: u=v; p1 = g; g = leading_term(u);
! 1884: switch(degq)
! 1885: {
! 1886: case 0: break;
! 1887: case 1:
! 1888: p1 = gmul(h,p1); h = g; break;
! 1889: default:
! 1890: p1 = gmul(gpuigs(h,degq), p1);
! 1891: h = gdiv(gpuigs(g,degq), gpuigs(h,degq-1));
! 1892: }
! 1893: v=gdiv(r,p1); uze=gdiv(uze,p1);
! 1894: if (dr==3) break;
! 1895: }
! 1896: if (!poldivis(gsub(v,gmul(uze,xprim)),yprim, &vze))
! 1897: err(warner,"non-exact computation in bezoutpol");
! 1898: uze=gdiv(uze,p3); vze=gdiv(vze,p4); p1=ginv(content(v));
! 1899:
! 1900: tetpil=avma; uze=gmul(uze,p1); vze=gmul(vze,p1); p1=gmul(v,p1);
! 1901: gptr[0]=&uze; gptr[1]=&vze; gptr[2]=&p1;
! 1902: gerepilemanysp(av,tetpil,gptr,3);
! 1903: *U=uze; *V=vze; return p1;
! 1904: }
! 1905:
! 1906:
! 1907:
! 1908: /*******************************************************************/
! 1909: /* */
! 1910: /* RESULTANT PAR L'ALGORITHME DE DUCOS */
! 1911: /* */
! 1912: /*******************************************************************/
! 1913: GEN addshiftw(GEN x, GEN y, long d);
! 1914:
! 1915: static GEN
! 1916: reductum(GEN P)
! 1917: {
! 1918: if (signe(P)==0) return P;
! 1919: return normalizepol_i(dummycopy(P),lgef(P)-1);
! 1920: }
! 1921:
! 1922: static GEN
! 1923: Lazard(GEN x, GEN y, long n)
! 1924: {
! 1925: long a, b;
! 1926: GEN c;
! 1927:
! 1928: if (n==1) return x;
! 1929: a=1; while (n >= (b=a+a)) a=b;
! 1930: c=x; n-=a;
! 1931: while (a>1)
! 1932: {
! 1933: a>>=1; c=gdivexact(gsqr(c),y);
! 1934: if (n>=a) { c=gdivexact(gmul(c,x),y); n -= a; }
! 1935: }
! 1936: return c;
! 1937: }
! 1938:
! 1939: static GEN
! 1940: Lazard2(GEN F, GEN x, GEN y, long n)
! 1941: {
! 1942: if (n<=1) return F;
! 1943: x = Lazard(x,y,n-1); return gdivexact(gmul(x,F),y);
! 1944: }
! 1945:
! 1946: static GEN
! 1947: addshift(GEN x, GEN y)
! 1948: {
! 1949: long v = varn(x);
! 1950: if (!signe(x)) return y;
! 1951: x = addshiftw(x,y,1);
! 1952: setvarn(x,v); return x;
! 1953: }
! 1954:
! 1955: static GEN
! 1956: nextSousResultant(GEN P, GEN Q, GEN Z, GEN s)
! 1957: {
! 1958: GEN p0, q0, z0, H, A;
! 1959: long p, q, j, av, lim, v = varn(P);
! 1960:
! 1961: z0 = leading_term(Z);
! 1962: p = degree(P); p0 = leading_term(P); P = reductum(P);
! 1963: q = degree(Q); q0 = leading_term(Q); Q = reductum(Q);
! 1964:
! 1965: av = avma; lim = stack_lim(av,1);
! 1966: H = gneg(reductum(Z));
! 1967: A = gmul((GEN)P[q+2],H);
! 1968: for (j = q+1; j < p; j++)
! 1969: {
! 1970: H = (degree(H) == q-1) ?
! 1971: addshift(reductum(H), gdivexact(gmul(gneg((GEN)H[q+1]),Q), q0)) :
! 1972: addshift(H, zeropol(v));
! 1973: A = gadd(A,gmul((GEN)P[j+2],H));
! 1974: if (low_stack(lim,stack_lim(av,1)))
! 1975: {
! 1976: GEN *gptr[2]; gptr[0]=&A; gptr[1]=&H;
! 1977: if(DEBUGMEM>1) err(warnmem,"nextSousResultant j = %ld/%ld",j,p);
! 1978: gerepilemany(av,gptr,2);
! 1979: }
! 1980: }
! 1981: P = normalizepol_i(P, q+2);
! 1982: A = gdivexact(gadd(A,gmul(z0,P)), p0);
! 1983: A = (degree(H) == q-1) ?
! 1984: gadd(gmul(q0,addshift(reductum(H),A)), gmul(gneg((GEN)H[q+1]),Q)) :
! 1985: gmul(q0, addshift(H,A));
! 1986: return gdivexact(A, ((p-q)&1)? s: gneg(s));
! 1987: }
! 1988:
! 1989: GEN
! 1990: resultantducos(GEN P, GEN Q)
! 1991: {
! 1992: long delta, av=avma, tetpil, lim = stack_lim(av,1);
! 1993: GEN Z, s;
! 1994:
! 1995: if ((Z = init_resultant(P,Q))) return Z;
! 1996: delta = degree(P) - degree(Q);
! 1997: if (delta < 0)
! 1998: {
! 1999: Z = ((degree(P)&1) && (degree(Q)&1)) ? gneg(Q) : Q;
! 2000: Q = P; P = Z; delta = -delta;
! 2001: }
! 2002: s = gun;
! 2003: if (degree(Q) > 0)
! 2004: {
! 2005: s = gpuigs(leading_term(Q),delta);
! 2006: Z = Q;
! 2007: Q = pseudorem(P, gneg(Q));
! 2008: P = Z;
! 2009: while(degree(Q) > 0)
! 2010: {
! 2011: if (low_stack(lim,stack_lim(av,1)))
! 2012: {
! 2013: GEN *gptr[2]; gptr[0]=&P; gptr[1]=&Q;
! 2014: if(DEBUGMEM>1) err(warnmem,"resultantducos, deg Q = %ld",degree(Q));
! 2015: gerepilemany(av,gptr,2); s = leading_term(P);
! 2016: }
! 2017: delta = degree(P) - degree(Q);
! 2018: Z = Lazard2(Q, leading_term(Q), s, delta);
! 2019: Q = nextSousResultant(P, Q, Z, s);
! 2020: P = Z;
! 2021: s = leading_term(P);
! 2022: }
! 2023: }
! 2024: if (!signe(Q)) { avma = av; return gzero; }
! 2025: s = Lazard(leading_term(Q), s, degree(P));
! 2026: tetpil = avma; return gerepile(av,tetpil,gcopy(s));
! 2027: }
! 2028:
! 2029: /*******************************************************************/
! 2030: /* */
! 2031: /* RESULTANT PAR MATRICE DE SYLVESTER */
! 2032: /* */
! 2033: /*******************************************************************/
! 2034: GEN
! 2035: sylvestermatrix_i(GEN x, GEN y)
! 2036: {
! 2037: long d,dx,dy,i,j;
! 2038: GEN p1,p2;
! 2039:
! 2040: dx=lgef(x)-3; dy=lgef(y)-3; d=dx+dy;
! 2041: p1=cgetg(d+1,t_MAT);
! 2042: for (j=1; j<=dy; j++)
! 2043: {
! 2044: p2=cgetg(d+1,t_COL); p1[j]=(long)p2;
! 2045: for (i=1; i<j; i++) p2[i]=zero;
! 2046: for ( ; i<=j+dx; i++) p2[i]=x[dx-i+j+2];
! 2047: for ( ; i<=d; i++) p2[i]=zero;
! 2048: }
! 2049: for (j=1; j<=dx; j++)
! 2050: {
! 2051: p2=cgetg(d+1,t_COL); p1[j+dy]=(long)p2;
! 2052: for (i=1; i<j; i++) p2[i]=zero;
! 2053: for ( ; i<=j+dy; i++) p2[i]=y[dy-i+j+2];
! 2054: for ( ; i<=d; i++) p2[i]=zero;
! 2055: }
! 2056: return p1;
! 2057: }
! 2058:
! 2059: GEN
! 2060: sylvestermatrix(GEN x, GEN y)
! 2061: {
! 2062: long i,j,lx;
! 2063: if (typ(x)!=t_POL || typ(y)!=t_POL) err(typeer,"sylvestermatrix");
! 2064: if (varn(x) != varn(y))
! 2065: err(talker,"not the same variables in sylvestermatrix");
! 2066: x = sylvestermatrix_i(x,y); lx = lg(x);
! 2067: for (i=1; i<lx; i++)
! 2068: for (j=1; j<lx; j++) coeff(x,i,j) = lcopy(gcoeff(x,i,j));
! 2069: return x;
! 2070: }
! 2071:
! 2072: GEN
! 2073: resultant2(GEN x, GEN y)
! 2074: {
! 2075: long av;
! 2076: GEN r;
! 2077: if ((r = init_resultant(x,y))) return r;
! 2078: av = avma; return gerepileupto(av,det(sylvestermatrix_i(x,y)));
! 2079: }
! 2080:
! 2081: static GEN
! 2082: fix_pol(GEN x, long v, long *mx)
! 2083: {
! 2084: long vx;
! 2085: GEN p1;
! 2086:
! 2087: if (typ(x) == t_POL)
! 2088: {
! 2089: vx = varn(x);
! 2090: if (vx)
! 2091: {
! 2092: if (v>=vx) return gsubst(x,v,polx[0]);
! 2093: p1 = cgetg(3,t_POL);
! 2094: p1[1] = evalvarn(0)|evalsigne(signe(x))|evallgef(3);
! 2095: p1[2] = (long)x; return p1;
! 2096: }
! 2097: if (v)
! 2098: {
! 2099: *mx = 1;
! 2100: return gsubst(gsubst(x,0,polx[MAXVARN]),v,polx[0]);
! 2101: }
! 2102: }
! 2103: return x;
! 2104: }
! 2105:
! 2106: /* resultant of x and y with respect to variable v, or with respect to their
! 2107: * main variable if v < 0.
! 2108: */
! 2109: GEN
! 2110: polresultant0(GEN x, GEN y, long v, long flag)
! 2111: {
! 2112: long av = avma, m = 0;
! 2113:
! 2114: if (v >= 0)
! 2115: {
! 2116: x = fix_pol(x,v, &m);
! 2117: y = fix_pol(y,v, &m);
! 2118: }
! 2119: switch(flag)
! 2120: {
! 2121: case 0: x=subresall(x,y,NULL); break;
! 2122: case 1: x=resultant2(x,y); break;
! 2123: case 2: x=resultantducos(x,y); break;
! 2124: default: err(flagerr,"polresultant");
! 2125: }
! 2126: if (m) x = gsubst(x,MAXVARN,polx[0]);
! 2127: return gerepileupto(av,x);
! 2128: }
! 2129:
! 2130: /*******************************************************************/
! 2131: /* */
! 2132: /* P.G.C.D PAR L'ALGORITHME DU SOUS RESULTANT */
! 2133: /* */
! 2134: /*******************************************************************/
! 2135:
! 2136: GEN
! 2137: srgcd(GEN x, GEN y)
! 2138: {
! 2139: long av,av1,tetpil,tx=typ(x),ty=typ(y),dx,dy,vx,lim;
! 2140: GEN d,g,h,p1,p2,u,v;
! 2141:
! 2142: if (!signe(y)) return gcopy(x);
! 2143: if (!signe(x)) return gcopy(y);
! 2144: if (is_scalar_t(tx) || is_scalar_t(ty)) return gun;
! 2145: if (tx!=t_POL || ty!=t_POL) err(typeer,"srgcd");
! 2146: vx=varn(x); if (vx!=varn(y)) return gun;
! 2147: if (ismonome(x)) return gcdmonome(x,y);
! 2148: if (ismonome(y)) return gcdmonome(y,x);
! 2149: if (isrational(x) && isrational(y)) return modulargcd(x,y);
! 2150:
! 2151: av=avma;
! 2152: if (issimplefield(x) || issimplefield(y)) x = polgcdnun(x,y);
! 2153: else
! 2154: {
! 2155: dx=lgef(x); dy=lgef(y);
! 2156: if (dx<dy) { p1=x; x=y; y=p1; tx=dx; dx=dy; dy=tx; }
! 2157: p1=content(x); p2=content(y); d=ggcd(p1,p2);
! 2158:
! 2159: tetpil=avma; d=gmul(d,polun[vx]);
! 2160: if (dy==3) return gerepile(av,tetpil,d);
! 2161:
! 2162: av1=avma; lim=stack_lim(av1,1);
! 2163: u=gdiv(x,p1); v=gdiv(y,p2); g=h=gun;
! 2164: for(;;)
! 2165: {
! 2166: GEN r = pseudorem(u,v);
! 2167: long degq, du, dv, dr=lgef(r);
! 2168:
! 2169: if (dr<=3)
! 2170: {
! 2171: if (gcmp0(r)) break;
! 2172: avma=av1; return gerepile(av,tetpil,d);
! 2173: }
! 2174: if (DEBUGLEVEL > 9) fprintferr("srgcd: dr = %ld\n", dr);
! 2175: du=lgef(u); dv=lgef(v); degq=du-dv; u=v;
! 2176: switch(degq)
! 2177: {
! 2178: case 0:
! 2179: v = gdiv(r,g);
! 2180: g = leading_term(u);
! 2181: break;
! 2182: case 1:
! 2183: v = gdiv(r,gmul(h,g));
! 2184: h = g = leading_term(u);
! 2185: break;
! 2186: default:
! 2187: v = gdiv(r,gmul(gpuigs(h,degq),g));
! 2188: g = leading_term(u);
! 2189: h = gdiv(gpuigs(g,degq), gpuigs(h,degq-1));
! 2190: }
! 2191: if (low_stack(lim, stack_lim(av1,1)))
! 2192: {
! 2193: GEN *gptr[4]; gptr[0]=&u; gptr[1]=&v; gptr[2]=&g; gptr[3]=&h;
! 2194: if(DEBUGMEM>1) err(warnmem,"srgcd");
! 2195: gerepilemany(av1,gptr,4);
! 2196: }
! 2197: }
! 2198: p1 = content(v); if (!gcmp1(p1)) v = gdiv(v,p1);
! 2199: x = gmul(d,v);
! 2200: }
! 2201:
! 2202: if (typ(x)!=t_POL) x = gmul(polun[vx],x);
! 2203: else
! 2204: {
! 2205: p1=leading_term(x); ty=typ(p1);
! 2206: if ((is_frac_t(ty) || is_intreal_t(ty)) && gsigne(p1)<0) x = gneg(x);
! 2207: }
! 2208: return gerepileupto(av,x);
! 2209: }
! 2210:
! 2211: GEN qf_disc(GEN x, GEN y, GEN z);
! 2212:
! 2213: GEN
! 2214: poldisc0(GEN x, long v)
! 2215: {
! 2216: long av,tx=typ(x),i;
! 2217: GEN z,p1,p2;
! 2218:
! 2219: switch(tx)
! 2220: {
! 2221: case t_POL:
! 2222: if (gcmp0(x)) return gzero;
! 2223: av = avma; i = 0;
! 2224: if (v >= 0 && v != varn(x)) x = fix_pol(x,v, &i);
! 2225: p1 = subres(x, derivpol(x));
! 2226: p2 = leading_term(x); if (!gcmp1(p2)) p1 = gdiv(p1,p2);
! 2227: if ((lgef(x)-3) & 2) p1 = gneg(p1);
! 2228: if (i) p1 = gsubst(p1, MAXVARN, polx[0]);
! 2229: return gerepileupto(av,p1);
! 2230:
! 2231: case t_COMPLEX:
! 2232: return stoi(-4);
! 2233:
! 2234: case t_QUAD: case t_POLMOD:
! 2235: return poldisc0((GEN)x[1], v);
! 2236:
! 2237: case t_QFR: case t_QFI:
! 2238: av = avma; return gerepileuptoint(av, qf_disc(x,NULL,NULL));
! 2239:
! 2240: case t_VEC: case t_COL: case t_MAT:
! 2241: i=lg(x); z=cgetg(i,tx);
! 2242: for (i--; i; i--) z[i]=(long)poldisc0((GEN)x[i], v);
! 2243: return z;
! 2244: }
! 2245: err(typeer,"discsr");
! 2246: return NULL; /* not reached */
! 2247: }
! 2248:
! 2249: GEN
! 2250: discsr(GEN x)
! 2251: {
! 2252: return poldisc0(x, -1);
! 2253: }
! 2254:
! 2255: GEN
! 2256: reduceddiscsmith(GEN pol)
! 2257: {
! 2258: long av=avma,tetpil,i,j,n;
! 2259: GEN polp,alpha,p1,m;
! 2260:
! 2261: if (typ(pol)!=t_POL) err(typeer,"reduceddiscsmith");
! 2262: n=lgef(pol)-3;
! 2263: if (n<=0) err(constpoler,"reduceddiscsmith");
! 2264: check_pol_int(pol);
! 2265: if (!gcmp1((GEN)pol[n+2]))
! 2266: err(talker,"non-monic polynomial in poldiscreduced");
! 2267: polp = derivpol(pol); alpha = polx[varn(pol)];
! 2268: m=cgetg(n+1,t_MAT);
! 2269: for (j=1; j<=n; j++)
! 2270: {
! 2271: p1=cgetg(n+1,t_COL); m[j]=(long)p1;
! 2272: for (i=1; i<=n; i++) p1[i]=(long)truecoeff(polp,i-1);
! 2273: if (j<n) polp = gres(gmul(alpha,polp), pol);
! 2274: }
! 2275: tetpil=avma; return gerepile(av,tetpil,smith(m));
! 2276: }
! 2277:
! 2278: /***********************************************************************/
! 2279: /** **/
! 2280: /** ALGORITHME DE STURM **/
! 2281: /** (number of real roots of x in ]a,b]) **/
! 2282: /** **/
! 2283: /***********************************************************************/
! 2284:
! 2285: /* if a (resp. b) is NULL, set it to -oo (resp. +oo) */
! 2286: long
! 2287: sturmpart(GEN x, GEN a, GEN b)
! 2288: {
! 2289: long av = avma,sl,sr,s,t,r1;
! 2290: GEN g,h,u,v;
! 2291:
! 2292: if (typ(x) != t_POL) err(typeer,"sturm");
! 2293: if (gcmp0(x)) err(zeropoler,"sturm");
! 2294: s=lgef(x); if (s==3) return 0;
! 2295:
! 2296: sl = gsigne(leading_term(x));
! 2297: if (s==4)
! 2298: {
! 2299: s = b? gsigne(poleval(x,b)): sl;
! 2300: t = a? gsigne(poleval(x,a)): -sl;
! 2301: avma = av; return (s == t)? 0: 1;
! 2302: }
! 2303: u=gdiv(x,content(x)); v=derivpol(x);
! 2304: v=gdiv(v,content(v));
! 2305: g=gun; h=gun;
! 2306: s = b? gsigne(poleval(u,b)): sl;
! 2307: t = a? gsigne(poleval(u,a)): ((lgef(u)&1)? sl: -sl);
! 2308: r1=0;
! 2309: sr = b? gsigne(poleval(v,b)): s;
! 2310: if (sr)
! 2311: {
! 2312: if (!s) s=sr;
! 2313: else if (sr!=s) { s= -s; r1--; }
! 2314: }
! 2315: sr = a? gsigne(poleval(v,a)): -t;
! 2316: if (sr)
! 2317: {
! 2318: if (!t) t=sr;
! 2319: else if (sr!=t) { t= -t; r1++; }
! 2320: }
! 2321: for(;;)
! 2322: {
! 2323: GEN p1, r = pseudorem(u,v);
! 2324: long du=lgef(u), dv=lgef(v), dr=lgef(r), degq=du-dv;
! 2325:
! 2326: if (dr<=2) err(talker,"not a squarefree polynomial in sturm");
! 2327: if (gsigne(leading_term(v)) > 0 || degq&1) r=gneg_i(r);
! 2328: sl = gsigne((GEN) r[dr-1]);
! 2329: sr = b? gsigne(poleval(r,b)): sl;
! 2330: if (sr)
! 2331: {
! 2332: if (!s) s=sr;
! 2333: else if (sr!=s) { s= -s; r1--; }
! 2334: }
! 2335: sr = a? gsigne(poleval(r,a)): ((dr&1)? sl: -sl);
! 2336: if (sr)
! 2337: {
! 2338: if (!t) t=sr;
! 2339: else if (sr!=t) { t= -t; r1++; }
! 2340: }
! 2341: if (dr==3) { avma=av; return r1; }
! 2342:
! 2343: u=v; p1 = g; g = gabs(leading_term(u),DEFAULTPREC);
! 2344: switch(degq)
! 2345: {
! 2346: case 0: break;
! 2347: case 1:
! 2348: p1 = gmul(h,p1); h = g; break;
! 2349: default:
! 2350: p1 = gmul(gpuigs(h,degq),p1);
! 2351: h = gdiv(gpuigs(g,degq), gpuigs(h,degq-1));
! 2352: }
! 2353: v = gdiv(r,p1);
! 2354: }
! 2355: }
! 2356:
! 2357: /*******************************************************************/
! 2358: /* */
! 2359: /* POLYNOME QUADRATIQUE ASSOCIE A UN DISCRIMINANT */
! 2360: /* */
! 2361: /*******************************************************************/
! 2362:
! 2363: GEN
! 2364: quadpoly0(GEN x, long v)
! 2365: {
! 2366: long res,l,tetpil,i,sx, tx = typ(x);
! 2367: GEN y,p1;
! 2368:
! 2369: if (is_matvec_t(tx))
! 2370: {
! 2371: l=lg(x); y=cgetg(l,tx);
! 2372: for (i=1; i<l; i++) y[i]=(long)quadpoly0((GEN)x[i],v);
! 2373: return y;
! 2374: }
! 2375: if (tx!=t_INT) err(arither1);
! 2376: if (v < 0) v = 0;
! 2377: sx=signe(x);
! 2378: if (!sx) err(talker,"zero discriminant in quadpoly");
! 2379: y=cgetg(5,t_POL);
! 2380: y[1]=evalsigne(1) | evalvarn(v) | evallgef(5); y[4]=un;
! 2381: res=mod4(x); if (sx<0 && res) res=4-res;
! 2382: if (res>1) err(funder2,"quadpoly");
! 2383:
! 2384: l=avma; p1=shifti(x,-2); setsigne(p1,-signe(p1));
! 2385: y[2] = (long) p1;
! 2386: if (!res) y[3] = zero;
! 2387: else
! 2388: {
! 2389: if (sx<0) { tetpil=avma; y[2] = lpile(l,tetpil,addsi(1,p1)); }
! 2390: y[3] = lnegi(gun);
! 2391: }
! 2392: return y;
! 2393: }
! 2394:
! 2395: GEN
! 2396: quadpoly(GEN x)
! 2397: {
! 2398: return quadpoly0(x,-1);
! 2399: }
! 2400:
! 2401: GEN
! 2402: quadgen(GEN x)
! 2403: {
! 2404: GEN y=cgetg(4,t_QUAD);
! 2405: y[1]=lquadpoly(x); y[2]=zero; y[3]=un; return y;
! 2406: }
! 2407:
! 2408: /*******************************************************************/
! 2409: /* */
! 2410: /* INVERSE MODULO GENERAL */
! 2411: /* */
! 2412: /*******************************************************************/
! 2413:
! 2414: GEN
! 2415: ginvmod(GEN x, GEN y)
! 2416: {
! 2417: long tx=typ(x);
! 2418:
! 2419: switch(typ(y))
! 2420: {
! 2421: case t_POL:
! 2422: if (tx==t_POL) return polinvmod(x,y);
! 2423: if (is_scalar_t(tx)) return ginv(x);
! 2424: break;
! 2425: case t_INT:
! 2426: if (tx==t_INT) return mpinvmod(x,y);
! 2427: if (tx==t_POL) return gzero;
! 2428: }
! 2429: err(typeer,"ginvmod");
! 2430: return NULL; /* not reached */
! 2431: }
! 2432:
! 2433: /***********************************************************************/
! 2434: /** **/
! 2435: /** NEWTON POLYGON **/
! 2436: /** **/
! 2437: /***********************************************************************/
! 2438:
! 2439: /* assume leading coeff of x is non-zero */
! 2440: GEN
! 2441: newtonpoly(GEN x, GEN p)
! 2442: {
! 2443: GEN y;
! 2444: long n,ind,a,b,c,u1,u2,r1,r2;
! 2445: long *vval, num[] = {evaltyp(t_INT) | m_evallg(3), 0, 0};
! 2446:
! 2447: if (typ(x)!=t_POL) err(typeer,"newtonpoly");
! 2448: n=lgef(x)-3; if (n<=0) { y=cgetg(1,t_VEC); return y; }
! 2449: y = cgetg(n+1,t_VEC); x += 2; /* now x[i] = term of degree i */
! 2450: vval = (long *) gpmalloc(sizeof(long)*(n+1));
! 2451: for (a=0; a<=n; a++) vval[a] = ggval((GEN)x[a],p);
! 2452: for (a=0, ind=1; a<n; a++)
! 2453: {
! 2454: if (vval[a] != VERYBIGINT) break;
! 2455: y[ind++] = lstoi(VERYBIGINT);
! 2456: }
! 2457: for (b=a+1; b<=n; a=b, b=a+1)
! 2458: {
! 2459: while (vval[b] == VERYBIGINT) b++;
! 2460: u1=vval[a]-vval[b]; u2=b-a;
! 2461: for (c=b+1; c<=n; c++)
! 2462: {
! 2463: if (vval[c] == VERYBIGINT) continue;
! 2464: r1=vval[a]-vval[c]; r2=c-a;
! 2465: if (u1*r2<=u2*r1) { u1=r1; u2=r2; b=c; }
! 2466: }
! 2467: while (ind<=b) { affsi(u1,num); y[ind++] = ldivgs(num,u2); }
! 2468: }
! 2469: free(vval); return y;
! 2470: }
! 2471:
! 2472: int cmp_pol(GEN x, GEN y);
! 2473:
! 2474: /* Factor polynomial a on the number field defined by polynomial t */
! 2475: GEN
! 2476: polfnf(GEN a, GEN t)
! 2477: {
! 2478: GEN x0, y,p1,p2,u,g,fa,n,unt;
! 2479: long av=avma,tetpil,lx,v,i,k,vt;
! 2480:
! 2481: if (typ(a)!=t_POL || typ(t)!=t_POL) err(typeer,"polfnf");
! 2482: if (gcmp0(a)) return gcopy(a);
! 2483: vt=varn(t); v=varn(a);
! 2484: if (vt<=v)
! 2485: err(talker,"polynomial variable must be of higher priority than number field variable\nin factornf");
! 2486: u = gdiv(a, ggcd(a,derivpol(a)));
! 2487: unt = gmodulsg(1,t); u = gmul(unt,u);
! 2488: g = lift(u);
! 2489: for (k=-1; ; k++)
! 2490: {
! 2491: n = gsub(polx[MAXVARN], gmulsg(k,polx[vt]));
! 2492: n = subres(t, poleval(g,n));
! 2493: if (lgef(ggcd(n,derivpol(n))) == 3) break;
! 2494: }
! 2495: fa=factor(n); fa=(GEN)fa[1]; lx=lg(fa);
! 2496: y=cgetg(3,t_MAT);
! 2497: p1=cgetg(lx,t_COL); y[1]=(long)p1;
! 2498: p2=cgetg(lx,t_COL); y[2]=(long)p2;
! 2499: x0 = gadd(polx[v],gmulsg(k,gmodulcp(polx[vt],t)));
! 2500: for (i=1; i<lx; i++)
! 2501: {
! 2502: GEN b, pro = ggcd(u, gmul(unt, poleval((GEN)fa[i], x0)));
! 2503: long e;
! 2504:
! 2505: p1[i] = (typ(pro)==t_POL)? ldiv(pro,leading_term(pro)): (long)pro;
! 2506: if (gcmp1((GEN)p1[i])) err(talker,"reducible modulus in factornf");
! 2507: e=0; while (poldivis(a,(GEN)p1[i], &b)) { a = b; e++; }
! 2508: p2[i] = lstoi(e);
! 2509: }
! 2510: (void)sort_factor(y, cmp_pol);
! 2511: tetpil=avma; return gerepile(av,tetpil,gcopy(y));
! 2512: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>