[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.2

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>