[BACK]Return to polarit2.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / src / basemath

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, &lt);
                   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>