Annotation of OpenXM_contrib/pari/src/basemath/polarit2.c, Revision 1.1.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>