Annotation of OpenXM_contrib/pari-2.2/src/basemath/polarit2.c, Revision 1.1.1.1
1.1 noro 1: /* $Id: polarit2.c,v 1.120 2001/10/01 12:11:31 karim Exp $
2:
3: Copyright (C) 2000 The PARI group.
4:
5: This file is part of the PARI/GP package.
6:
7: PARI/GP is free software; you can redistribute it and/or modify it under the
8: terms of the GNU General Public License as published by the Free Software
9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
10: ANY WARRANTY WHATSOEVER.
11:
12: Check the License for details. You should have received a copy of it, along
13: with the package; see the file 'COPYING'. If not, write to the Free Software
14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
15:
16: /***********************************************************************/
17: /** **/
18: /** ARITHMETIC OPERATIONS ON POLYNOMIALS **/
19: /** (second part) **/
20: /** **/
21: /***********************************************************************/
22: #include "pari.h"
23:
24: #define swap(a,b) { GEN _x = a; a = b; b = _x; }
25: #define lswap(a,b) { long _x = a; a = b; b = _x; }
26: #define pswap(a,b) { GEN *_x = a; a = b; b = _x; }
27: #define both_even(a,b) ((((a)|(b))&1) == 0)
28:
29: GEN gassoc_proto(GEN f(GEN,GEN),GEN,GEN);
30:
31: GEN
32: polsym(GEN x, long n)
33: {
34: long av1,av2,dx=degpol(x),i,k;
35: GEN s,y,x_lead;
36:
37: if (n<0) err(impl,"polsym of a negative n");
38: if (typ(x) != t_POL) err(typeer,"polsym");
39: if (!signe(x)) err(zeropoler,"polsym");
40: y=cgetg(n+2,t_COL); y[1]=lstoi(dx);
41: x_lead=(GEN)x[dx+2]; if (gcmp1(x_lead)) x_lead=NULL;
42: for (k=1; k<=n; k++)
43: {
44: av1=avma; s = (dx>=k)? gmulsg(k,(GEN)x[dx+2-k]): gzero;
45: for (i=1; i<k && i<=dx; i++)
46: s = gadd(s,gmul((GEN)y[k-i+1],(GEN)x[dx+2-i]));
47: if (x_lead) s = gdiv(s,x_lead);
48: av2=avma; y[k+1]=lpile(av1,av2,gneg(s));
49: }
50: return y;
51: }
52:
53: static int (*polcmp_coeff_cmp)(GEN,GEN);
54:
55: /* assume x and y are polynomials in the same variable whose coeffs can be
56: * compared (used to sort polynomial factorizations)
57: */
58: static int
59: polcmp(GEN x, GEN y)
60: {
61: long i, lx = lgef(x), ly = lgef(y);
62: int fl;
63: #if 0 /* for efficiency */
64: if (typ(x) != t_POL || typ(y) != t_POL)
65: err(talker,"not a polynomial in polcmp");
66: #endif
67: if (lx > ly) return 1;
68: if (lx < ly) return -1;
69: for (i=lx-1; i>1; i--)
70: if ((fl = polcmp_coeff_cmp((GEN)x[i], (GEN)y[i]))) return fl;
71: return 0;
72: }
73:
74: /* sort polynomial factorization so that factors appear by decreasing
75: * degree, sorting coefficients according to cmp. In place */
76: GEN
77: sort_factor(GEN y, int (*cmp)(GEN,GEN))
78: {
79: int (*old)(GEN,GEN) = polcmp_coeff_cmp;
80: polcmp_coeff_cmp = cmp;
81: (void)sort_factor_gen(y,polcmp);
82: polcmp_coeff_cmp = old; return y;
83: }
84:
85: /* sort generic factorisation */
86: GEN
87: sort_factor_gen(GEN y, int (*cmp)(GEN,GEN))
88: {
89: long n,i, av = avma;
90: GEN a,b,A,B,w;
91: a = (GEN)y[1]; n = lg(a); A = new_chunk(n);
92: b = (GEN)y[2]; B = new_chunk(n);
93: w = gen_sort(a, cmp_IND | cmp_C, cmp);
94: for (i=1; i<n; i++) { A[i] = a[w[i]]; B[i] = b[w[i]]; }
95: for (i=1; i<n; i++) { a[i] = A[i]; b[i] = B[i]; }
96: avma = av; return y;
97: }
98:
99: /* for internal use */
100: GEN
101: centermod_i(GEN x, GEN p, GEN ps2)
102: {
103: long av,i,lx;
104: GEN y,p1;
105:
106: if (!ps2) ps2 = shifti(p,-1);
107: switch(typ(x))
108: {
109: case t_INT:
110: y=modii(x,p);
111: if (cmpii(y,ps2)>0) return subii(y,p);
112: return y;
113:
114: case t_POL: lx=lgef(x);
115: y=cgetg(lx,t_POL); y[1]=x[1];
116: for (i=2; i<lx; i++)
117: {
118: av=avma; p1=modii((GEN)x[i],p);
119: if (cmpii(p1,ps2)>0) p1=subii(p1,p);
120: y[i]=lpileupto(av,p1);
121: }
122: return y;
123:
124: case t_COL: lx=lg(x);
125: y=cgetg(lx,t_COL);
126: for (i=1; i<lx; i++)
127: {
128: p1=modii((GEN)x[i],p);
129: if (cmpii(p1,ps2)>0) p1=subii(p1,p);
130: y[i]=(long)p1;
131: }
132: return y;
133: }
134: return x;
135: }
136:
137: GEN
138: centermod(GEN x, GEN p) { return centermod_i(x,p,NULL); }
139:
140: /* assume same variables, y normalized, non constant */
141: static GEN
142: polidivis(GEN x, GEN y, GEN bound)
143: {
144: long dx,dy,dz,i,j,av, vx = varn(x);
145: GEN z,p1,y_lead;
146:
147: dy=degpol(y);
148: dx=degpol(x);
149: dz=dx-dy; if (dz<0) return NULL;
150: z=cgetg(dz+3,t_POL);
151: x += 2; y += 2; z += 2;
152: y_lead = (GEN)y[dy];
153: if (gcmp1(y_lead)) y_lead = NULL;
154:
155: p1 = (GEN)x[dx];
156: z[dz]=y_lead? ldivii(p1,y_lead): licopy(p1);
157: for (i=dx-1; i>=dy; i--)
158: {
159: av=avma; p1=(GEN)x[i];
160: for (j=i-dy+1; j<=i && j<=dz; j++)
161: p1 = subii(p1, mulii((GEN)z[j],(GEN)y[i-j]));
162: if (y_lead) { p1 = gdiv(p1,y_lead); if (typ(p1)!=t_INT) return NULL; }
163: if (absi_cmp(p1, bound) > 0) return NULL;
164: p1 = gerepileupto(av,p1);
165: z[i-dy] = (long)p1;
166: }
167: av = avma;
168: for (;; i--)
169: {
170: p1 = (GEN)x[i];
171: /* we always enter this loop at least once */
172: for (j=0; j<=i && j<=dz; j++)
173: p1 = subii(p1, mulii((GEN)z[j],(GEN)y[i-j]));
174: if (!gcmp0(p1)) return NULL;
175: avma = av;
176: if (!i) break;
177: }
178: z -= 2;
179: z[1]=evalsigne(1) | evallgef(dz+3) | evalvarn(vx);
180: return z;
181: }
182:
183: static long
184: min_deg(long jmax,ulong tabbit[])
185: {
186: long j, k = 1, j1 = 2;
187:
188: for (j=jmax; j>=0; j--)
189: {
190: for ( ; k<=15; k++)
191: {
192: if (tabbit[j]&j1) return ((jmax-j)<<4)+k;
193: j1<<=1;
194: }
195: k = 0; j1 = 1;
196: }
197: return (jmax<<4)+15;
198: }
199:
200: /* tabkbit is a bit vector (only lowest 32 bits of each word are used
201: * on 64bit architecture): reading from right to left, bit i+1 is set iff
202: * degree i is attainable from the factorisation mod p.
203: *
204: * record N modular factors of degree d. */
205: static void
206: record_factors(long N, long d, long jmax, ulong *tabkbit, ulong *tmp)
207: {
208: long n,j, a = d>>4, b = d&15; /* d = 16 a + b */
209: ulong *tmp2 = tmp - a;
210:
211: for (n = 1; n <= N; n++)
212: {
213: ulong pro, rem = 0;
214: for (j=jmax; j>=a; j--)
215: {
216: pro = tabkbit[j] << b;
217: tmp2[j] = (pro&0xffff) + rem; rem = pro >> 16;
218: }
219: for (j=jmax-a; j>=0; j--) tabkbit[j] |= tmp[j];
220: }
221: }
222:
223: /***********************************************************************/
224: /** **/
225: /** QUADRATIC HENSEL LIFT (adapted from V. Shoup's NTL) **/
226: /** **/
227: /***********************************************************************/
228: /* Setup for divide/conquer quadratic Hensel lift
229: * a = set of k t_POL in Z[X] corresponding to factors over Fp
230: * V = set of products of factors built as follows
231: * 1) V[1..k] = initial a
232: * 2) iterate:
233: * append to V the two smallest factors (minimal degree) in a, remove them
234: * from a and replace them by their product [net loss for a = 1 factor]
235: *
236: * W = bezout coeffs W[i]V[i] + W[i+1]V[i+1] = 1
237: *
238: * link[i] = -j if V[i] = a[j]
239: * j if V[i] = V[j] * V[j+1]
240: * Arrays (link, V, W) pre-allocated for 2k - 2 elements */
241: #if 0 /* restricted to Fp */
242: static void
243: BuildTree(GEN link, GEN V, GEN W, GEN a, GEN p)
244: {
245: long k = lg(a)-1;
246: long i, j, s, minp, mind;
247:
248: for (i=1; i<=k; i++) { V[i] = a[i]; link[i] = -i; }
249:
250: for (j=1; j <= 2*k-5; j+=2,i++)
251: {
252: minp = j;
253: mind = degpol(V[j]);
254: for (s=j+1; s<i; s++)
255: if (degpol(V[s]) < mind) { minp = s; mind = degpol(V[s]); }
256:
257: lswap(V[j], V[minp]);
258: lswap(link[j], link[minp]);
259:
260: minp = j+1;
261: mind = degpol(V[j+1]);
262: for (s=j+2; s<i; s++)
263: if (degpol(V[s]) < mind) { minp = s; mind = degpol(V[s]); }
264:
265: lswap(V[j+1], V[minp]);
266: lswap(link[j+1], link[minp]);
267:
268: V[i] = (long)FpX_mul((GEN)V[j], (GEN)V[j+1], p);
269: link[i] = j;
270: }
271:
272: for (j=1; j <= 2*k-3; j+=2)
273: {
274: GEN d, u, v;
275: d = FpX_extgcd((GEN)V[j], (GEN)V[j+1], p, &u, &v);
276: if (degpol(d) > 0) err(talker, "relatively prime polynomials expected");
277: d = (GEN)d[2];
278: if (!gcmp1(d))
279: {
280: d = mpinvmod(d, p);
281: u = FpX_Fp_mul(u, d, p);
282: v = FpX_Fp_mul(v, d, p);
283: }
284: W[j] = (long)u;
285: W[j+1] = (long)v;
286: }
287: }
288: #endif
289:
290: /* same over Fp[Y] / (T) [copy-paste] */
291: static void
292: BuildTree(GEN link, GEN V, GEN W, GEN a, GEN T, GEN p)
293: {
294: long k = lg(a)-1;
295: long i, j, s, minp, mind;
296:
297: for (i=1; i<=k; i++) { V[i] = a[i]; link[i] = -i; }
298:
299: for (j=1; j <= 2*k-5; j+=2,i++)
300: {
301: minp = j;
302: mind = degpol(V[j]);
303: for (s=j+1; s<i; s++)
304: if (degpol(V[s]) < mind) { minp = s; mind = degpol(V[s]); }
305:
306: lswap(V[j], V[minp]);
307: lswap(link[j], link[minp]);
308:
309: minp = j+1;
310: mind = degpol(V[j+1]);
311: for (s=j+2; s<i; s++)
312: if (degpol(V[s]) < mind) { minp = s; mind = degpol(V[s]); }
313:
314: lswap(V[j+1], V[minp]);
315: lswap(link[j+1], link[minp]);
316:
317: V[i] = (long)FpXQX_mul((GEN)V[j], (GEN)V[j+1], T, p);
318: link[i] = j;
319: }
320:
321: for (j=1; j <= 2*k-3; j+=2)
322: {
323: GEN d, u, v;
324: d = FpXQX_extgcd((GEN)V[j], (GEN)V[j+1], T, p, &u, &v);
325: if (degpol(d) > 0) err(talker, "relatively prime polynomials expected");
326: d = (GEN)d[2];
327: if (!gcmp1(d))
328: {
329: d = FpXQ_inv(d, T, p);
330: u = FpXQX_FpXQ_mul(u, d, T, p);
331: v = FpXQX_FpXQ_mul(v, d, T, p);
332: }
333: W[j] = (long)u;
334: W[j+1] = (long)v;
335: }
336: }
337:
338: /* au + bv = 1 (p0), ab = f (p0). Lift mod p1 = p0 pd (<= p0^2).
339: * If noinv is set, don't lift the inverses u and v */
340: static void
341: HenselLift(GEN V, GEN W, long j, GEN f, GEN T, GEN pd, GEN p0, int noinv)
342: {
343: ulong av = avma;
344: long space = lgef(f) * (lgefint(pd) + lgefint(p0) - 2);
345: GEN a2,b2,g,z,s,t;
346: GEN a = (GEN)V[j], b = (GEN)V[j+1];
347: GEN u = (GEN)W[j], v = (GEN)W[j+1];
348:
349: if (T) space *= lgef(T);
350:
351: (void)new_chunk(space); /* HACK */
352: g = gadd(f, gneg_i(gmul(a,b)));
353: if (T) g = FpXQX_red(g, T, mulii(p0,pd));
354: g = gdivexact(g, p0); g = FpXQX_red(g, NULL, pd);
355: z = FpXQX_mul(v,g, T,pd);
356: t = FpXQX_divres(z,a, T,pd, &s);
357: t = gadd(gmul(u,g), gmul(t,b)); t = FpXQX_red(t, T, pd);
358: t = gmul(t,p0);
359: s = gmul(s,p0);
360: avma = av;
361:
362: /* already reduced mod p1 = pd p0 */
363: a2 = gadd(a,s); V[j] = (long)a2;
364: b2 = gadd(b,t); V[j+1] = (long)b2;
365: if (noinv) return;
366:
367: av = avma;
368: (void)new_chunk(space); /* HACK */
369: g = gadd(gmul(u,a2), gmul(v,b2));
370: g = gadd(gneg_i(g), gun);
371:
372: if (T) g = FpXQX_red(g, T, mulii(p0,pd));
373: g = gdivexact(g, p0); g = FpXQX_red(g, NULL, pd);
374: z = FpXQX_mul(v,g, T,pd);
375: t = FpXQX_divres(z,a, T,pd, &s);
376: t = gadd(gmul(u,g), gmul(t,b)); t = FpXQX_red(t, T, pd);
377: t = gmul(t,p0);
378: s = gmul(s,p0);
379: avma = av;
380:
381: u = gadd(u,t); W[j] = (long)u;
382: v = gadd(v,s); W[j+1] = (long)v;
383: }
384:
385: /* v list of factors, w list of inverses. f = v[j] v[j+1]
386: * Lift v[j] and v[j+1] mod p0 pd (possibly mod T), then all their divisors */
387: static void
388: RecTreeLift(GEN link, GEN v, GEN w, GEN T, GEN pd, GEN p0, GEN f, long j, int noinv)
389: {
390: if (j < 0) return;
391:
392: HenselLift(v, w, j, f, T, pd, p0, noinv);
393: RecTreeLift(link, v, w, T, pd, p0, (GEN)v[j] , link[j ], noinv);
394: RecTreeLift(link, v, w, T, pd, p0, (GEN)v[j+1], link[j+1], noinv);
395: }
396:
397: /* lift from p^{e0} to p^{e1} */
398: static void
399: TreeLift(GEN link, GEN v, GEN w, GEN T, GEN p, long e0, long e1, GEN f, int noinv)
400: {
401: GEN p0 = gpowgs(p, e0);
402: GEN pd = gpowgs(p, e1-e0);
403: RecTreeLift(link, v, w, T, pd, p0, f, lg(v)-2, noinv);
404: }
405:
406: /* a = modular factors of f mod (p,T) [possibly T=NULL], lift to precision p^e0
407: * flag = 0: standard.
408: * flag = 1: return TreeLift structure
409: * flag = 2: a = TreeLift structure, go on lifting, as flag = 1 otherwise */
410: static GEN
411: MultiLift(GEN f, GEN a, GEN T, GEN p, long e0, int flag)
412: {
413: long l, i, e = e0, k = lg(a) - 1;
414: GEN E, v, w, link;
415:
416: if (k < 2 || e < 1) err(talker, "MultiLift: bad args");
417: if (e == 1) return a;
418: if (typ(a[1]) == t_INT) flag = 2;
419: else if (flag == 2) flag = 1;
420:
421: E = cgetg(BITS_IN_LONG, t_VECSMALL);
422: l = 0; E[++l] = e;
423: while (e > 1) { e = (e+1)/2; E[++l] = e; }
424:
425: if (DEBUGLEVEL > 3) timer2();
426:
427: if (flag != 2)
428: {
429: v = cgetg(2*k - 2 + 1, t_VEC);
430: w = cgetg(2*k - 2 + 1, t_VEC);
431: link=cgetg(2*k - 2 + 1, t_VECSMALL);
432: BuildTree(link, v, w, a, T, p);
433: if (DEBUGLEVEL > 3) msgtimer("building tree");
434: }
435: else
436: {
437: e = itos((GEN)a[1]);
438: link = (GEN)a[2];
439: v = (GEN)a[3];
440: w = (GEN)a[4];
441: }
442:
443: for (i = l; i > 1; i--) {
444: if (E[i-1] < e) continue;
445: TreeLift(link, v, w, T, p, E[i], E[i-1], f, (flag == 0) && (i == 2));
446: if (DEBUGLEVEL > 3) msgtimer("lifting to prec %ld", E[i-1]);
447: }
448:
449: if (flag)
450: {
451: E = cgetg(4, t_VEC);
452: E[1] = lstoi(e0);
453: E[2] = (long)link;
454: E[3] = (long)v;
455: E[4] = (long)w;
456: }
457: else
458: {
459: E = cgetg(k+1, t_VEC);
460: for (i = 1; i <= 2*k-2; i++)
461: {
462: long t = link[i];
463: if (t < 0) E[-t] = v[i];
464: }
465: }
466: return E;
467: }
468:
469: /* Q list of (coprime, monic) factors of pol mod (T,p). Lift mod p^e = pe.
470: * T may be NULL */
471: GEN
472: hensel_lift_fact(GEN pol, GEN Q, GEN T, GEN p, GEN pe, long e)
473: {
474: if (lg(Q) == 2) { GEN d = cgetg(2, t_VEC); d[1] = (long)pol; return d; }
475: pol = FpXQX_normalize(pol, T, pe);
476: return MultiLift(pol, Q, T, p, e, 0);
477: }
478:
479: /* U = NULL treated as 1 */
480: static void
481: BezoutPropagate(GEN link, GEN v, GEN w, GEN pe, GEN U, GEN f, long j)
482: {
483: GEN Q, R;
484: if (j < 0) return;
485:
486: Q = FpX_mul((GEN)v[j], (GEN)w[j], pe);
487: if (U)
488: {
489: Q = FpXQ_mul(Q, U, f, pe);
490: R = FpX_sub(U, Q, pe);
491: }
492: else
493: R = FpX_Fp_add(FpX_neg(Q, pe), gun, pe);
494: w[j+1] = (long)Q; /* 0 mod U v[j], 1 mod (1-U) v[j+1] */
495: w[j ] = (long)R; /* 1 mod U v[j], 0 mod (1-U) v[j+1] */
496: BezoutPropagate(link, v, w, pe, R, f, link[j ]);
497: BezoutPropagate(link, v, w, pe, Q, f, link[j+1]);
498: }
499:
500: /* as above, but return the Bezout coefficients for the lifted modular factors
501: * U[i] = 1 mod Qlift[i]
502: * 0 mod Qlift[j], j != i */
503: GEN
504: bezout_lift_fact(GEN pol, GEN Q, GEN p, long e)
505: {
506: GEN E, link, v, w, pe;
507: long i, k = lg(Q)-1;
508: if (k == 1) { GEN d = cgetg(2, t_VEC); d[1] = (long)pol; return d; }
509: pe = gpowgs(p, e);
510: pol = FpX_normalize(pol, pe);
511: E = MultiLift(pol, Q, NULL, p, e, 1);
512: link = (GEN) E[2];
513: v = (GEN) E[3];
514: w = (GEN) E[4];
515: BezoutPropagate(link, v, w, pe, NULL, pol, lg(v) - 2);
516: E = cgetg(k+1, t_VEC);
517: for (i = 1; i <= 2*k-2; i++)
518: {
519: long t = link[i];
520: if (t < 0) E[-t] = w[i];
521: }
522: return gcopy(E);
523: }
524:
525: /* Front-end for hensel_lift_fact:
526: lift the factorization of pol mod p given by fct to p^exp (if possible) */
527: GEN
528: polhensellift(GEN pol, GEN fct, GEN p, long exp)
529: {
530: GEN p1, p2;
531: long av = avma, i, j, l;
532:
533: /* we check the arguments */
534: if (typ(pol) != t_POL)
535: err(talker, "not a polynomial in polhensellift");
536: if ((typ(fct) != t_COL && typ(fct) != t_VEC) || (lg(fct) < 3))
537: err(talker, "not a factorization in polhensellift");
538: if (typ(p) != t_INT || !isprime(p))
539: err(talker, "not a prime number in polhensellift");
540: if (exp < 1)
541: err(talker, "not a positive exponent in polhensellift");
542:
543: p1 = lift(fct); /* make sure the coeffs are integers and not intmods */
544: l = lg(p1) - 1;
545: for (i=1; i<=l; i++)
546: {
547: p2 = (GEN)p1[i];
548: if (typ(p2) != t_POL)
549: {
550: if (typ(p2) != t_INT)
551: err(talker, "not an integral factorization in polhensellift");
552: p1[i] = (long)scalarpol(p2, varn(pol));
553: }
554: }
555:
556: /* then we check that pol \equiv \prod f ; f \in fct mod p */
557: p2 = (GEN)p1[1];
558: for (j = 2; j <= l; j++) p2 = FpX_mul(p2, (GEN)p1[j], p);
559: if (!gcmp0(FpX_sub(pol, p2, p)))
560: err(talker, "not a correct factorization in polhensellift");
561:
562: /* finally we check that the elements of fct are coprime mod p */
563: if (!FpX_is_squarefree(pol, p))
564: {
565: for (i = 1; i <= l; i++)
566: for (j = 1; j < i; j++)
567: if (lgef(FpX_gcd((GEN)p1[i], (GEN)p1[j], p)) != 3)
568: err(talker, "polhensellift: factors %Z and %Z are not coprime",
569: p1[i], p1[j]);
570: }
571: return gerepilecopy(av, hensel_lift_fact(pol,p1,NULL,p,gpowgs(p,exp),exp));
572: }
573:
574: #if 0
575: /* cf Beauzamy et al: upper bound for
576: * lc(x) * [2^(5/8) / pi^(3/8)] e^(1/4n) 2^(n/2) sqrt([x]_2)/ n^(3/8)
577: * where [x]_2 = sqrt(\sum_i=0^n x[i]^2 / binomial(n,i)). One factor has
578: * all coeffs less than then bound */
579: static GEN
580: two_factor_bound(GEN x)
581: {
582: long av = avma, i,j, n = lgef(x) - 3;
583: GEN *invbin, c, r = cgetr(3), z;
584:
585: x += 2; invbin = (GEN*)new_chunk(n+1);
586: z = realun(3); /* invbin[i] = 1 / binomial(n, i) */
587: for (i=0,j=n; j >= i; i++,j--)
588: {
589: invbin[i] = invbin[j] = z;
590: z = divrs(mulrs(z, i+1), n-i);
591: }
592: z = invbin[0]; /* = 1 */
593: for (i=0; i<=n; i++)
594: {
595: c = (GEN)x[i]; if (!signe(c)) continue;
596: affir(c, r);
597: z = addrr(z, mulrr(gsqr(r), invbin[i]));
598: }
599: z = shiftr(mpsqrt(z), n);
600: z = divrr(z, dbltor(pow((double)n, 0.75)));
601: z = grndtoi(mpsqrt(z), &i);
602: z = mulii(z, absi((GEN)x[n]));
603: return gerepileuptoint(av, shifti(z, 1));
604: }
605: #endif
606:
607: static GEN
608: uniform_Mignotte_bound(GEN x)
609: {
610: long e, n = degpol(x);
611: GEN p1, N2 = mpsqrt(QuickNormL2(x,DEFAULTPREC));
612:
613: p1 = grndtoi(gmul2n(N2, n), &e);
614: if (e>=0) p1 = addii(p1, shifti(gun, e));
615: return p1;
616: }
617:
618: /* all factors have coeffs less than the bound */
619: static GEN
620: all_factor_bound(GEN x)
621: {
622: long i, n = lgef(x) - 3;
623: GEN t, z = gzero;
624: for (i=2; i<=n+2; i++) z = addii(z,sqri((GEN)x[i]));
625: t = absi((GEN)x[n+2]);
626: z = addii(t, addsi(1, racine(z)));
627: z = mulii(z, binome(stoi(n-1), n>>1));
628: return shifti(mulii(t,z),1);
629: }
630:
631: /* x defined mod p^a, return mods ( (x - mods(x, p^b)) / p^b , p^(b-a) ) */
632: static GEN
633: TruncTrace(GEN x, GEN pb, GEN pa_b, GEN pa_bs2, GEN pbs2)
634: {
635: GEN r, q = dvmdii(x, pb, &r);
636: if (cmpii(r, pbs2) > 0) q = addis(q,1);
637: if (pa_bs2 && cmpii(q,pa_bs2) > 0) q = subii(q,pa_b);
638: return q;
639: }
640:
641: /* Naive recombination of modular factors: combine up to maxK modular
642: * factors, degree <= klim and divisible by hint
643: *
644: * target = polynomial we want to factor
645: * famod = array of modular factors. Product should be congruent to
646: * target/lc(target) modulo p^a
647: * All rational factors are bounded by p^b, b <= a and p^(b-a) < 2^(BIL-1) */
648: static GEN
649: cmbf(GEN target, GEN famod, GEN p, long b, long a,
650: long maxK, long klim,long hint)
651: {
652: long K = 1, cnt = 1, i,j,k, curdeg, lfamod = lg(famod)-1;
653: long spa_b, spa_bs2;
654: GEN lc, lctarget, pa = gpowgs(p,a), pas2 = shifti(pa,-1);
655: GEN trace = cgetg(lfamod+1, t_VECSMALL);
656: GEN ind = cgetg(lfamod+1, t_VECSMALL);
657: GEN degpol = cgetg(lfamod+1, t_VECSMALL);
658: GEN degsofar = cgetg(lfamod+1, t_VECSMALL);
659: GEN listmod = cgetg(lfamod+1, t_COL);
660: GEN fa = cgetg(lfamod+1, t_COL);
661: GEN res = cgetg(3, t_VEC);
662: GEN bound = all_factor_bound(target);
663:
664: if (maxK < 0) maxK = lfamod-1;
665:
666: lc = absi(leading_term(target));
667: lctarget = gmul(lc,target);
668:
669: {
670: GEN pa_b,pa_bs2,pb,pbs2;
671: pa_b = gpowgs(p, a-b); /* make sure p^(a-b) < 2^(BIL-1) */
672: while (is_bigint(pa_b)) { b++; pa_b = divii(pa_b, p); }
673: pa_bs2 = shifti(pa_b,-1);
674: pb= gpowgs(p, b); pbs2 = shifti(pb,-1);
675: for (i=1; i <= lfamod; i++)
676: {
677: GEN T, p1 = (GEN)famod[i];
678: degpol[i] = degpol(p1);
679: if (!gcmp1(lc))
680: T = modii(mulii(lc, (GEN)p1[degpol[i]+1]), pa);
681: else
682: T = (GEN)p1[degpol[i]+1]; /* d-1 term */
683: trace[i] = itos( TruncTrace(T, pb,pa_b,NULL,pbs2) );
684: }
685: spa_b = pa_b[2]; /* < 2^(BIL-1) */
686: spa_bs2 = pa_bs2[2]; /* < 2^(BIL-1) */
687: }
688: degsofar[0] = 0; /* sentinel */
689:
690: /* ind runs through strictly increasing sequences of length K,
691: * 1 <= ind[i] <= lfamod */
692: nextK:
693: if (K > maxK || 2*K > lfamod) goto END;
694: if (DEBUGLEVEL > 4)
695: fprintferr("\n### K = %d, %Z combinations\n", K,binome(stoi(lfamod), K));
696: setlg(ind, K+1); ind[1] = 1;
697: i = 1; curdeg = degpol[ind[1]];
698: for(;;)
699: { /* try all combinations of K factors */
700: for (j = i; j < K; j++)
701: {
702: degsofar[j] = curdeg;
703: ind[j+1] = ind[j]+1; curdeg += degpol[ind[j+1]];
704: }
705: if (curdeg <= klim && curdeg % hint == 0) /* trial divide */
706: {
707: GEN y, q, cont, list;
708: ulong av;
709: long t;
710:
711: /* d - 1 test, overflow is not a problem (correct mod 2^BIL) */
712: for (t=trace[ind[1]],i=2; i<=K; i++)
713: t = addssmod(t, trace[ind[i]], spa_b);
714: if (t > spa_bs2) t -= spa_b;
715: if (labs(t) > ((K+1)>>1))
716: {
717: if (DEBUGLEVEL>6) fprintferr(".");
718: goto NEXT;
719: }
720: av = avma;
721:
722: /* check trailing coeff */
723: y = lc;
724: for (i=1; i<=K; i++)
725: y = centermod_i(mulii(y, gmael(famod,ind[i],2)), pa, pas2);
726: if (!signe(y) || resii((GEN)lctarget[2], y) != gzero)
727: {
728: if (DEBUGLEVEL>6) fprintferr("T");
729: avma = av; goto NEXT;
730: }
731: y = lc; /* full computation */
732: for (i=1; i<=K; i++)
733: y = centermod_i(gmul(y, (GEN)famod[ind[i]]), pa, pas2);
734:
735: /* y is the candidate factor */
736: if (! (q = polidivis(lctarget,y,bound)) )
737: {
738: if (DEBUGLEVEL>6) fprintferr("*");
739: avma = av; goto NEXT;
740: }
741: /* found a factor */
742: cont = content(y);
743: if (signe(leading_term(y)) < 0) cont = negi(cont);
744: y = gdiv(y, cont);
745:
746: list = cgetg(K+1, t_VEC);
747: listmod[cnt] = (long)list;
748: for (i=1; i<=K; i++) list[i] = famod[ind[i]];
749:
750: fa[cnt++] = (long)y;
751: /* fix up target */
752: target = gdiv(q, leading_term(y));
753: for (i=j=k=1; i <= lfamod; i++)
754: { /* remove used factors */
755: if (j <= K && i == ind[j]) j++;
756: else
757: {
758: famod[k] = famod[i];
759: trace[k] = trace[i];
760: degpol[k] = degpol[i]; k++;
761: }
762: }
763: lfamod -= K;
764: if (lfamod < 2*K) goto END;
765: i = 1; curdeg = degpol[ind[1]];
766: bound = all_factor_bound(target);
767: lc = absi(leading_term(target));
768: lctarget = gmul(lc,target);
769: if (DEBUGLEVEL > 2)
770: {
771: fprintferr("\n"); msgtimer("to find factor %Z",y);
772: fprintferr("remaining modular factor(s): %ld\n", lfamod);
773: }
774: continue;
775: }
776:
777: NEXT:
778: for (i = K+1;;)
779: {
780: if (--i == 0) { K++; goto nextK; }
781: if (++ind[i] <= lfamod - K + i)
782: {
783: curdeg = degsofar[i-1] + degpol[ind[i]];
784: if (curdeg <= klim) break;
785: }
786: }
787: }
788: END:
789: if (degpol(target) > 0)
790: { /* leftover factor */
791: if (signe(leading_term(target)) < 0) target = gneg_i(target);
792:
793: setlg(famod, lfamod+1);
794: listmod[cnt] = (long)dummycopy(famod);
795: fa[cnt++] = (long)target;
796: }
797: if (DEBUGLEVEL>6) fprintferr("\n");
798: setlg(listmod, cnt); setlg(fa, cnt);
799: res[1] = (long)fa;
800: res[2] = (long)listmod; return res;
801: }
802:
803: void
804: factor_quad(GEN x, GEN res, long *ptcnt)
805: {
806: GEN a = (GEN)x[4], b = (GEN)x[3], c = (GEN)x[2], d, u, z1, z2, t;
807: GEN D = subii(sqri(b), shifti(mulii(a,c), 2));
808: long v, cnt = *ptcnt;
809:
810: if (!carrecomplet(D, &d)) { res[cnt++] = (long)x; *ptcnt = cnt; return; }
811:
812: t = shifti(negi(addii(b, d)), -1);
813: z1 = gdiv(t, a); u = denom(z1);
814: z2 = gdiv(addii(t, d), a);
815: v = varn(x);
816: res[cnt++] = lmul(u, gsub(polx[v], z1)); u = divii(a, u);
817: res[cnt++] = lmul(u, gsub(polx[v], z2)); *ptcnt = cnt;
818: }
819:
820: /* y > 1 and B integers. Let n such that y^(n-1) <= B < y^n.
821: * Return e = max(n,1), set *ptq = y^e if non-NULL */
822: long
823: logint(GEN B, GEN y, GEN *ptq)
824: {
825: ulong av = avma;
826: long e,i,fl;
827: GEN q,pow2, r = y;
828:
829: if (typ(B) != t_INT) B = ceil_safe(B);
830: if (expi(B) <= (expi(y) << 6)) /* e small, be naive */
831: {
832: for (e=1; cmpii(r, B) < 0; e++) r = mulii(r,y);
833: goto END;
834: }
835: /* binary splitting: compute bits of e one by one */
836: /* compute pow2[i] = y^(2^i) [i < very crude upper bound for log_2(n)] */
837: pow2 = new_chunk(bit_accuracy(lgefint(B)));
838: pow2[0] = (long)y;
839: for (i=0,q=r;; )
840: {
841: fl = cmpii(r,B); if (fl >= 0) break;
842: q = r; r = sqri(q);
843: i++; pow2[i] = (long)r;
844: }
845: if (i == 0) { e = 1; goto END; } /* y <= B */
846:
847: for (i--, e=1<<i;;)
848: { /* y^e = q < B <= r = q * y^(2^i) */
849: if (!fl) break; /* B = r */
850: /* q < B < r */
851: if (--i < 0) { if (fl > 0) e++; break; }
852: r = mulii(q, (GEN)pow2[i]);
853: fl = cmpii(r, B);
854: if (fl <= 0) { e += (1<<i); q = r; }
855: }
856: if (fl <= 0) { e++; r = mulii(r,y); }
857: END:
858: if (ptq) *ptq = gerepileuptoint(av, icopy(r)); else avma = av;
859: return e;
860: }
861:
862: /* recombination of modular factors: van Hoeij's algorithm */
863:
864: /* compute Newton sums of P (i-th powers of roots, i=1..n)
865: * If N != NULL, assume p-adic roots and compute mod N [assume integer coeffs]
866: * If y0!= NULL, precomputed i-th powers, i=1..m, m = length(y0) */
867: GEN
868: polsym_gen(GEN P, GEN y0, long n, GEN N)
869: {
870: long av1,av2,dP=degpol(P),i,k,m;
871: GEN s,y,P_lead;
872:
873: if (n<0) err(impl,"polsym of a negative n");
874: if (typ(P) != t_POL) err(typeer,"polsym");
875: if (!signe(P)) err(zeropoler,"polsym");
876: y = cgetg(n+2,t_COL);
877: if (y0)
878: {
879: if (typ(y0) != t_COL) err(typeer,"polsym_gen");
880: m = lg(y0)-1;
881: for (i=1; i<=m; i++) y[i] = lcopy((GEN)y0[i]);
882: }
883: else
884: {
885: m = 1;
886: y[1] = lstoi(dP);
887: }
888: P += 2; /* strip codewords */
889:
890: P_lead=(GEN)P[dP]; if (gcmp1(P_lead)) P_lead=NULL;
891: if (N && P_lead)
892: if (!invmod(P_lead,N,&P_lead))
893: err(talker,"polsyn: non-invertible leading coeff: %Z", P_lead);
894: for (k=m; k<=n; k++)
895: {
896: av1=avma; s = (dP>=k)? gmulsg(k,(GEN)P[dP-k]): gzero;
897: for (i=1; i<k && i<=dP; i++)
898: s = gadd(s, gmul((GEN)y[k-i+1],(GEN)P[dP-i]));
899: if (N)
900: {
901: s = modii(s, N);
902: if (P_lead) { s = mulii(s,P_lead); s = modii(s,N); }
903: }
904: else
905: if (P_lead) s = gdiv(s,P_lead);
906: av2=avma; y[k+1]=lpile(av1,av2,gneg(s));
907: }
908: return y;
909: }
910:
911: /* return integer y such that all roots of P are less than y */
912: static GEN
913: root_bound(GEN P)
914: {
915: GEN P0 = dummycopy(P), lP = absi(leading_term(P)), x,y,z;
916: long k,d = degpol(P);
917:
918: setlgef(P0, d+2); /* P = lP x^d + P0 */
919: P = P0+2; /* strip codewords */
920: for (k=0; k<d; k++) P[k] = labsi((GEN)P[k]);
921:
922: x = y = gun;
923: for (k=0; ; k++)
924: {
925: if (cmpii(poleval(P0,y), mulii(lP, gpowgs(y, d))) < 0) break;
926: x = y; y = shifti(y,1);
927: }
928: for(;;)
929: {
930: z = shifti(addii(x,y), -1);
931: if (egalii(x,z)) break;
932: if (cmpii(poleval(P0,z), mulii(lP, gpowgs(z, d))) < 0)
933: y = z;
934: else
935: x = z;
936: }
937: return y;
938: }
939:
940: extern GEN gscal(GEN x,GEN y);
941: extern GEN sqscal(GEN x);
942:
943: /* return Gram-Schmidt orthogonal basis (f) associated to (e), B is the
944: * vector of the (f_i . f_i)*/
945: GEN
946: gram_schmidt(GEN e, GEN *ptB)
947: {
948: long i,j,lx = lg(e);
949: GEN f = dummycopy(e), B, iB;
950:
951: B = cgetg(lx, t_VEC);
952: iB= cgetg(lx, t_VEC);
953:
954: for (i=1;i<lx;i++)
955: {
956: GEN p1 = NULL;
957: ulong av;
958: B[i] = (long)sqscal((GEN)f[i]);
959: iB[i]= linv((GEN)B[i]); av = avma;
960: for (j=1; j<i; j++)
961: {
962: GEN mu = gmul(gscal((GEN)e[i],(GEN)f[j]), (GEN)iB[j]);
963: GEN p2 = gmul(mu, (GEN)f[j]);
964: p1 = p1? gadd(p1,p2): p2;
965: }
966: p1 = p1? gerepileupto(av, gsub((GEN)e[i], p1)): (GEN)e[i];
967: f[i] = (long)p1;
968: }
969: *ptB = B; return f;
970: }
971:
972: extern GEN hnfall_i(GEN A, GEN *ptB, long remove);
973:
974: GEN
975: special_pivot(GEN x)
976: {
977: GEN t, H = hnfall_i(x, NULL, 1);
978: long i,j, l = lg(H), h = lg(H[1]);
979: for (i=1; i<h; i++)
980: {
981: int fl = 0;
982: for (j=1; j<l; j++)
983: {
984: t = gcoeff(H,i,j);
985: if (signe(t))
986: {
987: if (!is_pm1(t) || fl) return NULL;
988: fl = 1;
989: }
990: }
991: }
992: return H;
993: }
994:
995: /* x matrix: compute a bound for | \sum e_i x_i | ^ 2, e_i = 0,1 */
996: static GEN
997: my_norml2(GEN x)
998: {
999: long i,j, co = lg(x), li;
1000: GEN S = gzero;
1001: if (co == 1) return S;
1002: li = lg(x[1]);
1003: for (i=1; i<li; i++)
1004: {
1005: GEN p = gzero;
1006: GEN m = gzero;
1007: for (j=1; j<co; j++)
1008: {
1009: GEN u = gcoeff(x,i,j);
1010: long s = gsigne(u);
1011: if (s < 0) m = gadd(m,u);
1012: else if (s > 0) p = gadd(p,u);
1013: }
1014: if (m != gzero) m = gneg(m);
1015: if (gcmp(p,m) > 0) m = p;
1016:
1017: S = gadd(S, gsqr(m));
1018: }
1019: return S;
1020: }
1021:
1022: /* each entry < 2^e */
1023: static long
1024: init_padic_prec(long e, int BitPerFactor, long n0, double LOGp2)
1025: {
1026: /* long b, goodb = (long) ((e - 0.175 * n0 * n0) * LOGp2); */
1027: long b, goodb = (long) (((e - BitPerFactor*n0)) * LOGp2);
1028: b = (long) ((e - 32)*LOGp2); if (b < goodb) goodb = b;
1029: /* b = (long) ((e - Max*32)*LOGp2); if (b > goodb) goodb = b; */
1030: return goodb;
1031: }
1032:
1033: extern GEN sindexrank(GEN x);
1034: extern GEN vconcat(GEN Q1, GEN Q2);
1035: extern GEN gauss_intern(GEN a, GEN b);
1036:
1037: /* Recombination phase of Berlekamp-Zassenhaus algorithm using a variant of
1038: * van Hoeij's knapsack
1039: *
1040: * P = monic squarefree in Z[X].
1041: * famod = array of (lifted) modular factors mod p^a
1042: * bound = Mignotte bound for the size of divisors of P (sor the sup norm)
1043: * previously recombined all set of factors with less than rec elts
1044: */
1045: GEN
1046: LLL_cmbf(GEN P, GEN famod, GEN p, GEN pa, GEN bound, long a, long rec)
1047: {
1048: long s = 2; /* # of traces added at each step */
1049: long BitPerFactor = 3; /* nb bits in p^(a-b) / modular factor */
1050: long i,j,C,r,S,tmax,n0,n,dP = degpol(P);
1051: double logp = log(gtodouble(p)), LOGp2 = LOG2/logp;
1052: double b0 = log((double)dP*2) / logp;
1053: double k = gtodouble(glog(root_bound(P), DEFAULTPREC)) / logp;
1054: GEN y, T, T2, TT, BL, m, u, norm, target, M, piv, list;
1055: GEN run = realun(DEFAULTPREC);
1056: ulong av,av2, lim;
1057: int did_recompute_famod = 0;
1058:
1059: n0 = n = r = lg(famod) - 1;
1060: list = cgetg(n0+1, t_COL);
1061:
1062: av = avma; lim = stack_lim(av, 1);
1063: TT = cgetg(n0+1, t_VEC);
1064: T = cgetg(n0+1, t_MAT);
1065: for (i=1; i<=n0; i++)
1066: {
1067: TT[i] = 0;
1068: T [i] = lgetg(s+1, t_COL);
1069: }
1070: BL = idmat(n0);
1071: /* tmax = current number of traces used (and computed so far)
1072: * S = number of traces used at the round's end = tmax + s */
1073: for(tmax = 0;; tmax = S)
1074: {
1075: GEN pas2, pa_b, BE;
1076: long b, goodb;
1077: double Nx;
1078:
1079: if (DEBUGLEVEL>3)
1080: fprintferr("LLL_cmbf: %ld potential factors (tmax = %ld)\n", r, tmax);
1081: av2 = avma;
1082: if (tmax > 0)
1083: { /* bound small vector in terms of a modified L2 norm of a
1084: * left inverse of BL */
1085: GEN z = gauss_intern(BL,NULL); /* 1/BL */
1086: if (!z) /* not maximal rank */
1087: {
1088: avma = av2;
1089: BL = hnfall_i(BL,NULL,1);
1090: r = lg(BL)-1; z = invmat(BL);
1091: av2 = avma;
1092: }
1093: Nx = gtodouble(my_norml2(gmul(run, z)));
1094: avma = av2;
1095: }
1096: else
1097: Nx = (double)n0; /* first time: BL = id */
1098: C = (long)sqrt(s*n0*n0/4. / Nx);
1099: if (C == 0) C = 1; /* frequent after a few iterations */
1100: M = dbltor((Nx * C*C + s*n0*n0/4.) * 1.00001);
1101:
1102: S = tmax + s;
1103: b = (long)ceil(b0 + S*k);
1104: if (a <= b)
1105: {
1106: a = (long)ceil(b + 3*s*k) + 1; /* enough for 3 more rounds */
1107: pa = gpowgs(p,a);
1108: famod = hensel_lift_fact(P,famod,NULL,p,pa,a);
1109: /* recompute old Newton sums to new precision */
1110: for (i=1; i<=n0; i++)
1111: TT[i] = (long)polsym_gen((GEN)famod[i], NULL, tmax, pa);
1112: did_recompute_famod = 1;
1113: }
1114: for (i=1; i<=n0; i++)
1115: {
1116: GEN p1 = (GEN)T[i];
1117: GEN p2 = polsym_gen((GEN)famod[i], (GEN)TT[i], S, pa);
1118: TT[i] = (long)p2;
1119: p2 += 1+tmax; /* ignore traces number 0...tmax */
1120: for (j=1; j<=s; j++) p1[j] = p2[j];
1121: }
1122:
1123: av2 = avma;
1124: T2 = gmod( gmul(T, BL), pa );
1125: goodb = init_padic_prec(gexpo(T2), BitPerFactor, n0, LOGp2);
1126: if (goodb > b) b = goodb;
1127: if (DEBUGLEVEL>2)
1128: fprintferr("LLL_cmbf: (a, b) = (%ld, %ld), expo(T) = %ld\n",
1129: a,b,gexpo(T2));
1130: pa_b = gpowgs(p, a-b);
1131: {
1132: GEN pb = gpowgs(p, b);
1133: GEN pa_bs2 = shifti(pa_b,-1);
1134: GEN pbs2 = shifti(pb,-1);
1135: for (i=1; i<=r; i++)
1136: {
1137: GEN p1 = (GEN)T2[i];
1138: for (j=1; j<=s; j++)
1139: p1[j] = (long)TruncTrace((GEN)p1[j],pb,pa_b,pa_bs2,pbs2);
1140: }
1141: }
1142: if (gcmp0(T2)) { avma = av2; continue; }
1143:
1144: BE = cgetg(s+1, t_MAT);
1145: for (i=1; i<=s; i++)
1146: {
1147: BE[i] = (long)zerocol(r+s);
1148: coeff(BE, i+r, i) = (long)pa_b;
1149: }
1150: m = concatsp( vconcat( gscalmat(stoi(C), r), T2 ), BE );
1151: /* [ C 0 ]
1152: * m = [ ] square matrix
1153: * [ T2 p^(a-b) I_S ] T2 = T * BL truncated
1154: */
1155: u = lllgramintern(gram_matrix(m), 4, 0, 0);
1156: m = gmul(m,u);
1157: (void)gram_schmidt(gmul(run,m), &norm);
1158: for (i=r+s; i>0; i--)
1159: if (cmprr((GEN)norm[i], M) < 0) break;
1160: if (i > r)
1161: { /* no progress */
1162: avma = av2; BitPerFactor += 2;
1163: if (DEBUGLEVEL>2)
1164: fprintferr("LLL_cmbf: increasing BitPerFactor = %ld\n", BitPerFactor);
1165: #if 0
1166: s++; for (i=1; i<=n; i++) T[i] = lgetg(s+1, t_COL);
1167: if (DEBUGLEVEL>2) fprintferr("LLL_cmbf: increasing s = %ld\n", s);
1168: #endif
1169: continue;
1170: }
1171:
1172: n = r; r = i;
1173: if (r <= 1)
1174: {
1175: if (r == 0) err(bugparier,"LLL_cmbf [no factor]");
1176: if (DEBUGLEVEL>2) fprintferr("LLL_cmbf: 1 factor\n");
1177: list[1] = (long)P; setlg(list,2); return list;
1178: }
1179:
1180: setlg(u, r+1);
1181: for (i=1; i<=r; i++) setlg(u[i], n+1);
1182: BL = gerepileupto(av2, gmul(BL, u));
1183: if (low_stack(lim, stack_lim(av,1)))
1184: {
1185: GEN *gptr[4]; gptr[0]=&BL; gptr[1]=&TT; gptr[2]=&T; gptr[3]=&famod;
1186: if(DEBUGMEM>1) err(warnmem,"LLL_cmbf");
1187: gerepilemany(av, gptr, did_recompute_famod? 4: 3);
1188: }
1189: if (r*rec >= n0) continue;
1190:
1191: av2 = avma;
1192: piv = special_pivot(BL);
1193: if (DEBUGLEVEL) fprintferr("special_pivot output:\n%Z\n",piv);
1194: if (!piv) { avma = av2; continue; }
1195:
1196: pas2 = shifti(pa,-1); target = P;
1197: for (i=1; i<=r; i++)
1198: {
1199: GEN p1 = (GEN)piv[i];
1200: if (DEBUGLEVEL) fprintferr("LLL_cmbf: checking factor %ld\n",i);
1201:
1202: y = gun;
1203: for (j=1; j<=n0; j++)
1204: if (signe(p1[j]))
1205: y = centermod_i(gmul(y, (GEN)famod[j]), pa, pas2);
1206:
1207: /* y is the candidate factor */
1208: if (! (target = polidivis(target,y,bound)) ) break;
1209: list[i] = (long)y;
1210: }
1211: if (i > r)
1212: {
1213: if (DEBUGLEVEL>2) fprintferr("LLL_cmbf: %ld factors\n", r);
1214: setlg(list,r+1); return list;
1215: }
1216: }
1217: }
1218:
1219: extern GEN primitive_pol_to_monic(GEN pol, GEN *ptlead);
1220:
1221: /* P(hx), in place. Assume P in Z[X], h in Z */
1222: void
1223: rescale_pol_i(GEN P, GEN h)
1224: {
1225: GEN hi = gun;
1226: long i, l = lgef(P);
1227: for (i=3; i<l; i++)
1228: {
1229: hi = mulii(hi,h);
1230: P[i] = lmulii((GEN)P[i], hi);
1231: }
1232: }
1233:
1234: /* P(hx) in Fp[X], in place. Assume P in Z[X], h in Z */
1235: void
1236: FpX_rescale_i(GEN P, GEN h, GEN p)
1237: {
1238: GEN hi = gun;
1239: long i, l = lgef(P);
1240: for (i=3; i<l; i++)
1241: {
1242: hi = modii(mulii(hi,h), p);
1243: P[i] = lmodii(mulii((GEN)P[i], hi), p);
1244: }
1245: }
1246:
1247: /* use van Hoeij's knapsack algorithm */
1248: static GEN
1249: combine_factors(GEN a, GEN famod, GEN p, long klim, long hint)
1250: {
1251: GEN B = uniform_Mignotte_bound(a), res,y,lt,L,pe,pE,listmod,p1;
1252: long i,E,e,l, maxK = 3, nft = lg(famod)-1;
1253:
1254: e = logint(B, p, &pe);
1255: if (DEBUGLEVEL > 4) fprintferr("Mignotte bound: %Z^%ld\n", p,e);
1256:
1257: { /* overlift for the d-1 test */
1258: int over = (int) (32 * LOG2 / log((double)itos(p)));
1259: pE = mulii(pe, gpowgs(p,over)); E = e + over;
1260: }
1261: famod = hensel_lift_fact(a,famod,NULL,p,pE,E);
1262:
1263: if (nft < 11) maxK = -1; /* few modular factors: try all posibilities */
1264: else
1265: {
1266: lt = leading_term(a);
1267: if (!is_pm1(lt) && nft < 13) maxK = -1;
1268: }
1269: L = cmbf(a, famod, p, e, E, maxK, klim, hint);
1270:
1271: res = (GEN)L[1];
1272: listmod = (GEN)L[2]; l = lg(listmod);
1273: famod = (GEN)listmod[l-1];
1274: if (maxK >= 0 && lg(famod)-1 > 2*maxK)
1275: {
1276: a = (GEN)res[l-1];
1277: lt = leading_term(a);
1278: if (signe(lt) < 0) { a = gneg_i(a); lt = leading_term(a); }
1279: if (DEBUGLEVEL > 4) fprintferr("last factor still to be checked\n");
1280: if (gcmp1(lt))
1281: lt = NULL;
1282: else
1283: {
1284: GEN invlt, invLT;
1285: if (DEBUGLEVEL > 4) fprintferr("making it monic\n");
1286: a = primitive_pol_to_monic(a, <);
1287: B = uniform_Mignotte_bound(a);
1288: e = logint(B, p, &pe);
1289:
1290: invlt = mpinvmod(lt,p);
1291: for (i = 1; i<lg(famod); i++)
1292: { /* renormalize modular factors */
1293: p1 = (GEN)famod[i]; FpX_rescale_i(p1, invlt, p);
1294: invLT = powmodulo(lt, stoi(degpol(p1)), p);
1295: famod[i] = (long)FpX_Fp_mul(p1, invLT, p);
1296: }
1297: famod = hensel_lift_fact(a,famod,NULL,p,pe,e);
1298: }
1299: setlg(res, l-1); /* remove last elt (possibly unfactored) */
1300: L = LLL_cmbf(a, famod, p, pe, B, e, maxK);
1301: if (lt)
1302: {
1303: for (i=1; i<lg(L); i++)
1304: {
1305: y = (GEN)L[i]; rescale_pol_i(y, lt);
1306: L[i] = (long)primitive_part(y, &p1);
1307: }
1308: }
1309: res = concatsp(res, L);
1310: }
1311: return res;
1312: }
1313:
1314: extern long split_berlekamp(GEN *t, GEN pp, GEN pps2);
1315: #define u_FpX_div(x,y,p) u_FpX_divrem((x),(y),(p),(0),NULL)
1316:
1317: /* assume degree(a) > 0, a(0) != 0, and a squarefree */
1318: static GEN
1319: squff(GEN a, long hint)
1320: {
1321: GEN PolX,lead,res,prime,primes2,famod,y,g,z,w,*tabd,*tabdnew;
1322: long da = degpol(a), va = varn(a);
1323: long klim,chosenp,p,nfacp,lbit,j,d,e,np,nmax,nf,nft;
1324: ulong *tabbit, *tabkbit, *tmp, av = avma;
1325: byteptr pt=diffptr;
1326: const int MAXNP = max(5, (long)sqrt(da));
1327:
1328: if (hint <= 0) hint = 1;
1329: if (DEBUGLEVEL > 2) timer2();
1330: lbit = (da>>4)+1; nmax = da+1; klim = da>>1;
1331: chosenp = 0;
1332: tabd = NULL;
1333: tabdnew = (GEN*)new_chunk(nmax);
1334: tabbit = (ulong*)new_chunk(lbit);
1335: tabkbit = (ulong*)new_chunk(lbit);
1336: tmp = (ulong*)new_chunk(lbit);
1337: prime = icopy(gun);
1338: lead = (GEN)a[da+2]; PolX = u_Fp_FpX(polx[0],0, 2);
1339: for (p = np = 0; np < MAXNP; )
1340: {
1341: ulong av0 = avma;
1342: p += *pt++; if (!*pt) err(primer1);
1343: if (!smodis(lead,p)) continue;
1344: z = u_Fp_FpX(a,0, p);
1345: if (!u_FpX_is_squarefree(z, p)) { avma = av0; continue ; }
1346:
1347: for (j=0; j<lbit-1; j++) tabkbit[j] = 0;
1348: tabkbit[j] = 1;
1349: d = 0; e = da; nfacp = 0;
1350: w = PolX; prime[2] = p;
1351: while (d < (e>>1))
1352: {
1353: long lgg;
1354: d++; w = u_FpXQ_pow(w, prime, z, p);
1355: g = u_FpX_gcd(z, u_FpX_sub(w, PolX, p), p);
1356: lgg = degpol(g);
1357: if (lgg == 0) g = NULL;
1358: else
1359: {
1360: z = u_FpX_div(z, g, p); e = degpol(z);
1361: w = u_FpX_rem(w, z, p);
1362: lgg /= d; nfacp += lgg;
1363: if (DEBUGLEVEL>5)
1364: fprintferr(" %3ld factor%s of degree %3ld\n", lgg, lgg==1?"":"s",d);
1365: record_factors(lgg, d, lbit-1, tabkbit, tmp);
1366: }
1367: tabdnew[d] = g;
1368: }
1369: if (e > 0)
1370: {
1371: if (DEBUGLEVEL>5) fprintferr(" %3ld factor of degree %3ld\n",1,e);
1372: tabdnew[e] = z; nfacp++;
1373: record_factors(1, e, lbit-1, tabkbit, tmp);
1374: }
1375:
1376: if (np)
1377: for (j=0; j<lbit; j++) tabbit[j] &= tabkbit[j];
1378: else
1379: for (j=0; j<lbit; j++) tabbit[j] = tabkbit[j];
1380: if (DEBUGLEVEL > 4)
1381: fprintferr("...tried prime %3ld (%-3ld factor%s). Time = %ld\n",
1382: p, nfacp, nfacp==1?"": "s", timer2());
1383: if (min_deg(lbit-1,tabbit) > klim) { avma = av; return _col(a); }
1384: if (nfacp < nmax)
1385: {
1386: nmax = nfacp; tabd = tabdnew; chosenp = p;
1387: for (j=d+1; j<e; j++) tabd[j] = NULL;
1388: tabdnew = (GEN*)new_chunk(da);
1389: }
1390: else avma = av0;
1391: np++;
1392: }
1393: prime[2] = chosenp; primes2 = shifti(prime, -1);
1394: nf = nmax; nft = 1;
1395: y = cgetg(nf+1,t_COL); famod = cgetg(nf+1,t_COL);
1396: for (d = 1; nft <= nf; d++)
1397: {
1398: g = tabd[d];
1399: if (g)
1400: {
1401: long n = degpol(g)/d;
1402: famod[nft] = (long)small_to_pol(u_FpX_normalize(g, chosenp),va);
1403: if (n > 1 && n != split_berlekamp((GEN*)(famod+nft),prime,primes2))
1404: err(bugparier,"squff: wrong numbers of factors");
1405: nft += n;
1406: }
1407: }
1408: if (DEBUGLEVEL > 4) msgtimer("splitting mod p = %ld",chosenp);
1409: res = combine_factors(a, famod, prime, da-1, hint);
1410: return gerepilecopy(av, res);
1411: }
1412:
1413: /* A(X^d) --> A(X) */
1414: GEN
1415: poldeflate_i(GEN x0, long d)
1416: {
1417: GEN z, y, x;
1418: long i,id, dy, dx = degpol(x0);
1419: if (d == 1) return x0;
1420: if (dx < 0) return zeropol(varn(x0));
1421: dy = dx/d;
1422: y = cgetg(dy+3, t_POL);
1423: y[1] = evalsigne(1)|evaldeg(dy)|evalvarn(varn(x0));
1424: z = y + 2;
1425: x = x0+ 2;
1426: for (i=id=0; i<=dy; i++,id+=d) z[i] = x[id];
1427: return y;
1428: }
1429:
1430: long
1431: checkdeflate(GEN x)
1432: {
1433: long d = 0, i, lx = lgef(x);
1434: for (i=3; i<lx; i++)
1435: if (!gcmp0((GEN)x[i])) { d = cgcd(d,i-2); if (d == 1) break; }
1436: return d;
1437: }
1438:
1439: GEN
1440: gdeflate(GEN x, long v, long d)
1441: {
1442: long i, lx, tx = typ(x);
1443: GEN z;
1444: if (is_scalar_t(tx)) return gcopy(x);
1445: if (tx == t_POL)
1446: {
1447: long vx = varn(x);
1448: ulong av;
1449: if (vx < v)
1450: {
1451: lx = lgef(x);
1452: z = cgetg(lx,t_POL); z[1] = x[1];
1453: for (i=2; i<lx; i++) z[i] = (long)gdeflate((GEN)x[i],v,d);
1454: return z;
1455: }
1456: if (vx > v) return gcopy(x);
1457: av = avma;
1458: if (checkdeflate(x) % d != 0)
1459: err(talker,"impossible substitution in gdeflate");
1460: return gerepilecopy(av, poldeflate_i(x,d));
1461: }
1462: if (tx == t_RFRAC)
1463: {
1464: z = cgetg(3, t_RFRAC);
1465: z[1] = (long)gdeflate((GEN)x[1],v,d);
1466: z[2] = (long)gdeflate((GEN)x[2],v,d);
1467: return z;
1468: }
1469: if (is_matvec_t(tx))
1470: {
1471: lx = lg(x); z = cgetg(lx, tx);
1472: for (i=1; i<lx; i++) z[i] = (long)gdeflate((GEN)x[i],v,d);
1473: return z;
1474: }
1475: err(typeer,"gdeflate");
1476: return NULL; /* not reached */
1477: }
1478:
1479: /* set *m to the largest d such that x0 = A(X^d); return A */
1480: GEN
1481: poldeflate(GEN x, long *m)
1482: {
1483: *m = checkdeflate(x);
1484: return poldeflate_i(x, *m);
1485: }
1486:
1487: /* return x0(X^d) */
1488: GEN
1489: polinflate(GEN x0, long d)
1490: {
1491: long i, id, dy, dx = degpol(x0);
1492: GEN x = x0 + 2, z, y;
1493: dy = dx*d;
1494: y = cgetg(dy+3, t_POL);
1495: y[1] = evalsigne(1)|evaldeg(dy)|evalvarn(varn(x0));
1496: z = y + 2;
1497: for (i=0; i<=dy; i++) z[i] = zero;
1498: for (i=id=0; i<=dx; i++,id+=d) z[id] = x[i];
1499: return y;
1500: }
1501:
1502: GEN
1503: squff2(GEN x, long hint)
1504: {
1505: GEN L;
1506: long m;
1507: x = poldeflate(x, &m);
1508: L = squff(x, hint);
1509: if (m > 1)
1510: {
1511: GEN e, v, fa = decomp(stoi(m));
1512: long i,j,k, l;
1513:
1514: e = (GEN)fa[2]; k = 0;
1515: fa= (GEN)fa[1]; l = lg(fa);
1516: for (i=1; i<l; i++)
1517: {
1518: e[i] = itos((GEN)e[i]);
1519: k += e[i];
1520: }
1521: v = cgetg(k+1, t_VECSMALL); k = 1;
1522: for (i=1; i<l; i++)
1523: for (j=1; j<=e[i]; j++) v[k++] = itos((GEN)fa[i]);
1524: for (k--; k; k--)
1525: {
1526: GEN L2 = cgetg(1,t_VEC);
1527: for (i=1; i < lg(L); i++)
1528: L2 = concatsp(L2, squff(polinflate((GEN)L[i], v[k]), hint));
1529: L = L2;
1530: }
1531: }
1532: return L;
1533: }
1534:
1535: /* Factor x in Z[t]. Assume all factors have degree divisible by hint */
1536: GEN
1537: factpol(GEN x, long hint)
1538: {
1539: GEN fa,p1,d,t,v,w, y = cgetg(3,t_MAT);
1540: long av=avma,av2,lx,vx,i,j,k,ex,nbfac,zval;
1541:
1542: if (typ(x)!=t_POL) err(notpoler,"factpol");
1543: if (!signe(x)) err(zeropoler,"factpol");
1544:
1545: ex = nbfac = 0;
1546: p1 = x+2; while (gcmp0((GEN)*p1)) p1++;
1547: zval = p1 - (x + 2);
1548: lx = lgef(x) - zval;
1549: vx = varn(x);
1550: if (zval)
1551: {
1552: x = cgetg(lx, t_POL); p1 -= 2;
1553: for (i=2; i<lx; i++) x[i] = p1[i];
1554: x[1] = evalsigne(1)|evalvarn(vx)|evallgef(lx);
1555: nbfac++;
1556: }
1557: /* now x(0) != 0 */
1558: if (lx==3) { fa = NULL;/* for lint */ goto END; }
1559: p1 = cgetg(1,t_VEC); fa=cgetg(lx,t_VEC);
1560: for (i=1; i<lx; i++) fa[i] = (long)p1;
1561: d=content(x); if (gsigne(leading_term(x)) < 0) d = gneg_i(d);
1562: if (!gcmp1(d)) x=gdiv(x,d);
1563: if (lx==4) { nbfac++; ex++; fa[1] = (long)concatsp(p1,x); goto END; }
1564:
1565: w=derivpol(x); t=modulargcd(x,w);
1566: if (!gcmp1(t)) { x=gdeuc(x,t); w=gdeuc(w,t); }
1567: k=1;
1568: while (k)
1569: {
1570: ex++; w=gadd(w, gneg_i(derivpol(x))); k=signe(w);
1571: if (k) { t=modulargcd(x,w); x=gdeuc(x,t); w=gdeuc(w,t); } else t=x;
1572: if (degpol(t) > 0)
1573: {
1574: fa[ex] = (long)squff2(t,hint);
1575: nbfac += lg(fa[ex])-1;
1576: }
1577: }
1578: END: av2=avma;
1579: v=cgetg(nbfac+1,t_COL); y[1]=(long)v;
1580: w=cgetg(nbfac+1,t_COL); y[2]=(long)w;
1581: if (zval) { v[1]=lpolx[vx]; w[1]=lstoi(zval); k=1; } else k=0;
1582: for (i=1; i<=ex; i++)
1583: for (j=1; j<lg(fa[i]); j++)
1584: {
1585: k++; v[k]=lcopy(gmael(fa,i,j)); w[k]=lstoi(i);
1586: }
1587: gerepilemanyvec(av,av2,y+1,2);
1588: return sort_factor(y, cmpii);
1589: }
1590:
1591: /***********************************************************************/
1592: /** **/
1593: /** FACTORIZATION **/
1594: /** **/
1595: /***********************************************************************/
1596: #define LT 17
1597: #define assign_or_fail(x,y) {\
1598: if (y==NULL) y=x; else if (!gegal(x,y)) return 0;\
1599: }
1600: #define tsh 6
1601: #define typs(x,y) ((x << tsh) | y)
1602: #define typ1(x) (x >> tsh)
1603: #define typ2(x) (x & ((1<<tsh)-1))
1604:
1605: static long
1606: poltype(GEN x, GEN *ptp, GEN *ptpol, long *ptpa)
1607: {
1608: long t[LT]; /* code for 0,1,2,3,61,62,63,67,7,81,82,83,86,87,91,93,97 */
1609: long tx = typ(x),lx,i,j,s,pa=BIGINT;
1610: GEN pcx=NULL, p=NULL,pol=NULL,p1,p2;
1611:
1612: if (is_scalar_t(tx))
1613: {
1614: if (tx == t_POLMOD) return 0;
1615: x = scalarpol(x,0);
1616: }
1617: for (i=2; i<LT; i++) t[i]=0; /* t[0..1] unused */
1618: lx = lgef(x);
1619: for (i=2; i<lx; i++)
1620: {
1621: p1=(GEN)x[i];
1622: switch(typ(p1))
1623: {
1624: case t_INT: case t_FRAC: case t_FRACN:
1625: break;
1626: case t_REAL:
1627: s = precision(p1); if (s < pa) pa = s;
1628: t[2]=1; break;
1629: case t_INTMOD:
1630: assign_or_fail((GEN)p1[1],p);
1631: t[3]=1; break;
1632: case t_COMPLEX:
1633: if (!pcx)
1634: {
1635: pcx = cgetg(5,t_POL); /* x^2 + 1 */
1636: pcx[1] = evalsigne(1)|evalvarn(0)|m_evallgef(5),
1637: pcx[2]=pcx[4]=un; pcx[3]=zero;
1638: }
1639: for (j=1; j<=2; j++)
1640: {
1641: p2 = (GEN)p1[j];
1642: switch(typ(p2))
1643: {
1644: case t_INT: case t_FRAC: case t_FRACN:
1645: assign_or_fail(pcx,pol);
1646: t[4]=1; break;
1647: case t_REAL:
1648: s = precision(p2); if (s < pa) pa = s;
1649: t[5]=1; break;
1650: case t_INTMOD:
1651: assign_or_fail((GEN)p2[1],p);
1652: assign_or_fail(pcx,pol);
1653: t[6]=1; break;
1654: case t_PADIC:
1655: s = precp(p2) + valp(p2); if (s < pa) pa = s;
1656: assign_or_fail((GEN)p2[2],p);
1657: assign_or_fail(pcx,pol);
1658: t[7]=1; break;
1659: default: return 0;
1660: }
1661: }
1662: break;
1663: case t_PADIC:
1664: s = precp(p1) + valp(p1); if (s < pa) pa = s;
1665: assign_or_fail((GEN)p1[2],p);
1666: t[8]=1; break;
1667: case t_QUAD:
1668: for (j=2; j<=3; j++)
1669: {
1670: p2 = (GEN)p1[j];
1671: switch(typ(p2))
1672: {
1673: case t_INT: case t_FRAC: case t_FRACN:
1674: assign_or_fail((GEN)p1[1],pol);
1675: t[9]=1; break;
1676: case t_REAL:
1677: s = precision(p2); if (s < pa) pa = s;
1678: if (gsigne(discsr((GEN)p1[1]))>0) t[10]=1; else t[12]=1;
1679: break;
1680: case t_INTMOD:
1681: assign_or_fail((GEN)p2[1],p);
1682: assign_or_fail((GEN)p1[1],pol);
1683: t[11]=1; break;
1684: case t_PADIC:
1685: s = precp(p2) + valp(p2); if (s < pa) pa = s;
1686: assign_or_fail((GEN)p2[2],p);
1687: assign_or_fail((GEN)p1[1],pol);
1688: t[13]=1; break;
1689: default: return 0;
1690: }
1691: }
1692: break;
1693: case t_POLMOD:
1694: assign_or_fail((GEN)p1[1],pol);
1695: for (j=1; j<=2; j++)
1696: {
1697: GEN pbis = NULL, polbis = NULL;
1698: long pabis;
1699: switch(poltype((GEN)p1[j],&pbis,&polbis,&pabis))
1700: {
1701: case t_INT: t[14]=1; break;
1702: case t_INTMOD: t[15]=1; break;
1703: case t_PADIC: t[16]=1; if (pabis<pa) pa=pabis; break;
1704: default: return 0;
1705: }
1706: if (pbis) assign_or_fail(pbis,p);
1707: if (polbis) assign_or_fail(polbis,pol);
1708: }
1709: break;
1710: default: return 0;
1711: }
1712: }
1713: if (t[5]||t[12])
1714: {
1715: if (t[3]||t[6]||t[7]||t[8]||t[11]||t[13]||t[14]||t[15]||t[16]) return 0;
1716: *ptpa=pa; return t_COMPLEX;
1717: }
1718: if (t[2]||t[10])
1719: {
1720: if (t[3]||t[6]||t[7]||t[8]||t[11]||t[13]||t[14]||t[15]||t[16]) return 0;
1721: *ptpa=pa; return t[4]?t_COMPLEX:t_REAL;
1722: }
1723: if (t[6]||t[11]||t[15])
1724: {
1725: *ptpol=pol; *ptp=p;
1726: i = t[15]? t_POLMOD: (t[11]? t_QUAD: t_COMPLEX);
1727: return typs(i, t_INTMOD);
1728: }
1729: if (t[7]||t[13]||t[16])
1730: {
1731: *ptpol=pol; *ptp=p; *ptpa=pa;
1732: i = t[16]? t_POLMOD: (t[13]? t_QUAD: t_COMPLEX);
1733: return typs(i, t_PADIC);
1734: }
1735: if (t[4]||t[9]||t[14])
1736: {
1737: *ptpol=pol;
1738: i = t[14]? t_POLMOD: (t[9]? t_QUAD: t_COMPLEX);
1739: return typs(i, t_INT);
1740: }
1741: if (t[3]) { *ptp=p; return t_INTMOD; }
1742: if (t[8]) { *ptp=p; *ptpa=pa; return t_PADIC; }
1743: return t_INT;
1744: }
1745: #undef LT
1746:
1747: GEN
1748: factor0(GEN x,long flag)
1749: {
1750: long tx=typ(x);
1751:
1752: if (flag<0) return factor(x);
1753: if (is_matvec_t(tx)) return gboundfact(x,flag);
1754: if (tx==t_INT || tx==t_FRAC || tx==t_FRACN) return boundfact(x,flag);
1755: err(talker,"partial factorization is not meaningful here");
1756: return NULL; /* not reached */
1757: }
1758:
1759: /* assume f and g coprime integer factorizations */
1760: GEN
1761: merge_factor_i(GEN f, GEN g)
1762: {
1763: GEN h;
1764: if (lg(f) == 1) return g;
1765: if (lg(g) == 1) return f;
1766: h = cgetg(3,t_MAT);
1767: h[1] = (long)concatsp((GEN)f[1], (GEN)g[1]);
1768: h[2] = (long)concatsp((GEN)f[2], (GEN)g[2]);
1769: return sort_factor_gen(h, cmpii);
1770: }
1771:
1772: GEN
1773: factor(GEN x)
1774: {
1775: long tx=typ(x),lx,av,tetpil,i,j,pa,v,r1;
1776: GEN y,p,p1,p2,p3,p4,p5,pol;
1777:
1778: if (is_matvec_t(tx))
1779: {
1780: lx=lg(x); y=cgetg(lx,tx);
1781: for (i=1; i<lx; i++) y[i]=(long)factor((GEN)x[i]);
1782: return y;
1783: }
1784: if (gcmp0(x))
1785: {
1786: y=cgetg(3,t_MAT);
1787: p1=cgetg(2,t_COL); y[1]=(long)p1; p1[1]=lcopy(x);
1788: p2=cgetg(2,t_COL); y[2]=(long)p2; p2[1]=un;
1789: return y;
1790: }
1791: av = avma;
1792: switch(tx)
1793: {
1794: case t_INT: return decomp(x);
1795:
1796: case t_FRACN:
1797: x = gred(x); /* fall through */
1798: case t_FRAC:
1799: p1 = decomp((GEN)x[1]);
1800: p2 = decomp((GEN)x[2]); p2[2] = (long)gneg_i((GEN)p2[2]);
1801: return gerepilecopy(av, merge_factor_i(p1,p2));
1802:
1803: case t_POL:
1804: tx=poltype(x,&p,&pol,&pa);
1805: switch(tx)
1806: {
1807: case 0: err(impl,"factor for general polynomials");
1808: case t_INT: return factpol(x,1);
1809: case t_INTMOD: return factmod(x,p);
1810:
1811: case t_COMPLEX: y=cgetg(3,t_MAT); lx=lgef(x)-2; v=varn(x);
1812: av = avma; p1 = roots(x,pa); tetpil = avma;
1813: p2=cgetg(lx,t_COL);
1814: for (i=1; i<lx; i++)
1815: p2[i] = (long)deg1pol_i(gun, gneg((GEN)p1[i]), v);
1816: y[1]=lpile(av,tetpil,p2);
1817: p3=cgetg(lx,t_COL); for (i=1; i<lx; i++) p3[i] = un;
1818: y[2]=(long)p3; return y;
1819:
1820: case t_REAL: y=cgetg(3,t_MAT); lx=lgef(x)-2; v=varn(x);
1821: av=avma; p1=roots(x,pa); tetpil=avma;
1822: for(r1=1; r1<lx; r1++)
1823: if (signe(gmael(p1,r1,2))) break;
1824: lx=(r1+lx)>>1; p2=cgetg(lx,t_COL);
1825: for(i=1; i<r1; i++)
1826: p2[i] = (long)deg1pol_i(gun, negr(gmael(p1,i,1)), v);
1827: for( ; i<lx; i++)
1828: {
1829: GEN a = (GEN) p1[2*i-r1];
1830: p = cgetg(5, t_POL); p2[i] = (long)p;
1831: p[1] = evalsigne(1) | evalvarn(v) | evallgef(5);
1832: p[2] = lnorm(a);
1833: p[3] = lmul2n((GEN)a[1],1); setsigne(p[3],-signe(p[3]));
1834: p[4] = un;
1835: }
1836: y[1]=lpile(av,tetpil,p2);
1837: p3=cgetg(lx,t_COL); for (i=1; i<lx; i++) p3[i] = un;
1838: y[2]=(long)p3; return y;
1839:
1840: case t_PADIC: return factorpadic4(x,p,pa);
1841:
1842: default:
1843: {
1844: long killv;
1845: x = dummycopy(x); lx=lgef(x);
1846: pol = dummycopy(pol);
1847: v = manage_var(4,NULL);
1848: for(i=2; i<lx; i++)
1849: {
1850: p1=(GEN)x[i];
1851: switch(typ(p1))
1852: {
1853: case t_QUAD: p1++;
1854: case t_COMPLEX:
1855: p2 = cgetg(3, t_POLMOD); x[i] = (long) p2;
1856: p2[1] = (long)pol;
1857: p2[2] = (long)deg1pol_i((GEN)p1[2], (GEN)p1[1], v);
1858: }
1859: }
1860: killv = (avma != (ulong)pol);
1861: if (killv) setvarn(pol, fetch_var());
1862: switch (typ2(tx))
1863: {
1864: case t_INT: p1 = polfnf(x,pol); break;
1865: case t_INTMOD: p1 = factmod9(x,p,pol); break;
1866: default: err(impl,"factor of general polynomial");
1867: return NULL; /* not reached */
1868: }
1869: switch (typ1(tx))
1870: {
1871: case t_POLMOD:
1872: if (killv) delete_var();
1873: return gerepileupto(av,p1);
1874: case t_COMPLEX: p5 = gi; break;
1875: case t_QUAD: p5=cgetg(4,t_QUAD);
1876: p5[1]=(long)pol; p5[2]=zero; p5[3]=un;
1877: break;
1878: default: err(impl,"factor of general polynomial");
1879: return NULL; /* not reached */
1880: }
1881: p2=(GEN)p1[1];
1882: for(i=1; i<lg(p2); i++)
1883: {
1884: p3=(GEN)p2[i];
1885: for(j=2; j<lgef(p3); j++)
1886: {
1887: p4=(GEN)p3[j];
1888: if(typ(p4)==t_POLMOD) p3[j]=lsubst((GEN)p4[2],v,p5);
1889: }
1890: }
1891: if (killv) delete_var();
1892: tetpil=avma; y=cgetg(3,t_MAT);
1893: y[1]=lcopy(p2);y[2]=lcopy((GEN)p1[2]);
1894: return gerepile(av,tetpil,y);
1895: }
1896: }
1897:
1898: case t_RFRACN:
1899: x=gred_rfrac(x); /* fall through */
1900: case t_RFRAC:
1901: p1=factor((GEN)x[1]);
1902: p2=factor((GEN)x[2]); p3=gneg_i((GEN)p2[2]);
1903: tetpil=avma; y=cgetg(3,t_MAT);
1904: y[1]=lconcat((GEN)p1[1],(GEN)p2[1]);
1905: y[2]=lconcat((GEN)p1[2],p3);
1906: return gerepile(av,tetpil,y);
1907: }
1908: err(talker,"can't factor %Z",x);
1909: return NULL; /* not reached */
1910: }
1911: #undef typ1
1912: #undef typ2
1913: #undef typs
1914: #undef tsh
1915:
1916: GEN
1917: divide_conquer_prod(GEN x, GEN (*mul)(GEN,GEN))
1918: {
1919: long i,k,lx = lg(x);
1920:
1921: if (lx == 1) return gun;
1922: if (lx == 2) return gcopy((GEN)x[1]);
1923: x = dummycopy(x); k = lx;
1924: while (k > 2)
1925: {
1926: if (DEBUGLEVEL>7)
1927: fprintferr("prod: remaining objects %ld\n",k-1);
1928: lx = k; k = 1;
1929: for (i=1; i<lx-1; i+=2)
1930: x[k++] = (long)mul((GEN)x[i],(GEN)x[i+1]);
1931: if (i < lx) x[k++] = x[i];
1932: }
1933: return (GEN)x[1];
1934: }
1935:
1936: static GEN static_nf;
1937:
1938: static GEN
1939: myidealmulred(GEN x, GEN y) { return idealmulred(static_nf, x, y, 0); }
1940:
1941: static GEN
1942: myidealpowred(GEN x, GEN n) { return idealpowred(static_nf, x, n, 0); }
1943:
1944: static GEN
1945: myidealmul(GEN x, GEN y) { return idealmul(static_nf, x, y); }
1946:
1947: static GEN
1948: myidealpow(GEN x, GEN n) { return idealpow(static_nf, x, n); }
1949:
1950: GEN
1951: factorback_i(GEN fa, GEN nf, int red)
1952: {
1953: long av=avma,k,l,lx,t=typ(fa);
1954: GEN ex, x;
1955: GEN (*_mul)(GEN,GEN);
1956: GEN (*_pow)(GEN,GEN);
1957: if (nf)
1958: {
1959: static_nf = nf;
1960: if (red)
1961: {
1962: _mul = &myidealmulred;
1963: _pow = &myidealpowred;
1964: }
1965: else
1966: {
1967: _mul = &myidealmul;
1968: _pow = &myidealpow;
1969: }
1970: }
1971: else
1972: {
1973: _mul = &gmul;
1974: _pow = &powgi;
1975: }
1976: if ( t == t_VEC || t == t_COL)
1977: return gerepileupto(av, divide_conquer_prod(fa, _mul));
1978: if (t!=t_MAT || lg(fa)!=3)
1979: err(talker,"not a factorisation in factorback");
1980: ex=(GEN)fa[2]; fa=(GEN)fa[1];
1981: lx = lg(fa); if (lx == 1) return gun;
1982: x = cgetg(lx,t_VEC);
1983: for (l=1,k=1; k<lx; k++)
1984: if (signe(ex[k]))
1985: x[l++] = (long)_pow((GEN)fa[k],(GEN)ex[k]);
1986: setlg(x,l);
1987: return gerepileupto(av, divide_conquer_prod(x, _mul));
1988: }
1989:
1990: GEN
1991: factorback(GEN fa, GEN nf)
1992: {
1993: return factorback_i(fa,nf,0);
1994: }
1995:
1996: GEN
1997: gisirreducible(GEN x)
1998: {
1999: long av=avma, tx = typ(x),l,i;
2000: GEN y;
2001:
2002: if (is_matvec_t(tx))
2003: {
2004: l=lg(x); y=cgetg(l,tx);
2005: for (i=1; i<l; i++) y[i]=(long)gisirreducible((GEN)x[i]);
2006: return y;
2007: }
2008: if (is_intreal_t(tx) || is_frac_t(tx)) return gzero;
2009: if (tx!=t_POL) err(notpoler,"gisirreducible");
2010: l=lgef(x); if (l<=3) return gzero;
2011: y=factor(x); avma=av;
2012: return (lgef(gcoeff(y,1,1))==l)?gun:gzero;
2013: }
2014:
2015: /*******************************************************************/
2016: /* */
2017: /* GENERIC GCD */
2018: /* */
2019: /*******************************************************************/
2020:
2021: GEN
2022: gcd0(GEN x, GEN y, long flag)
2023: {
2024: switch(flag)
2025: {
2026: case 0: return gassoc_proto(ggcd,x,y);
2027: case 1: return gassoc_proto(modulargcd,x,y);
2028: case 2: return gassoc_proto(srgcd,x,y);
2029: default: err(flagerr,"gcd");
2030: }
2031: return NULL; /* not reached */
2032: }
2033:
2034: /* x is a COMPLEX or a QUAD */
2035: static GEN
2036: triv_cont_gcd(GEN x, GEN y)
2037: {
2038: long av = avma, tetpil;
2039: GEN p1 = (typ(x)==t_COMPLEX)? ggcd((GEN)x[1],(GEN)x[2])
2040: : ggcd((GEN)x[2],(GEN)x[3]);
2041: tetpil=avma; return gerepile(av,tetpil,ggcd(p1,y));
2042: }
2043:
2044: static GEN
2045: cont_gcd(GEN x, GEN y)
2046: {
2047: long av = avma, tetpil;
2048: GEN p1 = content(x);
2049:
2050: tetpil=avma; return gerepile(av,tetpil,ggcd(p1,y));
2051: }
2052:
2053: /* y is a PADIC, x a rational number or an INTMOD */
2054: static GEN
2055: padic_gcd(GEN x, GEN y)
2056: {
2057: long v = ggval(x,(GEN)y[2]), w = valp(y);
2058: if (w < v) v = w;
2059: return gpuigs((GEN)y[2], v);
2060: }
2061:
2062: #define fix_frac(z) if (signe(z[2])<0)\
2063: {\
2064: setsigne(z[1],-signe(z[1]));\
2065: setsigne(z[2],1);\
2066: }
2067:
2068: GEN
2069: ggcd(GEN x, GEN y)
2070: {
2071: long l,av,tetpil,i,vx,vy, tx = typ(x), ty = typ(y);
2072: GEN p1,z;
2073:
2074: if (tx>ty) { swap(x,y); lswap(tx,ty); }
2075: if (is_matvec_t(ty))
2076: {
2077: l=lg(y); z=cgetg(l,ty);
2078: for (i=1; i<l; i++) z[i]=lgcd(x,(GEN)y[i]);
2079: return z;
2080: }
2081: if (is_noncalc_t(tx) || is_noncalc_t(ty)) err(operf,"g",tx,ty);
2082: if (gcmp0(x)) return gcopy(y);
2083: if (gcmp0(y)) return gcopy(x);
2084: if (is_const_t(tx))
2085: {
2086: if (ty == t_FRACN)
2087: {
2088: if (tx==t_INTMOD)
2089: {
2090: av=avma; y = gred(y); tetpil=avma;
2091: return gerepile(av,tetpil,ggcd(x,y));
2092: }
2093: ty = t_FRAC;
2094: }
2095: if (tx == t_FRACN) tx = t_FRAC;
2096: if (ty == tx) switch(tx)
2097: {
2098: case t_INT:
2099: return mppgcd(x,y);
2100:
2101: case t_INTMOD: z=cgetg(3,t_INTMOD);
2102: if (egalii((GEN)x[1],(GEN)y[1]))
2103: { copyifstack(x[1],z[1]); }
2104: else
2105: z[1] = lmppgcd((GEN)x[1],(GEN)y[1]);
2106: if (gcmp1((GEN)z[1])) z[2] = zero;
2107: else
2108: {
2109: av = avma; p1 = mppgcd((GEN)z[1],(GEN)x[2]);
2110: if (!is_pm1(p1)) p1 = gerepileuptoint(av, mppgcd(p1,(GEN)y[2]));
2111: z[2] = (long)p1;
2112: }
2113: return z;
2114:
2115: case t_FRAC: z=cgetg(3,t_FRAC);
2116: z[1] = (long)mppgcd((GEN)x[1], (GEN)y[1]);
2117: z[2] = (long)mpppcm((GEN)x[2], (GEN)y[2]);
2118: return z;
2119:
2120: case t_COMPLEX:
2121: av=avma; p1=gdiv(x,y);
2122: if (gcmp0((GEN)p1[2]))
2123: {
2124: p1 = (GEN)p1[1];
2125: switch(typ(p1))
2126: {
2127: case t_INT:
2128: avma=av; return gcopy(y);
2129: case t_FRAC: case t_FRACN:
2130: tetpil=avma; return gerepile(av,tetpil,gdiv(y,(GEN)p1[2]));
2131: default: avma=av; return gun;
2132: }
2133: }
2134: if (typ(p1[1])==t_INT && typ(p1[2])==t_INT) {avma=av; return gcopy(y);}
2135: p1 = ginv(p1); avma=av;
2136: if (typ(p1[1])==t_INT && typ(p1[2])==t_INT) return gcopy(x);
2137: return triv_cont_gcd(y,x);
2138:
2139: case t_PADIC:
2140: if (!egalii((GEN)x[2],(GEN)y[2])) return gun;
2141: vx = valp(x);
2142: vy = valp(y); return gpuigs((GEN)y[2], min(vy,vx));
2143:
2144: case t_QUAD:
2145: av=avma; p1=gdiv(x,y);
2146: if (gcmp0((GEN)p1[3]))
2147: {
2148: p1=(GEN)p1[2];
2149: if (typ(p1)==t_INT) { avma=av; return gcopy(y); }
2150: tetpil=avma; return gerepile(av,tetpil, gdiv(y,(GEN)p1[2]));
2151: }
2152: if (typ(p1[2])==t_INT && typ(p1[3])==t_INT) {avma=av; return gcopy(y);}
2153: p1 = ginv(p1); avma=av;
2154: if (typ(p1[2])==t_INT && typ(p1[3])==t_INT) return gcopy(x);
2155: return triv_cont_gcd(y,x);
2156:
2157: default: return gun; /* t_REAL */
2158: }
2159: if (is_const_t(ty)) switch(tx)
2160: {
2161: case t_INT:
2162: switch(ty)
2163: {
2164: case t_INTMOD: z = cgetg(3,t_INTMOD);
2165: copyifstack(y[1],z[1]); av=avma;
2166: p1 = mppgcd((GEN)y[1],(GEN)y[2]);
2167: if (!is_pm1(p1)) p1 = gerepileuptoint(av, mppgcd(x,p1));
2168: z[2] = (long)p1; return z;
2169:
2170: case t_FRAC: z = cgetg(3,t_FRAC);
2171: z[1] = lmppgcd(x,(GEN)y[1]);
2172: z[2] = licopy((GEN)y[2]); return z;
2173:
2174: case t_COMPLEX: case t_QUAD:
2175: return triv_cont_gcd(y,x);
2176:
2177: case t_PADIC:
2178: return padic_gcd(x,y);
2179:
2180: default: return gun; /* t_REAL */
2181: }
2182:
2183: case t_INTMOD:
2184: switch(ty)
2185: {
2186: case t_FRAC:
2187: av = avma; p1=mppgcd((GEN)x[1],(GEN)y[2]); avma = av;
2188: if (!is_pm1(p1)) err(operi,"g",tx,ty);
2189: return ggcd((GEN)y[1], x);
2190:
2191: case t_COMPLEX: case t_QUAD:
2192: return triv_cont_gcd(y,x);
2193:
2194: case t_PADIC:
2195: return padic_gcd(x,y);
2196: }
2197:
2198: case t_FRAC:
2199: switch(ty)
2200: {
2201: case t_COMPLEX: case t_QUAD:
2202: return triv_cont_gcd(y,x);
2203:
2204: case t_PADIC:
2205: return padic_gcd(x,y);
2206: }
2207:
2208: case t_COMPLEX: /* ty = PADIC or QUAD */
2209: return triv_cont_gcd(x,y);
2210:
2211: case t_PADIC: /* ty = QUAD */
2212: return triv_cont_gcd(y,x);
2213:
2214: default: return gun; /* tx = t_REAL */
2215: }
2216: return cont_gcd(y,x);
2217: }
2218:
2219: vx = gvar9(x); vy = gvar9(y);
2220: if (vy<vx) return cont_gcd(y,x);
2221: if (vx<vy) return cont_gcd(x,y);
2222: switch(tx)
2223: {
2224: case t_POLMOD:
2225: switch(ty)
2226: {
2227: case t_POLMOD: z=cgetg(3,t_POLMOD);
2228: if (gegal((GEN)x[1],(GEN)y[1]))
2229: { copyifstack(x[1],z[1]); }
2230: else
2231: z[1] = lgcd((GEN)x[1],(GEN)y[1]);
2232: if (lgef(z[1])<=3) z[2]=zero;
2233: else
2234: {
2235: av=avma; p1=ggcd((GEN)z[1],(GEN)x[2]);
2236: if (lgef(p1)>3)
2237: {
2238: tetpil=avma;
2239: p1=gerepile(av,tetpil,ggcd(p1,(GEN)y[2]));
2240: }
2241: z[2]=(long)p1;
2242: }
2243: return z;
2244:
2245: case t_POL: z=cgetg(3,t_POLMOD);
2246: copyifstack(x[1],z[1]); av=avma;
2247: p1=ggcd((GEN)x[1],(GEN)x[2]);
2248: if (lgef(p1)>3)
2249: { tetpil=avma; p1=gerepile(av,tetpil,ggcd(y,p1)); }
2250: z[2]=(long)p1; return z;
2251:
2252: case t_RFRAC:
2253: av = avma; p1=ggcd((GEN)x[1],(GEN)y[2]); avma = av;
2254: if (!gcmp1(p1)) err(operi,"g",tx,ty);
2255: return ggcd((GEN)y[1],x);
2256:
2257: case t_RFRACN:
2258: av=avma; p1=gred_rfrac(y); tetpil=avma;
2259: return gerepile(av,tetpil,ggcd(p1,x));
2260: }
2261: break;
2262:
2263: case t_POL:
2264: switch(ty)
2265: {
2266: case t_POL:
2267: return srgcd(x,y);
2268:
2269: case t_SER:
2270: return gpuigs(polx[vx],min(valp(y),gval(x,vx)));
2271:
2272: case t_RFRAC: case t_RFRACN: av=avma; z=cgetg(3,ty);
2273: z[1]=lgcd(x,(GEN)y[1]);
2274: z[2]=lcopy((GEN)y[2]); return z;
2275: }
2276: break;
2277:
2278: case t_SER:
2279: switch(ty)
2280: {
2281: case t_SER:
2282: return gpuigs(polx[vx],min(valp(x),valp(y)));
2283:
2284: case t_RFRAC: case t_RFRACN:
2285: return gpuigs(polx[vx],min(valp(x),gval(y,vx)));
2286: }
2287: break;
2288:
2289: case t_RFRAC: case t_RFRACN: z=cgetg(3,ty);
2290: if (!is_rfrac_t(ty)) err(operf,"g",tx,ty);
2291: p1 = gdiv((GEN)y[2], ggcd((GEN)x[2], (GEN)y[2]));
2292: tetpil = avma;
2293: z[2] = lpile((long)z,tetpil,gmul(p1, (GEN)x[2]));
2294: z[1] = lgcd((GEN)x[1], (GEN)y[1]); return z;
2295: }
2296: err(operf,"g",tx,ty);
2297: return NULL; /* not reached */
2298: }
2299:
2300: GEN glcm0(GEN x, GEN y)
2301: {
2302: return gassoc_proto(glcm,x,y);
2303: }
2304:
2305: GEN
2306: glcm(GEN x, GEN y)
2307: {
2308: long av,tx,ty,i,l;
2309: GEN p1,p2,z;
2310:
2311: ty = typ(y);
2312: if (is_matvec_t(ty))
2313: {
2314: l=lg(y); z=cgetg(l,ty);
2315: for (i=1; i<l; i++) z[i]=(long)glcm(x,(GEN)y[i]);
2316: return z;
2317: }
2318: tx = typ(x);
2319: if (is_matvec_t(tx))
2320: {
2321: l=lg(x); z=cgetg(l,tx);
2322: for (i=1; i<l; i++) z[i]=(long)glcm((GEN)x[i],y);
2323: return z;
2324: }
2325: if (tx==t_INT && ty==t_INT) return mpppcm(x,y);
2326: if (gcmp0(x)) return gzero;
2327:
2328: av = avma;
2329: p1 = ggcd(x,y); if (!gcmp1(p1)) y = gdiv(y,p1);
2330: p2 = gmul(x,y);
2331: switch(typ(p2))
2332: {
2333: case t_INT: if (signe(p2)<0) setsigne(p2,1);
2334: break;
2335: case t_POL:
2336: if (lgef(p2) <= 2) break;
2337: p1=leading_term(p2);
2338: if (typ(p1)==t_INT && signe(p1)<0) p2=gneg(p2);
2339: }
2340: return gerepileupto(av,p2);
2341: }
2342:
2343: static GEN
2344: polgcdnun(GEN x, GEN y)
2345: {
2346: long av1, av = avma, lim = stack_lim(av,1);
2347: GEN p1, yorig = y;
2348:
2349: for(;;)
2350: {
2351: av1 = avma; p1 = gres(x,y);
2352: if (gcmp0(p1))
2353: {
2354: avma = av1;
2355: if (lgef(y) == 3 && isinexactreal(y)) { avma = av; return gun; }
2356: return (y==yorig)? gcopy(y): gerepileupto(av,y);
2357: }
2358: x = y; y = p1;
2359: if (low_stack(lim,stack_lim(av,1)))
2360: {
2361: GEN *gptr[2]; x = gcopy(x); gptr[0]=&x; gptr[1]=&y;
2362: if(DEBUGMEM>1) err(warnmem,"polgcdnun");
2363: gerepilemanysp(av,av1,gptr,2);
2364: }
2365: }
2366: }
2367:
2368: /* return 1 if coeff explosion is not possible */
2369: static int
2370: issimplefield(GEN x)
2371: {
2372: long lx,i;
2373: switch(typ(x))
2374: {
2375: case t_REAL: case t_INTMOD: case t_PADIC: case t_SER:
2376: return 1;
2377: case t_POL:
2378: lx=lgef(x);
2379: for (i=2; i<lx; i++)
2380: if (issimplefield((GEN)x[i])) return 1;
2381: return 0;
2382: case t_COMPLEX: case t_POLMOD:
2383: return issimplefield((GEN)x[1]) || issimplefield((GEN)x[2]);
2384: }
2385: return 0;
2386: }
2387:
2388: int
2389: isrational(GEN x)
2390: {
2391: long i;
2392: for (i=lgef(x)-1; i>1; i--)
2393: switch(typ(x[i]))
2394: {
2395: case t_INT: case t_FRAC: break;
2396: default: return 0;
2397: }
2398: return 1;
2399: }
2400:
2401: static int
2402: can_use_modular_gcd(GEN x, GEN *mod, long *v)
2403: {
2404: GEN p1, p2;
2405: long i;
2406: for (i=lgef(x)-1; i>1; i--)
2407: {
2408: p1 = (GEN)x[i];
2409: switch(typ(p1))
2410: {
2411: case t_INT: case t_FRAC: break;
2412: case t_POLMOD:
2413: p2 = (GEN)p1[1];
2414: if (*mod)
2415: {
2416: if (!isrational((GEN)p1[2])) return 0;
2417: if (!gegal(*mod,p2)) return 0;
2418: } else
2419: {
2420: if (!isrational(p2)) return 0;
2421: *mod = p2; *v = varn(p2);
2422: }
2423: break;
2424: case t_POL:
2425: if (!isrational(p1)) return 0;
2426: if (*v >= 0)
2427: {
2428: if (*v != varn(p1)) return 0;
2429: } else *v = varn(p1);
2430: break;
2431: default: return 0;
2432: }
2433: }
2434: return 1;
2435: }
2436:
2437: static int
2438: isinexactfield(GEN x)
2439: {
2440: long lx,i;
2441: switch(typ(x))
2442: {
2443: case t_REAL: case t_PADIC: case t_SER:
2444: return 1;
2445: case t_POL:
2446: lx=lgef(x); if (lx == 2) return 0;/*true 0 polynomial*/
2447: for (i=2; i<lx; i++)
2448: if (isinexactfield((GEN)x[i])) return 1;
2449: return 0;
2450: case t_COMPLEX: case t_POLMOD:
2451: return isinexactfield((GEN)x[1]) || isinexactfield((GEN)x[2]);
2452: }
2453: return 0;
2454: }
2455:
2456: static GEN
2457: gcdmonome(GEN x, GEN y)
2458: {
2459: long tetpil,av=avma, dx=degpol(x), v=varn(x), e=gval(y,v);
2460: GEN p1,p2;
2461:
2462: if (dx < e) e = dx;
2463: p1=ggcd(leading_term(x),content(y)); p2=gpuigs(polx[v],e);
2464: tetpil=avma; return gerepile(av,tetpil,gmul(p1,p2));
2465: }
2466:
2467: /***********************************************************************/
2468: /** **/
2469: /** GENERIC EXTENDED GCD **/
2470: /** **/
2471: /***********************************************************************/
2472:
2473: static GEN
2474: polinvinexact(GEN x, GEN y)
2475: {
2476: ulong av = avma;
2477: long i,dx=degpol(x),dy=degpol(y),lz=dx+dy;
2478: GEN v,z;
2479:
2480: if (dx < 0 || dy < 0) err(talker,"non-invertible polynomial in polinvmod");
2481: z=cgetg(dy+2,t_POL); z[1]=y[1];
2482: v=cgetg(lz+1,t_COL);
2483: for (i=1; i<lz; i++) v[i]=zero;
2484: v[lz]=un; v=gauss(sylvestermatrix(y,x),v);
2485: for (i=2; i<dy+2; i++) z[i]=v[lz-i+2];
2486: z = normalizepol_i(z, dy+2);
2487: return gerepilecopy(av,z);
2488: }
2489:
2490: static GEN
2491: polinvmod(GEN x, GEN y)
2492: {
2493: long av,av1,tx,vx=varn(x),vy=varn(y);
2494: GEN u,v,d,p1;
2495:
2496: while (vx!=vy)
2497: {
2498: if (vx > vy)
2499: {
2500: d=cgetg(3,t_RFRAC);
2501: d[1]=(long)polun[vx];
2502: d[2]=lcopy(x); return d;
2503: }
2504: if (lgef(x)!=3) err(talker,"non-invertible polynomial in polinvmod");
2505: x=(GEN)x[2]; vx=gvar(x);
2506: }
2507: tx=typ(x);
2508: if (tx==t_POL)
2509: {
2510: if (isinexactfield(x) || isinexactfield(y))
2511: return polinvinexact(x,y);
2512:
2513: av=avma; d=subresext(x,y,&u,&v);
2514: if (gcmp0(d)) err(talker,"non-invertible polynomial in polinvmod");
2515: if (typ(d)==t_POL && varn(d)==vx)
2516: {
2517: if (lgef(d)>3) err(talker,"non-invertible polynomial in polinvmod");
2518: d=(GEN)d[2];
2519: }
2520: av1=avma; return gerepile(av,av1,gdiv(u,d));
2521: }
2522: if (!is_rfrac_t(tx)) err(typeer,"polinvmod");
2523: av=avma; p1=gmul((GEN)x[1],polinvmod((GEN)x[2],y));
2524: av1=avma; return gerepile(av,av1,gmod(p1,y));
2525: }
2526:
2527: GEN
2528: gbezout(GEN x, GEN y, GEN *u, GEN *v)
2529: {
2530: long tx=typ(x),ty=typ(y);
2531:
2532: if (tx==t_INT && ty==t_INT) return bezout(x,y,u,v);
2533: if (!is_extscalar_t(tx) || !is_extscalar_t(ty)) err(typeer,"gbezout");
2534: return bezoutpol(x,y,u,v);
2535: }
2536:
2537: GEN
2538: vecbezout(GEN x, GEN y)
2539: {
2540: GEN z=cgetg(4,t_VEC);
2541: z[3]=(long)gbezout(x,y,(GEN*)(z+1),(GEN*)(z+2));
2542: return z;
2543: }
2544:
2545: GEN
2546: vecbezoutres(GEN x, GEN y)
2547: {
2548: GEN z=cgetg(4,t_VEC);
2549: z[3]=(long)subresext(x,y,(GEN*)(z+1),(GEN*)(z+2));
2550: return z;
2551: }
2552:
2553: /*******************************************************************/
2554: /* */
2555: /* CONTENT / PRIMITIVE PART */
2556: /* */
2557: /*******************************************************************/
2558:
2559: GEN
2560: content(GEN x)
2561: {
2562: long lx,i,tx=typ(x);
2563: ulong av,tetpil;
2564: GEN p1,p2;
2565:
2566: if (is_scalar_t(tx))
2567: return tx==t_POLMOD? content((GEN)x[2]): gcopy(x);
2568: av = avma;
2569: switch(tx)
2570: {
2571: case t_RFRAC: case t_RFRACN:
2572: p1=content((GEN)x[1]);
2573: p2=content((GEN)x[2]); tetpil=avma;
2574: return gerepile(av,tetpil,gdiv(p1,p2));
2575:
2576: case t_VEC: case t_COL: case t_MAT:
2577: lx = lg(x); if (lx==1) return gun;
2578: p1=content((GEN)x[1]);
2579: for (i=2; i<lx; i++) p1 = ggcd(p1,content((GEN)x[i]));
2580: return gerepileupto(av,p1);
2581:
2582: case t_POL:
2583: if (!signe(x)) return gzero;
2584: lx = lgef(x); break;
2585: case t_SER:
2586: if (!signe(x)) return gzero;
2587: lx = lg(x); break;
2588: case t_QFR: case t_QFI:
2589: lx = 4; break;
2590:
2591: default: err(typeer,"content");
2592: return NULL; /* not reached */
2593: }
2594: for (i=lontyp[tx]; i<lx; i++)
2595: if (typ(x[i]) != t_INT) break;
2596: lx--; p1=(GEN)x[lx];
2597: if (i > lx)
2598: { /* integer coeffs */
2599: while (lx>lontyp[tx])
2600: {
2601: lx--; p1=mppgcd(p1,(GEN)x[lx]);
2602: if (is_pm1(p1)) { avma=av; return gun; }
2603: }
2604: }
2605: else
2606: {
2607: while (lx>lontyp[tx])
2608: {
2609: lx--; p1=ggcd(p1,(GEN)x[lx]);
2610: }
2611: if (isinexactreal(p1)) { avma=av; return gun; }
2612: }
2613: return av==avma? gcopy(p1): gerepileupto(av,p1);
2614: }
2615:
2616: GEN
2617: primitive_part(GEN x, GEN *c)
2618: {
2619: *c = content(x);
2620: if (gcmp1(*c)) *c = NULL; else x = gdiv(x,*c);
2621: return x;
2622: }
2623:
2624: /*******************************************************************/
2625: /* */
2626: /* SUBRESULTANT */
2627: /* */
2628: /*******************************************************************/
2629: /* for internal use */
2630: GEN
2631: gdivexact(GEN x, GEN y)
2632: {
2633: long i,lx;
2634: GEN z;
2635: if (gcmp1(y)) return x;
2636: switch(typ(x))
2637: {
2638: case t_INT:
2639: if (typ(y)==t_INT) return diviiexact(x,y);
2640: if (!signe(x)) return gzero;
2641: break;
2642: case t_INTMOD:
2643: case t_POLMOD: return gmul(x,ginv(y));
2644: case t_POL:
2645: switch(typ(y))
2646: {
2647: case t_INTMOD:
2648: case t_POLMOD: return gmul(x,ginv(y));
2649: case t_POL:
2650: if (varn(x)==varn(y)) return poldivres(x,y, ONLY_DIVIDES_EXACT);
2651: }
2652: lx = lgef(x); z = cgetg(lx,t_POL);
2653: for (i=2; i<lx; i++) z[i]=(long)gdivexact((GEN)x[i],y);
2654: z[1]=x[1]; return z;
2655: case t_VEC: case t_COL: case t_MAT:
2656: lx = lg(x); z = cgetg(lx, typ(x));
2657: for (i=1; i<lx; i++) z[i]=(long)gdivexact((GEN)x[i],y);
2658: return z;
2659: }
2660: if (DEBUGLEVEL) err(warner,"missing case in gdivexact");
2661: return gdiv(x,y);
2662: }
2663:
2664: static GEN
2665: init_resultant(GEN x, GEN y)
2666: {
2667: long tx,ty;
2668: if (gcmp0(x) || gcmp0(y)) return gzero;
2669: tx = typ(x); ty = typ(y);
2670: if (is_scalar_t(tx) || is_scalar_t(ty))
2671: {
2672: if (tx==t_POL) return gpuigs(y,degpol(x));
2673: if (ty==t_POL) return gpuigs(x,degpol(y));
2674: return gun;
2675: }
2676: if (tx!=t_POL || ty!=t_POL) err(typeer,"subresall");
2677: if (varn(x)==varn(y)) return NULL;
2678: return (varn(x)<varn(y))? gpuigs(y,degpol(x)): gpuigs(x,degpol(y));
2679: }
2680:
2681: /* return coefficients s.t x = x_0 X^n + ... + x_n */
2682: static GEN
2683: revpol(GEN x)
2684: {
2685: long i,n = degpol(x);
2686: GEN y = cgetg(n+3,t_POL);
2687: y[1] = x[1]; x += 2; y += 2;
2688: for (i=0; i<=n; i++) y[i] = x[n-i];
2689: return y;
2690: }
2691:
2692: /* assume dx >= dy, y non constant */
2693: GEN
2694: pseudorem(GEN x, GEN y)
2695: {
2696: long av = avma, av2,lim, vx = varn(x),dx,dy,dz,i,lx, p;
2697:
2698: if (!signe(y)) err(talker,"euclidean division by zero (pseudorem)");
2699: (void)new_chunk(2);
2700: dx=degpol(x); x = revpol(x);
2701: dy=degpol(y); y = revpol(y); dz=dx-dy; p = dz+1;
2702: av2 = avma; lim = stack_lim(av2,1);
2703: for (;;)
2704: {
2705: x[0] = lneg((GEN)x[0]); p--;
2706: for (i=1; i<=dy; i++)
2707: x[i] = ladd(gmul((GEN)y[0], (GEN)x[i]), gmul((GEN)x[0],(GEN)y[i]));
2708: for ( ; i<=dx; i++)
2709: x[i] = lmul((GEN)y[0], (GEN)x[i]);
2710: do { x++; dx--; } while (dx >= 0 && gcmp0((GEN)x[0]));
2711: if (dx < dy) break;
2712: if (low_stack(lim,stack_lim(av2,1)))
2713: {
2714: if(DEBUGMEM>1) err(warnmem,"pseudorem dx = %ld >= %ld",dx,dy);
2715: gerepilemanycoeffs(av2,x,dx+1);
2716: }
2717: }
2718: if (dx < 0) return zeropol(vx);
2719: lx = dx+3; x -= 2;
2720: x[0]=evaltyp(t_POL) | evallg(lx);
2721: x[1]=evalsigne(1) | evalvarn(vx) | evallgef(lx);
2722: x = revpol(x) - 2;
2723: return gerepileupto(av, gmul(x, gpowgs((GEN)y[0], p)));
2724: }
2725:
2726: extern void gerepilemanycoeffs2(long av, GEN x, long n, GEN y, long o);
2727:
2728: /* assume dx >= dy, y non constant
2729: * Compute z,r s.t lc(y)^(dx-dy+1) x = z y + r */
2730: GEN
2731: pseudodiv(GEN x, GEN y, GEN *ptr)
2732: {
2733: long av = avma, av2,lim, vx = varn(x),dx,dy,dz,i,iz,lx,lz,p;
2734: GEN z, r, ypow;
2735:
2736: if (!signe(y)) err(talker,"euclidean division by zero (pseudorem)");
2737: (void)new_chunk(2);
2738: dx=degpol(x); x = revpol(x);
2739: dy=degpol(y); y = revpol(y); dz=dx-dy; p = dz+1;
2740: lz = dz+3; z = cgetg(lz, t_POL) + 2;
2741: ypow = new_chunk(dz+1);
2742: ypow[0] = un;
2743: for (i=1; i<=dz; i++) ypow[i] = lmul((GEN)ypow[i-1], (GEN)y[0]);
2744: av2 = avma; lim = stack_lim(av2,1);
2745: for (iz=0;;)
2746: {
2747: p--;
2748: z[iz++] = lmul((GEN)x[0], (GEN)ypow[p]);
2749: x[0] = lneg((GEN)x[0]);
2750: for (i=1; i<=dy; i++)
2751: x[i] = ladd(gmul((GEN)y[0], (GEN)x[i]), gmul((GEN)x[0],(GEN)y[i]));
2752: for ( ; i<=dx; i++)
2753: x[i] = lmul((GEN)y[0], (GEN)x[i]);
2754: x++; dx--;
2755: while (dx >= dy && gcmp0((GEN)x[0])) { x++; dx--; z[iz++] = zero; }
2756: if (dx < dy) break;
2757: if (low_stack(lim,stack_lim(av2,1)))
2758: {
2759: if(DEBUGMEM>1) err(warnmem,"pseudodiv dx = %ld >= %ld",dx,dy);
2760: gerepilemanycoeffs2(av2,x,dx+1, z,iz);
2761: }
2762: }
2763: while (dx >= 0 && gcmp0((GEN)x[0])) { x++; dx--; }
2764: if (dx < 0)
2765: x = zeropol(vx);
2766: else
2767: {
2768: lx = dx+3; x -= 2;
2769: x[0] = evaltyp(t_POL) | evallg(lx);
2770: x[1] = evalsigne(1) | evalvarn(vx) | evallgef(lx);
2771: x = revpol(x) - 2;
2772: }
2773:
2774: z -= 2;
2775: z[0] = evaltyp(t_POL) | evallg(lz);
2776: z[1] = evalsigne(1) | evalvarn(vx) | evallgef(lz);
2777: z = revpol(z) - 2;
2778: r = gmul(x, (GEN)ypow[p]);
2779: {
2780: GEN *gptr[2]; gptr[0] = &z; gptr[1] = &r;
2781: gerepilemany(av,gptr,2);
2782: }
2783: *ptr = r; return z;
2784: }
2785:
2786: /* Return resultant(u,v). If sol != NULL: set *sol to the last non-zero
2787: * polynomial in the prs IF the sequence was computed, and gzero otherwise
2788: */
2789: GEN
2790: subresall(GEN u, GEN v, GEN *sol)
2791: {
2792: ulong av,av2,lim;
2793: long degq,dx,dy,du,dv,dr,signh;
2794: GEN z,g,h,r,p1,p2,cu,cv;
2795:
2796: if (sol) *sol=gzero;
2797: if ((r = init_resultant(u,v))) return r;
2798:
2799: if (isinexactfield(u) || isinexactfield(v)) return resultant2(u,v);
2800: dx=lgef(u); dy=lgef(v); signh=1;
2801: if (dx<dy)
2802: {
2803: swap(u,v); lswap(dx,dy);
2804: if (both_even(dx, dy)) signh = -signh;
2805: }
2806: if (dy==3) return gpowgs((GEN)v[2],dx-3);
2807: av = avma;
2808: u = primitive_part(u, &cu);
2809: v = primitive_part(v, &cv);
2810: g = h = gun; av2 = avma; lim = stack_lim(av2,1);
2811: for(;;)
2812: {
2813: r = pseudorem(u,v); dr = lgef(r);
2814: if (dr == 2)
2815: {
2816: if (sol) { avma = (long)(r+2); *sol=gerepileupto(av,v); } else avma = av;
2817: return gzero;
2818: }
2819: du = lgef(u); dv = lgef(v); degq = du-dv;
2820: u = v; p1 = g; g = leading_term(u);
2821: switch(degq)
2822: {
2823: case 0: break;
2824: case 1:
2825: p1 = gmul(h,p1); h = g; break;
2826: default:
2827: p1 = gmul(gpowgs(h,degq),p1);
2828: h = gdivexact(gpowgs(g,degq), gpowgs(h,degq-1));
2829: }
2830: if (both_even(du,dv)) signh = -signh;
2831: v = gdivexact(r,p1);
2832: if (dr==3) break;
2833: if (low_stack(lim,stack_lim(av2,1)))
2834: {
2835: GEN *gptr[4]; gptr[0]=&u; gptr[1]=&v; gptr[2]=&g; gptr[3]=&h;
2836: if(DEBUGMEM>1) err(warnmem,"subresall, dr = %ld",dr);
2837: gerepilemany(av2,gptr,4);
2838: }
2839: }
2840: z = (GEN)v[2];
2841: if (dv > 4) z = gdivexact(gpowgs(z,dv-3), gpowgs(h,dv-4));
2842: if (signh < 0) z = gneg(z); /* z = resultant(ppart(x), ppart(y)) */
2843: p2 = gun;
2844: if (cu) p2 = gmul(p2, gpowgs(cu,dy-3));
2845: if (cv) p2 = gmul(p2, gpowgs(cv,dx-3));
2846: z = gmul(z, p2);
2847:
2848: if (sol) u = gclone(u);
2849: z = gerepileupto(av, z);
2850: if (sol) { *sol = forcecopy(u); gunclone(u); }
2851: return z;
2852: }
2853:
2854: static GEN
2855: scalar_res(GEN x, GEN y, GEN *U, GEN *V)
2856: {
2857: long dx=lgef(x)-4;
2858: *V=gpuigs(y,dx); *U=gzero; return gmul(y,*V);
2859: }
2860:
2861: /* compute U, V s.t Ux + Vy = resultant(x,y) */
2862: GEN
2863: subresext(GEN x, GEN y, GEN *U, GEN *V)
2864: {
2865: ulong av,av2,tetpil,lim;
2866: long degq,tx,ty,dx,dy,du,dv,dr,signh;
2867: GEN q,z,g,h,r,p1,p2,cu,cv,u,v,um1,uze,vze,xprim,yprim;
2868:
2869: if (gcmp0(x) || gcmp0(y)) { *U = *V = gzero; return gzero; }
2870: tx=typ(x); ty=typ(y);
2871: if (is_scalar_t(tx) || is_scalar_t(ty))
2872: {
2873: if (tx==t_POL) return scalar_res(x,y,U,V);
2874: if (ty==t_POL) return scalar_res(y,x,V,U);
2875: *U = ginv(x); *V = gzero; return gun;
2876: }
2877: if (tx!=t_POL || ty!=t_POL) err(typeer,"subresext");
2878: if (varn(x) != varn(y))
2879: return (varn(x)<varn(y))? scalar_res(x,y,U,V)
2880: : scalar_res(y,x,V,U);
2881: dx = lgef(x); dy = lgef(y); signh = 1;
2882: if (dx < dy)
2883: {
2884: pswap(U,V); lswap(dx,dy); swap(x,y);
2885: if (both_even(dx, dy)) signh = -signh;
2886: }
2887: if (dy == 3)
2888: {
2889: *V = gpowgs((GEN)y[2],dx-4);
2890: *U = gzero; return gmul(*V,(GEN)y[2]);
2891: }
2892: av = avma;
2893: u = primitive_part(x, &cu); xprim = u;
2894: v = primitive_part(y, &cv); yprim = v;
2895: g = h = gun; av2 = avma; lim = stack_lim(av2,1);
2896: um1 = gun; uze = gzero;
2897: for(;;)
2898: {
2899: q = pseudodiv(u,v, &r); dr = lgef(r);
2900: if (dr == 2) { *U = *V = gzero; avma = av; return gzero; }
2901:
2902: du = lgef(u); dv = lgef(v); degq = du-dv;
2903: /* lead(v)^(degq + 1) * um1 - q * uze */
2904: p1 = gsub(gmul(gpowgs((GEN)v[dv-1],degq+1),um1), gmul(q,uze));
2905: um1 = uze; uze = p1;
2906: u = v; p1 = g; g = leading_term(u);
2907: switch(degq)
2908: {
2909: case 0: break;
2910: case 1: p1 = gmul(h,p1); h = g; break;
2911: default:
2912: p1 = gmul(gpowgs(h,degq),p1);
2913: h = gdivexact(gpowgs(g,degq), gpowgs(h,degq-1));
2914: }
2915: if (both_even(du, dv)) signh = -signh;
2916: v = gdivexact(r,p1);
2917: uze= gdivexact(uze,p1);
2918: if (dr==3) break;
2919: if (low_stack(lim,stack_lim(av2,1)))
2920: {
2921: GEN *gptr[6]; gptr[0]=&u; gptr[1]=&v; gptr[2]=&g; gptr[3]=&h;
2922: gptr[4]=&uze; gptr[5]=&um1;
2923: if(DEBUGMEM>1) err(warnmem,"subresext, dr = %ld",dr);
2924: gerepilemany(av2,gptr,6);
2925: }
2926: }
2927: z = (GEN)v[2];
2928: if (dv > 4)
2929: {
2930: /* z = gdivexact(gpowgs(z,dv-3), gpowgs(h,dv-4)); */
2931: p1 = gpowgs(gdiv(z,h),dv-4);
2932: z = gmul(z,p1); uze = gmul(uze,p1);
2933: }
2934: if (signh < 0) { z = gneg_i(z); uze = gneg_i(uze); }
2935: p1 = gadd(z, gneg(gmul(uze,xprim)));
2936: if (!poldivis(p1,yprim,&vze)) err(bugparier,"subresext");
2937: /* uze ppart(x) + vze ppart(y) = z = resultant(ppart(x), ppart(y)), */
2938: p2 = gun;
2939: if (cu) p2 = gmul(p2, gpowgs(cu,dy-3));
2940: if (cv) p2 = gmul(p2, gpowgs(cv,dx-3));
2941: cu = cu? gdiv(p2,cu): p2;
2942: cv = cv? gdiv(p2,cv): p2;
2943:
2944: tetpil = avma;
2945: z = gmul(z,p2); uze = gmul(uze,cu); vze = gmul(vze,cv);
2946: {
2947: GEN *gptr[3]; gptr[0]=&z; gptr[1]=&uze; gptr[2]=&vze;
2948: gerepilemanysp(av,tetpil,gptr,3);
2949: }
2950: *U = uze; *V = vze; return z;
2951: }
2952:
2953: static GEN
2954: scalar_bezout(GEN x, GEN y, GEN *U, GEN *V)
2955: {
2956: *U=gzero; *V=ginv(y); return polun[varn(x)];
2957: }
2958:
2959: static GEN
2960: zero_bezout(GEN y, GEN *U, GEN *V)
2961: {
2962: GEN x=content(y);
2963: *U=gzero; *V = ginv(x); return gmul(y,*V);
2964: }
2965:
2966: /* compute U, V s.t Ux + Vy = GCD(x,y) using subresultant */
2967: GEN
2968: bezoutpol(GEN x, GEN y, GEN *U, GEN *V)
2969: {
2970: ulong av,av2,tetpil,lim;
2971: long degq,tx,ty,dx,dy,du,dv,dr;
2972: GEN q,z,g,h,r,p1,cu,cv,u,v,um1,uze,vze,xprim,yprim, *gptr[3];
2973:
2974: if (gcmp0(x)) return zero_bezout(y,U,V);
2975: if (gcmp0(y)) return zero_bezout(x,V,U);
2976: tx=typ(x); ty=typ(y); av=avma;
2977: if (is_scalar_t(tx) || is_scalar_t(ty))
2978: {
2979: if (tx==t_POL) return scalar_bezout(x,y,U,V);
2980: if (ty==t_POL) return scalar_bezout(y,x,V,U);
2981: *U = ginv(x); *V = gzero; return polun[0];
2982: }
2983: if (tx!=t_POL || ty!=t_POL) err(typeer,"bezoutpol");
2984: if (varn(x)!=varn(y))
2985: return (varn(x)<varn(y))? scalar_bezout(x,y,U,V)
2986: : scalar_bezout(y,x,V,U);
2987: dx = lgef(x); dy = lgef(y);
2988: if (dx < dy)
2989: {
2990: pswap(U,V); lswap(dx,dy); swap(x,y);
2991: }
2992: if (dy==3) return scalar_bezout(x,y,U,V);
2993:
2994: u = primitive_part(x, &cu); xprim = u;
2995: v = primitive_part(y, &cv); yprim = v;
2996: g = h = gun; av2 = avma; lim = stack_lim(av2,1);
2997: um1 = gun; uze = gzero;
2998: for(;;)
2999: {
3000: q = pseudodiv(u,v, &r); dr = lgef(r);
3001: if (dr == 2) break;
3002:
3003: du = lgef(u); dv = lgef(v); degq = du-dv;
3004: p1 = gsub(gmul(gpowgs((GEN)v[dv-1],degq+1),um1), gmul(q,uze));
3005: um1 = uze; uze = p1;
3006: u = v; p1 = g; g = leading_term(u);
3007: switch(degq)
3008: {
3009: case 0: break;
3010: case 1:
3011: p1 = gmul(h,p1); h = g; break;
3012: default:
3013: p1 = gmul(gpowgs(h,degq), p1);
3014: h = gdiv(gpowgs(g,degq), gpowgs(h,degq-1));
3015: }
3016: v = gdivexact(r,p1);
3017: uze= gdivexact(uze,p1);
3018: if (dr==3) break;
3019: if (low_stack(lim,stack_lim(av2,1)))
3020: {
3021: GEN *gptr[6]; gptr[0]=&u; gptr[1]=&v; gptr[2]=&g; gptr[3]=&h;
3022: gptr[4]=&uze; gptr[5]=&um1;
3023: if(DEBUGMEM>1) err(warnmem,"bezoutpol, dr = %ld",dr);
3024: gerepilemany(av2,gptr,6);
3025: }
3026: }
3027: if (!poldivis(gsub(v,gmul(uze,xprim)),yprim, &vze))
3028: err(warner,"inexact computation in bezoutpol");
3029: if (cu) uze = gdiv(uze,cu);
3030: if (cv) vze = gdiv(vze,cv);
3031: p1 = ginv(content(v)); tetpil = avma;
3032:
3033: uze = gmul(uze,p1);
3034: vze = gmul(vze,p1);
3035: z = gmul(v,p1);
3036: gptr[0]=&uze; gptr[1]=&vze; gptr[2]=&z;
3037: gerepilemanysp(av,tetpil,gptr,3);
3038: *U = uze; *V = vze; return z;
3039: }
3040:
3041: /*******************************************************************/
3042: /* */
3043: /* RESULTANT USING DUCOS VARIANT */
3044: /* */
3045: /*******************************************************************/
3046:
3047: static GEN
3048: reductum(GEN P)
3049: {
3050: if (signe(P)==0) return P;
3051: return normalizepol_i(dummycopy(P),lgef(P)-1);
3052: }
3053:
3054: static GEN
3055: Lazard(GEN x, GEN y, long n)
3056: {
3057: long a, b;
3058: GEN c;
3059:
3060: if (n<=1) return x;
3061: a=1; while (n >= (b=a+a)) a=b;
3062: c=x; n-=a;
3063: while (a>1)
3064: {
3065: a>>=1; c=gdivexact(gsqr(c),y);
3066: if (n>=a) { c=gdivexact(gmul(c,x),y); n -= a; }
3067: }
3068: return c;
3069: }
3070:
3071: static GEN
3072: Lazard2(GEN F, GEN x, GEN y, long n)
3073: {
3074: if (n<=1) return F;
3075: x = Lazard(x,y,n-1); return gdivexact(gmul(x,F),y);
3076: }
3077:
3078: extern GEN addshiftpol(GEN x, GEN y, long d);
3079: #define addshift(x,y) addshiftpol((x),(y),1)
3080:
3081: static GEN
3082: nextSousResultant(GEN P, GEN Q, GEN Z, GEN s)
3083: {
3084: GEN p0, q0, z0, H, A;
3085: long p, q, j, av, lim, v = varn(P);
3086:
3087: z0 = leading_term(Z);
3088: p = degpol(P); p0 = leading_term(P); P = reductum(P);
3089: q = degpol(Q); q0 = leading_term(Q); Q = reductum(Q);
3090:
3091: av = avma; lim = stack_lim(av,1);
3092: H = gneg(reductum(Z));
3093: A = gmul((GEN)P[q+2],H);
3094: for (j = q+1; j < p; j++)
3095: {
3096: H = (degpol(H) == q-1) ?
3097: addshift(reductum(H), gdivexact(gmul(gneg((GEN)H[q+1]),Q), q0)) :
3098: addshift(H, zeropol(v));
3099: A = gadd(A,gmul((GEN)P[j+2],H));
3100: if (low_stack(lim,stack_lim(av,1)))
3101: {
3102: GEN *gptr[2]; gptr[0]=&A; gptr[1]=&H;
3103: if(DEBUGMEM>1) err(warnmem,"nextSousResultant j = %ld/%ld",j,p);
3104: gerepilemany(av,gptr,2);
3105: }
3106: }
3107: P = normalizepol_i(P, q+2);
3108: A = gdivexact(gadd(A,gmul(z0,P)), p0);
3109: A = (degpol(H) == q-1) ?
3110: gadd(gmul(q0,addshift(reductum(H),A)), gmul(gneg((GEN)H[q+1]),Q)) :
3111: gmul(q0, addshift(H,A));
3112: return gdivexact(A, ((p-q)&1)? s: gneg(s));
3113: }
3114:
3115: GEN
3116: resultantducos(GEN P, GEN Q)
3117: {
3118: ulong av = avma, av2,lim;
3119: long dP,dQ,delta;
3120: GEN cP,cQ,Z,s;
3121:
3122: if ((Z = init_resultant(P,Q))) return Z;
3123: dP = degpol(P);
3124: dQ = degpol(Q);
3125: P = primitive_part(P, &cP);
3126: Q = primitive_part(Q, &cQ);
3127: delta = dP - dQ;
3128: if (delta < 0)
3129: {
3130: Z = (dP & dQ & 1)? gneg(Q): Q;
3131: Q = P; P = Z; delta = -delta;
3132: }
3133: s = gun;
3134: if (degpol(Q) > 0)
3135: {
3136: av2 = avma; lim = stack_lim(av2,1);
3137: s = gpuigs(leading_term(Q),delta);
3138: Z = Q;
3139: Q = pseudorem(P, gneg(Q));
3140: P = Z;
3141: while(degpol(Q) > 0)
3142: {
3143: if (low_stack(lim,stack_lim(av,1)))
3144: {
3145: GEN *gptr[2]; gptr[0]=&P; gptr[1]=&Q;
3146: if(DEBUGMEM>1) err(warnmem,"resultantducos, degpol Q = %ld",degpol(Q));
3147: gerepilemany(av2,gptr,2); s = leading_term(P);
3148: }
3149: delta = degpol(P) - degpol(Q);
3150: Z = Lazard2(Q, leading_term(Q), s, delta);
3151: Q = nextSousResultant(P, Q, Z, s);
3152: P = Z;
3153: s = leading_term(P);
3154: }
3155: }
3156: if (!signe(Q)) { avma = av; return gzero; }
3157: if (!degpol(P)){ avma = av; return gun; }
3158: s = Lazard(leading_term(Q), s, degpol(P));
3159: if (cP) s = gmul(s, gpowgs(cP,dQ));
3160: if (cQ) s = gmul(s, gpowgs(cQ,dP)); else if (!cP) s = gcopy(s);
3161: return gerepileupto(av, s);
3162: }
3163:
3164: /*******************************************************************/
3165: /* */
3166: /* RESULTANT USING SYLVESTER MATRIX */
3167: /* */
3168: /*******************************************************************/
3169: static GEN
3170: _zeropol(void)
3171: {
3172: GEN x = cgetg(3,t_POL);
3173: x[1] = evallgef(3);
3174: x[2] = zero; return x;
3175: }
3176:
3177: static GEN
3178: sylvester_col(GEN x, long j, long d, long D)
3179: {
3180: GEN c = cgetg(d+1,t_COL);
3181: long i;
3182: for (i=1; i< j; i++) c[i]=zero;
3183: for ( ; i<=D; i++) c[i]=x[D-i+2];
3184: for ( ; i<=d; i++) c[i]=zero;
3185: return c;
3186: }
3187:
3188: GEN
3189: sylvestermatrix_i(GEN x, GEN y)
3190: {
3191: long j,d,dx,dy;
3192: GEN M;
3193:
3194: dx = degpol(x); if (dx < 0) { dx = 0; x = _zeropol(); }
3195: dy = degpol(y); if (dy < 0) { dy = 0; y = _zeropol(); }
3196: d = dx+dy; M = cgetg(d+1,t_MAT);
3197: for (j=1; j<=dy; j++) M[j] = (long)sylvester_col(x,j,d,j+dx);
3198: for (j=1; j<=dx; j++) M[j+dy] = (long)sylvester_col(y,j,d,j+dy);
3199: return M;
3200: }
3201:
3202: GEN
3203: sylvestermatrix(GEN x, GEN y)
3204: {
3205: long i,j,lx;
3206: if (typ(x)!=t_POL || typ(y)!=t_POL) err(typeer,"sylvestermatrix");
3207: if (varn(x) != varn(y))
3208: err(talker,"not the same variables in sylvestermatrix");
3209: x = sylvestermatrix_i(x,y); lx = lg(x);
3210: for (i=1; i<lx; i++)
3211: for (j=1; j<lx; j++) coeff(x,i,j) = lcopy(gcoeff(x,i,j));
3212: return x;
3213: }
3214:
3215: GEN
3216: resultant2(GEN x, GEN y)
3217: {
3218: long av;
3219: GEN r;
3220: if ((r = init_resultant(x,y))) return r;
3221: av = avma; return gerepileupto(av,det(sylvestermatrix_i(x,y)));
3222: }
3223:
3224: static GEN
3225: fix_pol(GEN x, long v, long *mx)
3226: {
3227: long vx;
3228: GEN p1;
3229:
3230: if (typ(x) == t_POL)
3231: {
3232: vx = varn(x);
3233: if (vx)
3234: {
3235: if (v>=vx) return gsubst(x,v,polx[0]);
3236: p1 = cgetg(3,t_POL);
3237: p1[1] = evalvarn(0)|evalsigne(signe(x))|evallgef(3);
3238: p1[2] = (long)x; return p1;
3239: }
3240: if (v)
3241: {
3242: *mx = 1;
3243: return gsubst(gsubst(x,0,polx[MAXVARN]),v,polx[0]);
3244: }
3245: }
3246: return x;
3247: }
3248:
3249: /* resultant of x and y with respect to variable v, or with respect to their
3250: * main variable if v < 0. */
3251: GEN
3252: polresultant0(GEN x, GEN y, long v, long flag)
3253: {
3254: long av = avma, m = 0;
3255:
3256: if (v >= 0)
3257: {
3258: x = fix_pol(x,v, &m);
3259: y = fix_pol(y,v, &m);
3260: }
3261: switch(flag)
3262: {
3263: case 0: x=subresall(x,y,NULL); break;
3264: case 1: x=resultant2(x,y); break;
3265: case 2: x=resultantducos(x,y); break;
3266: default: err(flagerr,"polresultant");
3267: }
3268: if (m) x = gsubst(x,MAXVARN,polx[0]);
3269: return gerepileupto(av,x);
3270: }
3271:
3272: /*******************************************************************/
3273: /* */
3274: /* GCD USING SUBRESULTANT */
3275: /* */
3276: /*******************************************************************/
3277: extern GEN nfgcd(GEN P, GEN Q, GEN nf, GEN den);
3278: extern GEN to_polmod(GEN x, GEN mod);
3279:
3280: GEN
3281: srgcd(GEN x, GEN y)
3282: {
3283: long av,av1,tetpil,tx=typ(x),ty=typ(y),dx,dy,vx,vmod,lim;
3284: GEN d,g,h,p1,p2,u,v,mod,cx,cy;
3285:
3286: if (!signe(y)) return gcopy(x);
3287: if (!signe(x)) return gcopy(y);
3288: if (is_scalar_t(tx) || is_scalar_t(ty)) return gun;
3289: if (tx!=t_POL || ty!=t_POL) err(typeer,"srgcd");
3290: vx=varn(x); if (vx!=varn(y)) return gun;
3291: if (ismonome(x)) return gcdmonome(x,y);
3292: if (ismonome(y)) return gcdmonome(y,x);
3293: av = avma;
3294: mod = NULL; vmod = -1;
3295: if (can_use_modular_gcd(x, &mod, &vmod) &&
3296: can_use_modular_gcd(y, &mod, &vmod))
3297: {
3298: if (mod)
3299: { /* (Q[Y]/mod)[X]*/
3300: x = primitive_part(lift(x), &cx);
3301: y = primitive_part(lift(y), &cy);
3302: if (cx)
3303: { if (cy) cx = ggcd(cx,cy); }
3304: else
3305: cx = cy;
3306: d = nfgcd(x,y,mod,NULL); if (cx) d = gmul(d,cx);
3307: return gerepileupto(av, gmul(d, to_polmod(gun,mod)));
3308: }
3309: if (vmod < 0) return modulargcd(x,y); /* Q[X] */
3310: }
3311:
3312: if (issimplefield(x) || issimplefield(y)) x = polgcdnun(x,y);
3313: else
3314: {
3315: dx=lgef(x); dy=lgef(y);
3316: if (dx<dy) { swap(x,y); lswap(dx,dy); }
3317: p1=content(x); p2=content(y); d=ggcd(p1,p2);
3318:
3319: tetpil=avma; d=gmul(d,polun[vx]);
3320: if (dy==3) return gerepile(av,tetpil,d);
3321:
3322: av1=avma; lim=stack_lim(av1,1);
3323: u=gdiv(x,p1); v=gdiv(y,p2); g=h=gun;
3324: for(;;)
3325: {
3326: GEN r = pseudorem(u,v);
3327: long degq, du, dv, dr=lgef(r);
3328:
3329: if (dr <= 3)
3330: {
3331: if (gcmp0(r)) break;
3332: avma=av1; return gerepile(av,tetpil,d);
3333: }
3334: if (DEBUGLEVEL > 9) fprintferr("srgcd: dr = %ld\n", dr);
3335: du=lgef(u); dv=lgef(v); degq=du-dv; u=v;
3336: switch(degq)
3337: {
3338: case 0:
3339: v = gdiv(r,g);
3340: g = leading_term(u);
3341: break;
3342: case 1:
3343: v = gdiv(r,gmul(h,g));
3344: h = g = leading_term(u);
3345: break;
3346: default:
3347: v = gdiv(r,gmul(gpuigs(h,degq),g));
3348: g = leading_term(u);
3349: h = gdiv(gpuigs(g,degq), gpuigs(h,degq-1));
3350: }
3351: if (low_stack(lim, stack_lim(av1,1)))
3352: {
3353: GEN *gptr[4]; gptr[0]=&u; gptr[1]=&v; gptr[2]=&g; gptr[3]=&h;
3354: if(DEBUGMEM>1) err(warnmem,"srgcd");
3355: gerepilemany(av1,gptr,4);
3356: }
3357: }
3358: p1 = content(v); if (!gcmp1(p1)) v = gdiv(v,p1);
3359: x = gmul(d,v);
3360: }
3361:
3362: if (typ(x)!=t_POL) x = gmul(polun[vx],x);
3363: else
3364: {
3365: p1=leading_term(x); ty=typ(p1);
3366: if ((is_frac_t(ty) || is_intreal_t(ty)) && gsigne(p1)<0) x = gneg(x);
3367: }
3368: return gerepileupto(av,x);
3369: }
3370:
3371: extern GEN qf_disc(GEN x, GEN y, GEN z);
3372:
3373: GEN
3374: poldisc0(GEN x, long v)
3375: {
3376: long av,tx=typ(x),i;
3377: GEN z,p1,p2;
3378:
3379: switch(tx)
3380: {
3381: case t_POL:
3382: if (gcmp0(x)) return gzero;
3383: av = avma; i = 0;
3384: if (v >= 0 && v != varn(x)) x = fix_pol(x,v, &i);
3385: p1 = subres(x, derivpol(x));
3386: p2 = leading_term(x); if (!gcmp1(p2)) p1 = gdiv(p1,p2);
3387: if (degpol(x) & 2) p1 = gneg(p1);
3388: if (i) p1 = gsubst(p1, MAXVARN, polx[0]);
3389: return gerepileupto(av,p1);
3390:
3391: case t_COMPLEX:
3392: return stoi(-4);
3393:
3394: case t_QUAD: case t_POLMOD:
3395: return poldisc0((GEN)x[1], v);
3396:
3397: case t_QFR: case t_QFI:
3398: av = avma; return gerepileuptoint(av, qf_disc(x,NULL,NULL));
3399:
3400: case t_VEC: case t_COL: case t_MAT:
3401: i=lg(x); z=cgetg(i,tx);
3402: for (i--; i; i--) z[i]=(long)poldisc0((GEN)x[i], v);
3403: return z;
3404: }
3405: err(typeer,"discsr");
3406: return NULL; /* not reached */
3407: }
3408:
3409: GEN
3410: discsr(GEN x)
3411: {
3412: return poldisc0(x, -1);
3413: }
3414:
3415: GEN
3416: reduceddiscsmith(GEN pol)
3417: {
3418: long av=avma,tetpil,i,j,n;
3419: GEN polp,alpha,p1,m;
3420:
3421: if (typ(pol)!=t_POL) err(typeer,"reduceddiscsmith");
3422: n=degpol(pol);
3423: if (n<=0) err(constpoler,"reduceddiscsmith");
3424: check_pol_int(pol,"poldiscreduced");
3425: if (!gcmp1((GEN)pol[n+2]))
3426: err(talker,"non-monic polynomial in poldiscreduced");
3427: polp = derivpol(pol); alpha = polx[varn(pol)];
3428: m=cgetg(n+1,t_MAT);
3429: for (j=1; j<=n; j++)
3430: {
3431: p1=cgetg(n+1,t_COL); m[j]=(long)p1;
3432: for (i=1; i<=n; i++) p1[i]=(long)truecoeff(polp,i-1);
3433: if (j<n) polp = gres(gmul(alpha,polp), pol);
3434: }
3435: tetpil=avma; return gerepile(av,tetpil,smith(m));
3436: }
3437:
3438: /***********************************************************************/
3439: /** **/
3440: /** STURM ALGORITHM **/
3441: /** (number of real roots of x in ]a,b]) **/
3442: /** **/
3443: /***********************************************************************/
3444:
3445: /* if a (resp. b) is NULL, set it to -oo (resp. +oo) */
3446: long
3447: sturmpart(GEN x, GEN a, GEN b)
3448: {
3449: long av = avma, lim = stack_lim(av,1), sl,sr,s,t,r1;
3450: GEN g,h,u,v;
3451:
3452: if (typ(x) != t_POL) err(typeer,"sturm");
3453: if (gcmp0(x)) err(zeropoler,"sturm");
3454: s=lgef(x); if (s==3) return 0;
3455:
3456: sl = gsigne(leading_term(x));
3457: if (s==4)
3458: {
3459: t = a? gsigne(poleval(x,a)): -sl;
3460: if (t == 0) { avma = av; return 0; }
3461: s = b? gsigne(poleval(x,b)): sl;
3462: avma = av; return (s == t)? 0: 1;
3463: }
3464: u=gdiv(x,content(x)); v=derivpol(x);
3465: v=gdiv(v,content(v));
3466: g=gun; h=gun;
3467: s = b? gsigne(poleval(u,b)): sl;
3468: t = a? gsigne(poleval(u,a)): ((lgef(u)&1)? sl: -sl);
3469: r1=0;
3470: sr = b? gsigne(poleval(v,b)): s;
3471: if (sr)
3472: {
3473: if (!s) s=sr;
3474: else if (sr!=s) { s= -s; r1--; }
3475: }
3476: sr = a? gsigne(poleval(v,a)): -t;
3477: if (sr)
3478: {
3479: if (!t) t=sr;
3480: else if (sr!=t) { t= -t; r1++; }
3481: }
3482: for(;;)
3483: {
3484: GEN p1, r = pseudorem(u,v);
3485: long du=lgef(u), dv=lgef(v), dr=lgef(r), degq=du-dv;
3486:
3487: if (dr<=2) err(talker,"not a squarefree polynomial in sturm");
3488: if (gsigne(leading_term(v)) > 0 || degq&1) r=gneg_i(r);
3489: sl = gsigne((GEN) r[dr-1]);
3490: sr = b? gsigne(poleval(r,b)): sl;
3491: if (sr)
3492: {
3493: if (!s) s=sr;
3494: else if (sr!=s) { s= -s; r1--; }
3495: }
3496: sr = a? gsigne(poleval(r,a)): ((dr&1)? sl: -sl);
3497: if (sr)
3498: {
3499: if (!t) t=sr;
3500: else if (sr!=t) { t= -t; r1++; }
3501: }
3502: if (dr==3) { avma=av; return r1; }
3503:
3504: u=v; p1 = g; g = gabs(leading_term(u),DEFAULTPREC);
3505: switch(degq)
3506: {
3507: case 0: break;
3508: case 1:
3509: p1 = gmul(h,p1); h = g; break;
3510: default:
3511: p1 = gmul(gpuigs(h,degq),p1);
3512: h = gdivexact(gpuigs(g,degq), gpuigs(h,degq-1));
3513: }
3514: v = gdivexact(r,p1);
3515: if (low_stack(lim,stack_lim(av,1)))
3516: {
3517: GEN *gptr[4]; gptr[0]=&u; gptr[1]=&v; gptr[2]=&g; gptr[3]=&h;
3518: if(DEBUGMEM>1) err(warnmem,"polsturm, dr = %ld",dr);
3519: gerepilemany(av,gptr,4);
3520: }
3521: }
3522: }
3523:
3524: /*******************************************************************/
3525: /* */
3526: /* QUADRATIC POLYNOMIAL ASSOCIATED TO A DISCRIMINANT */
3527: /* */
3528: /*******************************************************************/
3529:
3530: GEN
3531: quadpoly0(GEN x, long v)
3532: {
3533: long res,l,tetpil,i,sx, tx = typ(x);
3534: GEN y,p1;
3535:
3536: if (is_matvec_t(tx))
3537: {
3538: l=lg(x); y=cgetg(l,tx);
3539: for (i=1; i<l; i++) y[i]=(long)quadpoly0((GEN)x[i],v);
3540: return y;
3541: }
3542: if (tx!=t_INT) err(arither1);
3543: if (v < 0) v = 0;
3544: sx=signe(x);
3545: if (!sx) err(talker,"zero discriminant in quadpoly");
3546: y=cgetg(5,t_POL);
3547: y[1]=evalsigne(1) | evalvarn(v) | evallgef(5); y[4]=un;
3548: res=mod4(x); if (sx<0 && res) res=4-res;
3549: if (res>1) err(funder2,"quadpoly");
3550:
3551: l=avma; p1=shifti(x,-2); setsigne(p1,-signe(p1));
3552: y[2] = (long) p1;
3553: if (!res) y[3] = zero;
3554: else
3555: {
3556: if (sx<0) { tetpil=avma; y[2] = lpile(l,tetpil,addsi(1,p1)); }
3557: y[3] = lnegi(gun);
3558: }
3559: return y;
3560: }
3561:
3562: GEN
3563: quadpoly(GEN x)
3564: {
3565: return quadpoly0(x,-1);
3566: }
3567:
3568: GEN
3569: quadgen(GEN x)
3570: {
3571: GEN y=cgetg(4,t_QUAD);
3572: y[1]=lquadpoly(x); y[2]=zero; y[3]=un; return y;
3573: }
3574:
3575: /*******************************************************************/
3576: /* */
3577: /* GENERIC (modular) INVERSE */
3578: /* */
3579: /*******************************************************************/
3580:
3581: GEN
3582: ginvmod(GEN x, GEN y)
3583: {
3584: long tx=typ(x);
3585:
3586: switch(typ(y))
3587: {
3588: case t_POL:
3589: if (tx==t_POL) return polinvmod(x,y);
3590: if (is_scalar_t(tx)) return ginv(x);
3591: break;
3592: case t_INT:
3593: if (tx==t_INT) return mpinvmod(x,y);
3594: if (tx==t_POL) return gzero;
3595: }
3596: err(typeer,"ginvmod");
3597: return NULL; /* not reached */
3598: }
3599:
3600: /***********************************************************************/
3601: /** **/
3602: /** NEWTON POLYGON **/
3603: /** **/
3604: /***********************************************************************/
3605:
3606: /* assume leading coeff of x is non-zero */
3607: GEN
3608: newtonpoly(GEN x, GEN p)
3609: {
3610: GEN y;
3611: long n,ind,a,b,c,u1,u2,r1,r2;
3612: long *vval, num[] = {evaltyp(t_INT) | m_evallg(3), 0, 0};
3613:
3614: if (typ(x)!=t_POL) err(typeer,"newtonpoly");
3615: n=degpol(x); if (n<=0) { y=cgetg(1,t_VEC); return y; }
3616: y = cgetg(n+1,t_VEC); x += 2; /* now x[i] = term of degree i */
3617: vval = (long *) gpmalloc(sizeof(long)*(n+1));
3618: for (a=0; a<=n; a++) vval[a] = ggval((GEN)x[a],p);
3619: for (a=0, ind=1; a<n; a++)
3620: {
3621: if (vval[a] != VERYBIGINT) break;
3622: y[ind++] = lstoi(VERYBIGINT);
3623: }
3624: for (b=a+1; b<=n; a=b, b=a+1)
3625: {
3626: while (vval[b] == VERYBIGINT) b++;
3627: u1=vval[a]-vval[b]; u2=b-a;
3628: for (c=b+1; c<=n; c++)
3629: {
3630: if (vval[c] == VERYBIGINT) continue;
3631: r1=vval[a]-vval[c]; r2=c-a;
3632: if (u1*r2<=u2*r1) { u1=r1; u2=r2; b=c; }
3633: }
3634: while (ind<=b) { affsi(u1,num); y[ind++] = ldivgs(num,u2); }
3635: }
3636: free(vval); return y;
3637: }
3638:
3639: extern int cmp_pol(GEN x, GEN y);
3640: extern GEN ZY_ZXY_resultant(GEN A, GEN B0, long *lambda);
3641: GEN matratlift(GEN M, GEN mod, GEN amax, GEN bmax, GEN denom);
3642: GEN nfgcd(GEN P, GEN Q, GEN nf, GEN den);
3643:
3644: /* Factor polynomial a on the number field defined by polynomial t */
3645: GEN
3646: polfnf(GEN a, GEN t)
3647: {
3648: ulong av = avma;
3649: GEN x0,y,p1,p2,u,fa,n,unt,dent,alift;
3650: long lx,i,k,e;
3651: int sqfree, tmonic;
3652:
3653: if (typ(a)!=t_POL || typ(t)!=t_POL) err(typeer,"polfnf");
3654: if (gcmp0(a)) return gcopy(a);
3655: a = fix_relative_pol(t,a,0);
3656: alift = lift(a);
3657: p1 = content(alift); if (!gcmp1(p1)) { a = gdiv(a, p1); alift = lift(a); }
3658: p1 = content(t); if (!gcmp1(t)) t = gdiv(t, p1);
3659: tmonic = is_pm1(leading_term(t));
3660:
3661: dent = ZX_disc(t); unt = gmodulsg(1,t);
3662: u = nfgcd(alift,derivpol(alift), t, dent);
3663: sqfree = gcmp1(u);
3664: u = sqfree? alift: lift_intern(gdiv(a, gmul(unt,u)));
3665: k = 0; n = ZY_ZXY_resultant(t, u, &k);
3666: if (DEBUGLEVEL > 4) fprintferr("polfnf: choosing k = %ld\n",k);
3667:
3668: /* n guaranteed to be squarefree */
3669: fa = squff2(n,0); lx = lg(fa);
3670: y = cgetg(3,t_MAT);
3671: p1 = cgetg(lx,t_COL); y[1] = (long)p1;
3672: p2 = cgetg(lx,t_COL); y[2] = (long)p2;
3673: x0 = gadd(polx[varn(a)], gmulsg(-k, gmodulcp(polx[varn(t)], t)));
3674: for (i=lx-1; i>1; i--)
3675: {
3676: GEN b, F = lift_intern(poleval((GEN)fa[i], x0));
3677: if (!tmonic) F = gdiv(F, content(F));
3678: F = nfgcd(u, F, t, dent);
3679: if (typ(F) != t_POL || degpol(F) == 0)
3680: err(talker,"reducible modulus in factornf");
3681: F = gmul(unt, F);
3682: F = gdiv(F, leading_term(F));
3683: u = lift_intern(gdeuc(u, F));
3684: u = gdiv(u, content(u));
3685: if (sqfree) e = 1;
3686: else
3687: {
3688: e = 0; while (poldivis(a,F, &b)) { a = b; e++; }
3689: if (degpol(a) == degpol(u)) sqfree = 1;
3690: }
3691: p1[i] = (long)F;
3692: p2[i] = lstoi(e);
3693: }
3694: u = gmul(unt, u);
3695: u = gdiv(u, leading_term(u));
3696: p1[1] = (long)u;
3697: e = sqfree? 1: degpol(a)/degpol(u);
3698: p2[1] = lstoi(e);
3699: return gerepilecopy(av, sort_factor(y, cmp_pol));
3700: }
3701:
3702: extern GEN FpXQX_safegcd(GEN P, GEN Q, GEN T, GEN p);
3703: extern GEN FpM(GEN z, GEN p);
3704: extern GEN polpol_to_mat(GEN v, long n);
3705: extern GEN mat_to_polpol(GEN x, long v, long w);
3706:
3707: static GEN
3708: to_frac(GEN a, GEN b)
3709: {
3710: GEN f = cgetg(3, t_FRAC);
3711: f[1] = (long)a;
3712: f[2] = (long)b; return f;
3713: }
3714:
3715: static GEN
3716: lift_to_frac(GEN t, GEN mod, GEN amax, GEN bmax, GEN denom)
3717: {
3718: GEN a, b;
3719: if (signe(t) < 0) t = addii(t, mod); /* in case t is a centerlift */
3720: if (!ratlift(t, mod, &a, &b, amax, bmax)
3721: || (denom && !divise(denom,b))
3722: || !gcmp1(mppgcd(a,b))) return NULL;
3723: if (!is_pm1(b)) a = to_frac(a, b);
3724: return a;
3725: }
3726:
3727: /* compute rational lifting for all the components of M modulo mod.
3728: * If one components fails, return NULL.
3729: * See ratlift.
3730: * If denom is not NULL, check that the denominators divide denom
3731: *
3732: * FIXME: NOT stack clean ! a & b stay on the stack.
3733: * If we suppose mod and denom coprime, then a and b are coprime
3734: * so we can do a cgetg(t_FRAC).
3735: */
3736: GEN
3737: matratlift(GEN M, GEN mod, GEN amax, GEN bmax, GEN denom)
3738: {
3739: ulong ltop = avma;
3740: GEN N, a;
3741: long l2, l3;
3742: long i, j;
3743: if (typ(M)!=t_MAT) err(typeer,"matratlift");
3744: l2 = lg(M); l3 = lg((GEN)M[1]);
3745: N = cgetg(l2, t_MAT);
3746: for (j = 1; j < l2; ++j)
3747: {
3748: N[j] = lgetg(l3, t_COL);
3749: for (i = 1; i < l3; ++i)
3750: {
3751: a = lift_to_frac(gcoeff(M,i,j), mod, amax,bmax,denom);
3752: if (!a) { avma = ltop; return NULL; }
3753: coeff(N, i, j) = (long)a;
3754: }
3755: }
3756: return N;
3757: }
3758:
3759: GEN
3760: polratlift(GEN P, GEN mod, GEN amax, GEN bmax, GEN denom)
3761: {
3762: ulong ltop = avma;
3763: GEN Q,a;
3764: long l2, j;
3765: if (typ(P)!=t_POL) err(typeer,"polratlift");
3766: l2 = lg(P);
3767: Q = cgetg(l2, t_POL); Q[1] = P[1];
3768: for (j = 2; j < l2; ++j)
3769: {
3770: a = lift_to_frac((GEN)P[j], mod, amax,bmax,denom);
3771: if (!a) { avma = ltop; return NULL; }
3772: Q[j] = (long)a;
3773: }
3774: return Q;
3775: }
3776:
3777: /* P,Q in Z[X,Y], nf in Z[Y] irreducible. compute GCD in Q[Y]/(nf)[X].
3778: *
3779: * We essentially follow M. Encarnacion "On a modular Algorithm for computing
3780: * GCDs of polynomials over number fields" (ISSAC'94).
3781: *
3782: * We procede as follows
3783: * 1:compute the gcd modulo primes discarding bad primes as they are detected.
3784: * 2:reconstruct the result via matratlift, stoping as soon as we get weird
3785: * denominators.
3786: * 3:if matratlift succeeds, try the full division.
3787: * Suppose we does not have sufficient accuracy to get the result right:
3788: * it is extremly rare that matratlift will succeed, and even if it does, the
3789: * polynomial we get has sensible coefficients, so the full division will
3790: * not be too costly.
3791: *
3792: * FIXME: Handle rational coefficient for P and Q.
3793: * If not NULL, den must a a multiple of the denominator of the gcd,
3794: * for example the discriminant of nf.
3795: *
3796: * NOTE: if nf is not irreducible, nfgcd may loop forever, especially if the
3797: * gcd divides nf !
3798: */
3799: GEN
3800: nfgcd(GEN P, GEN Q, GEN nf, GEN den)
3801: {
3802: ulong ltop = avma;
3803: GEN sol, mod = NULL;
3804: long x = varn(P);
3805: long y = varn(nf);
3806: long d = degpol(nf);
3807: GEN lP, lQ;
3808: if (!signe(P) || !signe(Q))
3809: return zeropol(x);
3810: /*Compute denominators*/
3811: if (!den) den = ZX_disc(nf);
3812: lP = leading_term(P);
3813: lQ = leading_term(Q);
3814: if ( !((typ(lP)==t_INT && is_pm1(lP)) || (typ(lQ)==t_INT && is_pm1(lQ))) )
3815: den = mulii(den, mppgcd(ZX_resultant(lP, nf), ZX_resultant(lQ, nf)));
3816: /*Modular GCD*/
3817: {
3818: ulong btop = avma;
3819: ulong st_lim = stack_lim(btop, 1);
3820: long p;
3821: long dM=0, dR;
3822: GEN M, dsol, dens;
3823: GEN R, ax, bo;
3824: byteptr primepointer;
3825: for (p = 27449, primepointer = diffptr + 3000; ; p += *(primepointer++))
3826: {
3827: if (!*primepointer) err(primer1);
3828: if (!smodis(den, p))
3829: continue;/*Discard primes dividing the disc(T) or leadingcoeff(PQ) */
3830: if (DEBUGLEVEL>=5) fprintferr("nfgcd: p=%d\n",p);
3831: if ((R = FpXQX_safegcd(P, Q, nf, stoi(p))) == NULL)
3832: continue;/*Discard primes when modular gcd does not exist*/
3833: dR = degpol(R);
3834: if (dR == 0) return scalarpol(gun, x);
3835: if (mod && dR > dM) continue; /* p divides Res(P/gcd, Q/gcd). Discard. */
3836:
3837: R = polpol_to_mat(R, d);
3838: /* previous primes divided Res(P/gcd, Q/gcd)? Discard them. */
3839: if (!mod || dR < dM) { M = R; mod = stoi(p); dM = dR; continue; }
3840: if (low_stack(st_lim, stack_lim(btop, 1)))
3841: {
3842: GEN *bptr[2]; bptr[0]=&M; bptr[1]=&mod;
3843: if (DEBUGMEM>1) err(warnmem,"nfgcd");
3844: gerepilemany(btop, bptr, 2);
3845: }
3846:
3847: ax = gmulgs(mpinvmod(stoi(p), mod), p);
3848: M = gadd(R, gmul(ax, gsub(M, R)));
3849: mod = mulis(mod, p);
3850: M = lift(FpM(M, mod));
3851: /* I suspect it must be better to take amax > bmax*/
3852: bo = racine(shifti(mod, -1));
3853: if ((sol = matratlift(M, mod, bo, bo, den)) == NULL)
3854: continue;
3855: dens = denom(sol);
3856: sol = mat_to_polpol(sol,x,y);
3857: dsol = gmul(sol, gmodulcp(dens, nf));
3858: if (gdivise(P, dsol) && gdivise(Q, dsol))
3859: break;
3860: }
3861: }
3862: return gerepilecopy(ltop, sol);
3863: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>