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

Annotation of OpenXM_contrib/pari-2.2/src/basemath/polarit1.c, Revision 1.1.1.1

1.1       noro        1: /* $Id: polarit1.c,v 1.66 2001/10/01 17:19:06 bill Exp $
                      2:
                      3: Copyright (C) 2000  The PARI group.
                      4:
                      5: This file is part of the PARI/GP package.
                      6:
                      7: PARI/GP is free software; you can redistribute it and/or modify it under the
                      8: terms of the GNU General Public License as published by the Free Software
                      9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     10: ANY WARRANTY WHATSOEVER.
                     11:
                     12: Check the License for details. You should have received a copy of it, along
                     13: with the package; see the file 'COPYING'. If not, write to the Free Software
                     14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
                     15:
                     16: /***********************************************************************/
                     17: /**                                                                   **/
                     18: /**               ARITHMETIC OPERATIONS ON POLYNOMIALS                **/
                     19: /**                         (first part)                              **/
                     20: /**                                                                   **/
                     21: /***********************************************************************/
                     22: #include "pari.h"
                     23: extern GEN get_bas_den(GEN bas);
                     24: extern GEN get_mul_table(GEN x,GEN bas,GEN invbas,GEN *T);
                     25: extern GEN pol_to_monic(GEN pol, GEN *lead);
                     26:
                     27: /* see splitgen() for how to use these two */
                     28: GEN
                     29: setloop(GEN a)
                     30: {
                     31:   a=icopy(a); new_chunk(2); /* dummy to get two cells of extra space */
                     32:   return a;
                     33: }
                     34:
                     35: /* assume a > 0 */
                     36: GEN
                     37: incpos(GEN a)
                     38: {
                     39:   long i,l=lgefint(a);
                     40:
                     41:   for (i=l-1; i>1; i--)
                     42:     if (++a[i]) return a;
                     43:   i=l+1; a--; /* use extra cell */
                     44:   a[0]=evaltyp(1) | evallg(i);
                     45:   a[1]=evalsigne(1) | evallgefint(i);
                     46:   return a;
                     47: }
                     48:
                     49: GEN
                     50: incloop(GEN a)
                     51: {
                     52:   long i,l;
                     53:
                     54:   switch(signe(a))
                     55:   {
                     56:     case 0:
                     57:       a--; /* use extra cell */
                     58:       a[0]=evaltyp(t_INT) | evallg(3);
                     59:       a[1]=evalsigne(1) | evallgefint(3);
                     60:       a[2]=1; return a;
                     61:
                     62:     case -1:
                     63:       l=lgefint(a);
                     64:       for (i=l-1; i>1; i--)
                     65:         if (a[i]--) break;
                     66:       if (a[2] == 0)
                     67:       {
                     68:         a++; /* save one cell */
                     69:         a[0] = evaltyp(t_INT) | evallg(2);
                     70:         a[1] = evalsigne(0) | evallgefint(2);
                     71:       }
                     72:       return a;
                     73:
                     74:     default:
                     75:       return incpos(a);
                     76:   }
                     77: }
                     78:
                     79: /*******************************************************************/
                     80: /*                                                                 */
                     81: /*                           DIVISIBILITE                          */
                     82: /*                 Return 1 if y  |  x,  0 otherwise               */
                     83: /*                                                                 */
                     84: /*******************************************************************/
                     85:
                     86: int
                     87: gdivise(GEN x, GEN y)
                     88: {
                     89:   long av=avma;
                     90:   x=gmod(x,y); avma=av; return gcmp0(x);
                     91: }
                     92:
                     93: int
                     94: poldivis(GEN x, GEN y, GEN *z)
                     95: {
                     96:   long av = avma;
                     97:   GEN p1 = poldivres(x,y,ONLY_DIVIDES);
                     98:   if (p1) { *z = p1; return 1; }
                     99:   avma=av; return 0;
                    100: }
                    101:
                    102: /*******************************************************************/
                    103: /*                                                                 */
                    104: /*                  POLYNOMIAL EUCLIDEAN DIVISION                  */
                    105: /*                                                                 */
                    106: /*******************************************************************/
                    107: /* Polynomial division x / y:
                    108:  *   if z = ONLY_REM  return remainder, otherwise return quotient
                    109:  *   if z != NULL set *z to remainder
                    110:  *   *z is the last object on stack (and thus can be disposed of with cgiv
                    111:  *   instead of gerepile)
                    112:  */
                    113: GEN
                    114: poldivres(GEN x, GEN y, GEN *pr)
                    115: {
                    116:   ulong avy,av,av1;
                    117:   long ty=typ(y),tx,vx,vy,dx,dy,dz,i,j,sx,lrem;
                    118:   int remainder;
                    119:   GEN z,p1,rem,y_lead,mod;
                    120:   GEN (*f)(GEN,GEN);
                    121:
                    122:   if (pr == ONLY_DIVIDES_EXACT)
                    123:     { f = gdivexact; pr = ONLY_DIVIDES; }
                    124:   else
                    125:     f = gdiv;
                    126:   if (is_scalar_t(ty))
                    127:   {
                    128:     if (pr == ONLY_REM) return gzero;
                    129:     if (pr && pr != ONLY_DIVIDES) *pr=gzero;
                    130:     return f(x,y);
                    131:   }
                    132:   tx=typ(x); vy=gvar9(y);
                    133:   if (is_scalar_t(tx) || gvar9(x)>vy)
                    134:   {
                    135:     if (pr == ONLY_REM) return gcopy(x);
                    136:     if (pr == ONLY_DIVIDES) return gcmp0(x)? gzero: NULL;
                    137:     if (pr) *pr=gcopy(x);
                    138:     return gzero;
                    139:   }
                    140:   if (tx!=t_POL || ty!=t_POL) err(typeer,"euclidean division (poldivres)");
                    141:
                    142:   vx=varn(x);
                    143:   if (vx<vy)
                    144:   {
                    145:     if (pr && pr != ONLY_DIVIDES)
                    146:     {
                    147:       p1 = zeropol(vx); if (pr == ONLY_REM) return p1;
                    148:       *pr = p1;
                    149:     }
                    150:     return f(x,y);
                    151:   }
                    152:   if (!signe(y)) err(talker,"euclidean division by zero (poldivres)");
                    153:
                    154:   dy=degpol(y); y_lead = (GEN)y[dy+2];
                    155:   if (gcmp0(y_lead)) /* normalize denominator if leading term is 0 */
                    156:   {
                    157:     err(warner,"normalizing a polynomial with 0 leading term");
                    158:     for (dy--; dy>=0; dy--)
                    159:     {
                    160:       y_lead = (GEN)y[dy+2];
                    161:       if (!gcmp0(y_lead)) break;
                    162:     }
                    163:   }
                    164:   if (!dy) /* y is constant */
                    165:   {
                    166:     if (pr && pr != ONLY_DIVIDES)
                    167:     {
                    168:       if (pr == ONLY_REM) return zeropol(vx);
                    169:       *pr = zeropol(vx);
                    170:     }
                    171:     return f(x, constant_term(y));
                    172:   }
                    173:   dx=degpol(x);
                    174:   if (vx>vy || dx<dy)
                    175:   {
                    176:     if (pr)
                    177:     {
                    178:       if (pr == ONLY_DIVIDES) return gcmp0(x)? gzero: NULL;
                    179:       if (pr == ONLY_REM) return gcopy(x);
                    180:       *pr = gcopy(x);
                    181:     }
                    182:     return zeropol(vy);
                    183:   }
                    184:   dz=dx-dy; av=avma; /* to avoid gsub's later on */
                    185:   p1 = new_chunk(dy+3);
                    186:   for (i=2; i<dy+3; i++)
                    187:   {
                    188:     GEN p2 = (GEN)y[i];
                    189:     p1[i] = isexactzero(p2)? 0: (long)gneg_i(p2);
                    190:   }
                    191:   y = p1;
                    192:   switch(typ(y_lead))
                    193:   {
                    194:     case t_INTMOD:
                    195:     case t_POLMOD: y_lead = ginv(y_lead);
                    196:       f = gmul; mod = gmodulcp(gun, (GEN)y_lead[1]);
                    197:       break;
                    198:     default: if (gcmp1(y_lead)) y_lead = NULL;
                    199:       mod = NULL;
                    200:   }
                    201:   avy=avma; z=cgetg(dz+3,t_POL);
                    202:   z[1]=evalsigne(1) | evallgef(dz+3) | evalvarn(vx);
                    203:   x += 2; y += 2; z += 2;
                    204:
                    205:   p1 = (GEN)x[dx]; remainder = (pr == ONLY_REM);
                    206:   z[dz]=y_lead? (long)f(p1,y_lead): lcopy(p1);
                    207:   for (i=dx-1; i>=dy; i--)
                    208:   {
                    209:     av1=avma; p1=(GEN)x[i];
                    210:     for (j=i-dy+1; j<=i && j<=dz; j++)
                    211:       if (y[i-j]) p1 = gadd(p1, gmul((GEN)z[j],(GEN)y[i-j]));
                    212:     if (y_lead) p1 = f(p1,y_lead);
                    213:     if (!remainder) p1 = avma==av1? gcopy(p1): gerepileupto(av1,p1);
                    214:     z[i-dy] = (long)p1;
                    215:   }
                    216:   if (!pr) return gerepileupto(av,z-2);
                    217:
                    218:   rem = (GEN)avma; av1 = (long)new_chunk(dx+3);
                    219:   for (sx=0; ; i--)
                    220:   {
                    221:     p1 = (GEN)x[i];
                    222:     /* we always enter this loop at least once */
                    223:     for (j=0; j<=i && j<=dz; j++)
                    224:       if (y[i-j]) p1 = gadd(p1, gmul((GEN)z[j],(GEN)y[i-j]));
                    225:     if (mod && avma==av1) p1 = gmul(p1,mod);
                    226:     if (!gcmp0(p1)) { sx = 1; break; } /* remainder is non-zero */
                    227:     if (!isinexactreal(p1) && !isexactzero(p1)) break;
                    228:     if (!i) break;
                    229:     avma=av1;
                    230:   }
                    231:   if (pr == ONLY_DIVIDES)
                    232:   {
                    233:     if (sx) { avma=av; return NULL; }
                    234:     avma = (long)rem;
                    235:     return gerepileupto(av,z-2);
                    236:   }
                    237:   lrem=i+3; rem -= lrem;
                    238:   if (avma==av1) { avma = (long)rem; p1 = gcopy(p1); }
                    239:   else p1 = gerepileupto((long)rem,p1);
                    240:   rem[0]=evaltyp(t_POL) | evallg(lrem);
                    241:   rem[1]=evalsigne(1) | evalvarn(vx) | evallgef(lrem);
                    242:   rem += 2;
                    243:   rem[i]=(long)p1;
                    244:   for (i--; i>=0; i--)
                    245:   {
                    246:     av1=avma; p1 = (GEN)x[i];
                    247:     for (j=0; j<=i && j<=dz; j++)
                    248:       if (y[i-j]) p1 = gadd(p1, gmul((GEN)z[j],(GEN)y[i-j]));
                    249:     if (mod && avma==av1) p1 = gmul(p1,mod);
                    250:     rem[i]=avma==av1? lcopy(p1):lpileupto(av1,p1);
                    251:   }
                    252:   rem -= 2;
                    253:   if (!sx) normalizepol_i(rem, lrem);
                    254:   if (remainder) return gerepileupto(av,rem);
                    255:   z -= 2;
                    256:   {
                    257:     GEN *gptr[2]; gptr[0]=&z; gptr[1]=&rem;
                    258:     gerepilemanysp(av,avy,gptr,2); *pr = rem; return z;
                    259:   }
                    260: }
                    261:
                    262: /*******************************************************************/
                    263: /*                                                                 */
                    264: /*           ROOTS MODULO a prime p (no multiplicities)            */
                    265: /*                                                                 */
                    266: /*******************************************************************/
                    267: static GEN
                    268: mod(GEN x, GEN y)
                    269: {
                    270:   GEN z = cgetg(3,t_INTMOD);
                    271:   z[1]=(long)y; z[2]=(long)x; return z;
                    272: }
                    273:
                    274: static long
                    275: factmod_init(GEN *F, GEN pp, long *p)
                    276: {
                    277:   GEN f = *F;
                    278:   long i,d;
                    279:   if (typ(f)!=t_POL || typ(pp)!=t_INT) err(typeer,"factmod");
                    280:   if (expi(pp) > BITS_IN_LONG - 3) *p = 0;
                    281:   else
                    282:   {
                    283:     *p = itos(pp);
                    284:     if (*p < 2) err(talker,"not a prime in factmod");
                    285:   }
                    286:   f = gmul(f, mod(gun,pp));
                    287:   if (!signe(f)) err(zeropoler,"factmod");
                    288:   f = lift_intern(f); d = lgef(f);
                    289:   for (i=2; i <d; i++)
                    290:     if (typ(f[i])!=t_INT) err(impl,"factormod for general polynomials");
                    291:   *F = f; return d-3;
                    292: }
                    293:
                    294: #define mods(x,y) mod(stoi(x),y)
                    295: static GEN
                    296: root_mod_2(GEN f)
                    297: {
                    298:   int z1, z0 = !signe(constant_term(f));
                    299:   long i,n;
                    300:   GEN y;
                    301:
                    302:   for (i=2, n=1; i < lgef(f); i++)
                    303:     if (signe(f[i])) n++;
                    304:   z1 = n & 1;
                    305:   y = cgetg(z0+z1+1, t_COL); i = 1;
                    306:   if (z0) y[i++] = (long)mods(0,gdeux);
                    307:   if (z1) y[i]   = (long)mods(1,gdeux);
                    308:   return y;
                    309: }
                    310:
                    311: #define i_mod4(x) (signe(x)? mod4((GEN)(x)): 0)
                    312: static GEN
                    313: root_mod_4(GEN f)
                    314: {
                    315:   long no,ne;
                    316:   int z0 = !signe(constant_term(f));
                    317:   int z2 = ((i_mod4(constant_term(f)) + 2*i_mod4(f[3])) & 3) == 0;
                    318:   int i,z1,z3;
                    319:   GEN y,p;
                    320:
                    321:   for (ne=0,i=2; i<lgef(f); i+=2)
                    322:     if (signe(f[i])) ne += mael(f,i,2);
                    323:   for (no=0,i=3; i<lgef(f); i+=2)
                    324:     if (signe(f[i])) no += mael(f,i,2);
                    325:   no &= 3; ne &= 3;
                    326:   z3 = (no == ne);
                    327:   z1 = (no == ((4-ne)&3));
                    328:   y=cgetg(1+z0+z1+z2+z3,t_COL); i = 1; p = stoi(4);
                    329:   if (z0) y[i++] = (long)mods(0,p);
                    330:   if (z1) y[i++] = (long)mods(1,p);
                    331:   if (z2) y[i++] = (long)mods(2,p);
                    332:   if (z3) y[i]   = (long)mods(3,p);
                    333:   return y;
                    334: }
                    335: #undef i_mod4
                    336:
                    337: /* p even, accept p = 4 for p-adic stuff */
                    338: static GEN
                    339: root_mod_even(GEN f, long p)
                    340: {
                    341:   switch(p)
                    342:   {
                    343:     case 2: return root_mod_2(f);
                    344:     case 4: return root_mod_4(f);
                    345:   }
                    346:   err(talker,"not a prime in rootmod");
                    347:   return NULL; /* not reached */
                    348: }
                    349:
                    350: /* by checking f(0..p-1) */
                    351: GEN
                    352: rootmod2(GEN f, GEN pp)
                    353: {
                    354:   GEN g,y,ss,q,r, x_minus_s;
                    355:   long p,av = avma,av1,d,i,nbrac;
                    356:
                    357:   if (!(d = factmod_init(&f, pp, &p))) { avma=av; return cgetg(1,t_COL); }
                    358:   if (!p) err(talker,"prime too big in rootmod2");
                    359:   if ((p & 1) == 0) { avma = av; return root_mod_even(f,p); }
                    360:   x_minus_s = gadd(polx[varn(f)], stoi(-1));
                    361:
                    362:   nbrac=1;
                    363:   y=(GEN)gpmalloc((d+1)*sizeof(long));
                    364:   if (gcmp0(constant_term(f))) y[nbrac++] = 0;
                    365:   ss = icopy(gun); av1 = avma;
                    366:   do
                    367:   {
                    368:     mael(x_minus_s,2,2) = ss[2];
                    369:     /* one might do a FFT-type evaluation */
                    370:     q = FpX_divres(f, x_minus_s, pp, &r);
                    371:     if (signe(r)) avma = av1;
                    372:     else
                    373:     {
                    374:       y[nbrac++] = ss[2]; f = q; av1 = avma;
                    375:     }
                    376:     ss[2]++;
                    377:   }
                    378:   while (nbrac<d && p>ss[2]);
                    379:   if (nbrac == 1) { avma=av; return cgetg(1,t_COL); }
                    380:   if (nbrac == d && p != ss[2])
                    381:   {
                    382:     g = mpinvmod((GEN)f[3], pp); setsigne(g,-1);
                    383:     ss = modis(mulii(g, (GEN)f[2]), p);
                    384:     y[nbrac++]=ss[2];
                    385:   }
                    386:   avma=av; g=cgetg(nbrac,t_COL);
                    387:   if (isonstack(pp)) pp = icopy(pp);
                    388:   for (i=1; i<nbrac; i++) g[i]=(long)mods(y[i],pp);
                    389:   free(y); return g;
                    390: }
                    391:
                    392: /* by splitting */
                    393: GEN
                    394: rootmod(GEN f, GEN p)
                    395: {
                    396:   long av = avma,tetpil,n,i,j,la,lb;
                    397:   GEN y,pol,a,b,q,pol0;
                    398:
                    399:   if (!factmod_init(&f, p, &i)) { avma=av; return cgetg(1,t_COL); }
                    400:   i = p[lgefint(p)-1];
                    401:   if ((i & 1) == 0) { avma = av; return root_mod_even(f,i); }
                    402:   i=2; while (!signe(f[i])) i++;
                    403:   if (i == 2) j = 1;
                    404:   else
                    405:   {
                    406:     j = lgef(f) - (i-2);
                    407:     if (j==3) /* f = x^n */
                    408:     {
                    409:       avma = av; y = cgetg(2,t_COL);
                    410:       y[1] = (long)gmodulsg(0,p);
                    411:       return y;
                    412:     }
                    413:     a = cgetg(j, t_POL); /* a = f / x^{v_x(f)} */
                    414:     a[1] =  evalsigne(1) | evalvarn(varn(f)) | evallgef(j);
                    415:     f += i-2; for (i=2; i<j; i++) a[i]=f[i];
                    416:     j = 2; f = a;
                    417:   }
                    418:   q = shifti(p,-1);
                    419:   /* take gcd(x^(p-1) - 1, f) by splitting (x^q-1) * (x^q+1) */
                    420:   b = FpXQ_pow(polx[varn(f)],q, f,p);
                    421:   if (lgef(b)<3) err(talker,"not a prime in rootmod");
                    422:   b = ZX_s_add(b,-1); /* b = x^((p-1)/2) - 1 mod f */
                    423:   a = FpX_gcd(f,b, p);
                    424:   b = ZX_s_add(b, 2); /* b = x^((p-1)/2) + 1 mod f */
                    425:   b = FpX_gcd(f,b, p);
                    426:   la = degpol(a);
                    427:   lb = degpol(b); n = la + lb;
                    428:   if (!n)
                    429:   {
                    430:     avma = av; y = cgetg(n+j,t_COL);
                    431:     if (j>1) y[1] = (long)gmodulsg(0,p);
                    432:     return y;
                    433:   }
                    434:   y = cgetg(n+j,t_COL);
                    435:   if (j>1) { y[1] = zero; n++; }
                    436:   y[j] = (long)FpX_normalize(b,p);
                    437:   if (la) y[j+lb] = (long)FpX_normalize(a,p);
                    438:   pol = gadd(polx[varn(f)], gun); pol0 = constant_term(pol);
                    439:   while (j<=n)
                    440:   {
                    441:     a=(GEN)y[j]; la=degpol(a);
                    442:     if (la==1)
                    443:       y[j++] = lsubii(p, constant_term(a));
                    444:     else if (la==2)
                    445:     {
                    446:       GEN d = subii(sqri((GEN)a[3]), shifti((GEN)a[2],2));
                    447:       GEN e = mpsqrtmod(d,p), u = addis(q, 1); /* u = 1/2 */
                    448:       y[j++] = lmodii(mulii(u,subii(e,(GEN)a[3])), p);
                    449:       y[j++] = lmodii(mulii(u,negi(addii(e,(GEN)a[3]))), p);
                    450:     }
                    451:     else for (pol0[2]=1; ; pol0[2]++)
                    452:     {
                    453:       b = ZX_s_add(FpXQ_pow(pol,q, a,p), -1); /* pol^(p-1)/2 - 1 */
                    454:       b = FpX_gcd(a,b, p); lb = degpol(b);
                    455:       if (lb && lb<la)
                    456:       {
                    457:         b = FpX_normalize(b, p);
                    458:         y[j+lb] = (long)FpX_div(a,b, p);
                    459:         y[j]    = (long)b; break;
                    460:       }
                    461:     }
                    462:   }
                    463:   tetpil = avma; y = gerepile(av,tetpil,sort(y));
                    464:   if (isonstack(p)) p = icopy(p);
                    465:   for (i=1; i<=n; i++) y[i] = (long)mod((GEN)y[i], p);
                    466:   return y;
                    467: }
                    468:
                    469: GEN
                    470: rootmod0(GEN f, GEN p, long flag)
                    471: {
                    472:   switch(flag)
                    473:   {
                    474:     case 0: return rootmod(f,p);
                    475:     case 1: return rootmod2(f,p);
                    476:     default: err(flagerr,"polrootsmod");
                    477:   }
                    478:   return NULL; /* not reached */
                    479: }
                    480:
                    481: /*******************************************************************/
                    482: /*                                                                 */
                    483: /*                     FACTORISATION MODULO p                      */
                    484: /*                                                                 */
                    485: /*******************************************************************/
                    486: static GEN spec_FpXQ_pow(GEN x, GEN p, GEN S);
                    487: /* Functions giving information on the factorisation. */
                    488:
                    489: /* u in Z[X], return kernel of (Frob - Id) over Fp[X] / u */
                    490: static GEN
                    491: Berlekamp_ker(GEN u, GEN p)
                    492: {
                    493:   long i,j,d,N = degpol(u);
                    494:   GEN vker,v,w,Q,p1,p2;
                    495:   if (DEBUGLEVEL > 7) timer2();
                    496:   Q = cgetg(N+1,t_MAT); Q[1] = (long)zerocol(N);
                    497:   w = v = FpXQ_pow(polx[varn(u)],p,u,p);
                    498:   for (j=2; j<=N; j++)
                    499:   {
                    500:     Q[j] = lgetg(N+1,t_COL); p1 = (GEN)Q[j];
                    501:     d = lgef(w)-1; p2 = w+1;
                    502:     for (i=1; i<d ; i++) p1[i] = p2[i];
                    503:     for (   ; i<=N; i++) p1[i] = zero;
                    504:     p1[j] = laddis((GEN)p1[j], -1);
                    505:     if (j < N)
                    506:     {
                    507:       ulong av = avma;
                    508:       w = gerepileupto(av, FpX_res(gmul(w,v), u, p));
                    509:     }
                    510:   }
                    511:   if (DEBUGLEVEL > 7) msgtimer("frobenius");
                    512:   vker = FpM_ker(Q,p);
                    513:   if (DEBUGLEVEL > 7) msgtimer("kernel");
                    514:   return vker;
                    515: }
                    516:
                    517: /* f in ZZ[X] and p a prime number. */
                    518: long
                    519: FpX_is_squarefree(GEN f, GEN p)
                    520: {
                    521:   long av = avma;
                    522:   GEN z;
                    523:   z = FpX_gcd(f,derivpol(f),p);
                    524:   avma = av;
                    525:   return lgef(z)==3;
                    526: }
                    527: /* idem
                    528:  * leading term of f must be prime to p.
                    529:  */
                    530: /* Compute the number of roots in Fp without counting multiplicity
                    531:  * return -1 for 0 polynomial.
                    532:  */
                    533: long
                    534: FpX_nbroots(GEN f, GEN p)
                    535: {
                    536:   long av = avma, n=lgef(f);
                    537:   GEN z;
                    538:   if (n <= 4) return n-3;
                    539:   f = FpX_red(f, p);
                    540:   z = FpXQ_pow(polx[varn(f)], p, f, p);
                    541:   z = FpX_sub(z,polx[varn(f)],NULL);
                    542:   z = FpX_gcd(z,f,p),
                    543:   avma = av; return degpol(z);
                    544: }
                    545: long
                    546: FpX_is_totally_split(GEN f, GEN p)
                    547: {
                    548:   long av = avma, n=lgef(f);
                    549:   GEN z;
                    550:   if (n <= 4) return 1;
                    551:   if (!is_bigint(p) && n-3 > p[2]) return 0;
                    552:   f = FpX_red(f, p);
                    553:   z = FpXQ_pow(polx[varn(f)], p, f, p);
                    554:   avma = av; return lgef(z)==4 && gcmp1((GEN)z[3]) && !signe(z[2]);
                    555: }
                    556: /* u in ZZ[X] and p a prime number.
                    557:  * u must be squarefree mod p.
                    558:  * leading term of u must be prime to p. */
                    559: long
                    560: FpX_nbfact(GEN u, GEN p)
                    561: {
                    562:   ulong av = avma;
                    563:   GEN vker = Berlekamp_ker(u,p);
                    564:   avma = av; return lg(vker)-1;
                    565: }
                    566:
                    567: /* Please use only use this function when you it is false, or that there is a
                    568:  * lot of factors. If you believe f is irreducible or that it has few factors,
                    569:  * then use `FpX_nbfact(f,p)==1' instead (faster).
                    570:  */
                    571: static GEN factcantor0(GEN f, GEN pp, long flag);
                    572: long FpX_is_irred(GEN f, GEN p) { return !!factcantor0(f,p,2); }
                    573:
                    574: static GEN modulo;
                    575: static GEN gsmul(GEN a,GEN b){return FpX_mul(a,b,modulo);}
                    576: GEN
                    577: FpV_roots_to_pol(GEN V, GEN p, long v)
                    578: {
                    579:   ulong ltop=avma;
                    580:   long i;
                    581:   GEN g=cgetg(lg(V),t_VEC);
                    582:   for(i=1;i<lg(V);i++)
                    583:     g[i]=(long)deg1pol(gun,negi((GEN)V[i]),v);
                    584:   modulo=p;
                    585:   g=divide_conquer_prod(g,&gsmul);
                    586:   return gerepileupto(ltop,g);
                    587: }
                    588:
                    589: /************************************************************/
                    590: GEN
                    591: trivfact(void)
                    592: {
                    593:   GEN y=cgetg(3,t_MAT);
                    594:   y[1]=lgetg(1,t_COL);
                    595:   y[2]=lgetg(1,t_COL); return y;
                    596: }
                    597:
                    598: static void
                    599: fqunclone(GEN x, GEN a, GEN p)
                    600: {
                    601:   long i,j,lx = lgef(x);
                    602:   for (i=2; i<lx; i++)
                    603:   {
                    604:     GEN p1 = (GEN)x[i];
                    605:     if (typ(p1) == t_POLMOD) { p1[1] = (long)a; p1 = (GEN)p1[2]; }
                    606:     if (typ(p1) == t_INTMOD) p1[1] = (long)p;
                    607:     else /* t_POL */
                    608:       for (j = lgef(p1)-1; j > 1; j--)
                    609:       {
                    610:         GEN p2 = (GEN)p1[j];
                    611:         if (typ(p2) == t_INTMOD) p2[1] = (long)p;
                    612:       }
                    613:   }
                    614: }
                    615:
                    616: static GEN
                    617: try_pow(GEN w0, GEN pol, GEN p, GEN q, long r)
                    618: {
                    619:   GEN w2, w = FpXQ_pow(w0,q, pol,p);
                    620:   long s;
                    621:   if (gcmp1(w)) return w0;
                    622:   for (s=1; s<r; s++,w=w2)
                    623:   {
                    624:     w2 = gsqr(w);
                    625:     w2 = FpX_res(w2, pol, p);
                    626:     if (gcmp1(w2)) break;
                    627:   }
                    628:   return gcmp_1(w)? NULL: w;
                    629: }
                    630:
                    631: /* INPUT:
                    632:  *  m integer (converted to polynomial w in Z[X] by stopoly)
                    633:  *  p prime; q = (p^d-1) / 2^r
                    634:  *  t[0] polynomial of degree k*d product of k irreducible factors of degree d
                    635:  *  t[0] is expected to be normalized (leading coeff = 1)
                    636:  * OUTPUT:
                    637:  *  t[0],t[1]...t[k-1] the k factors, normalized
                    638:  */
                    639: static void
                    640: split(long m, GEN *t, long d, GEN p, GEN q, long r, GEN S)
                    641: {
                    642:   long ps,l,v,dv,av0,av;
                    643:   GEN w,w0;
                    644:
                    645:   dv=degpol(*t); if (dv==d) return;
                    646:   v=varn(*t); av0=avma; ps = p[2];
                    647:   for(av=avma;;avma=av)
                    648:   {
                    649:     if (ps==2)
                    650:     {
                    651:       w0=w=gpuigs(polx[v],m-1); m+=2;
                    652:       for (l=1; l<d; l++)
                    653:         w = gadd(w0, spec_FpXQ_pow(w, p, S));
                    654:     }
                    655:     else
                    656:     {
                    657:       w = FpX_res(stopoly(m,ps,v),*t, p);
                    658:       m++; w = try_pow(w,*t,p,q,r);
                    659:       if (!w) continue;
                    660:       w = ZX_s_add(w, -1);
                    661:     }
                    662:     w = FpX_gcd(*t,w, p);
                    663:     l = degpol(w); if (l && l!=dv) break;
                    664:   }
                    665:   w = FpX_normalize(w, p);
                    666:   w = gerepileupto(av0, w);
                    667:   l /= d; t[l]=FpX_div(*t,w,p); *t=w;
                    668:   split(m,t+l,d,p,q,r,S);
                    669:   split(m,t,  d,p,q,r,S);
                    670: }
                    671:
                    672: static void
                    673: splitgen(GEN m, GEN *t, long d, GEN  p, GEN q, long r)
                    674: {
                    675:   long l,v,dv,av;
                    676:   GEN w;
                    677:
                    678:   dv=degpol(*t); if (dv==d) return;
                    679:   v=varn(*t); m=setloop(m); m=incpos(m);
                    680:   av=avma;
                    681:   for(;; avma=av, m=incpos(m))
                    682:   {
                    683:     w = FpX_res(stopoly_gen(m,p,v),*t, p);
                    684:     w = try_pow(w,*t,p,q,r);
                    685:     if (!w) continue;
                    686:     w = ZX_s_add(w,-1);
                    687:     w = FpX_gcd(*t,w, p); l=degpol(w);
                    688:     if (l && l!=dv) break;
                    689:
                    690:   }
                    691:   w = FpX_normalize(w, p);
                    692:   w = gerepileupto(av, w);
                    693:   l /= d; t[l]=FpX_div(*t,w,p); *t=w;
                    694:   splitgen(m,t+l,d,p,q,r);
                    695:   splitgen(m,t,  d,p,q,r);
                    696: }
                    697:
                    698: /* return S = [ x^p, x^2p, ... x^(n-1)p ] mod (p, T), n = degree(T) > 0 */
                    699: static GEN
                    700: init_pow_p_mod_pT(GEN p, GEN T)
                    701: {
                    702:   long i, n = degpol(T), v = varn(T);
                    703:   GEN p1, S = cgetg(n, t_VEC);
                    704:   if (n == 1) return S;
                    705:   S[1] = (long)FpXQ_pow(polx[v], p, T, p);
                    706:   /* use as many squarings as possible */
                    707:   for (i=2; i < n; i+=2)
                    708:   {
                    709:     p1 = gsqr((GEN)S[i>>1]);
                    710:     S[i]   = (long)FpX_res(p1, T, p);
                    711:     if (i == n-1) break;
                    712:     p1 = gmul((GEN)S[i], (GEN)S[1]);
                    713:     S[i+1] = (long)FpX_res(p1, T, p);
                    714:   }
                    715:   return S;
                    716: }
                    717:
                    718: /* compute x^p, S is as above */
                    719: static GEN
                    720: spec_FpXQ_pow(GEN x, GEN p, GEN S)
                    721: {
                    722:   long av = avma, lim = stack_lim(av,1), i,dx = degpol(x);
                    723:   GEN x0 = x+2, z;
                    724:   z = (GEN)x0[0];
                    725:   if (dx < 0) err(talker, "zero polynomial in FpXQ_pow. %Z not prime", p);
                    726:   for (i = 1; i <= dx; i++)
                    727:   {
                    728:     GEN d, c = (GEN)x0[i]; /* assume coeffs in [0, p-1] */
                    729:     if (!signe(c)) continue;
                    730:     d = (GEN)S[i]; if (!gcmp1(c)) d = gmul(c,d);
                    731:     z = gadd(z, d);
                    732:     if (low_stack(lim, stack_lim(av,1)))
                    733:     {
                    734:       if(DEBUGMEM>1) err(warnmem,"spec_FpXQ_pow");
                    735:       z = gerepileupto(av, z);
                    736:     }
                    737:   }
                    738:   z = FpX_red(z, p);
                    739:   return gerepileupto(av, z);
                    740: }
                    741:
                    742: /* factor f mod pp.
                    743:  * If (flag = 1) return the degrees, not the factors
                    744:  * If (flag = 2) return NULL if f is not irreducible
                    745:  */
                    746: static GEN
                    747: factcantor0(GEN f, GEN pp, long flag)
                    748: {
                    749:   long i,j,k,d,e,vf,p,nbfact,tetpil,av = avma;
                    750:   GEN ex,y,f2,g,g1,u,v,pd,q;
                    751:   GEN *t;
                    752:
                    753:   if (!(d = factmod_init(&f, pp, &p))) { avma=av; return trivfact(); }
                    754:   /* to hold factors and exponents */
                    755:   t = (GEN*)cgetg(d+1,t_VEC); ex = new_chunk(d+1);
                    756:   vf=varn(f); e = nbfact = 1;
                    757:   for(;;)
                    758:   {
                    759:     f2 = FpX_gcd(f,derivpol(f), pp);
                    760:     if (flag > 1 && lgef(f2) > 3) return NULL;
                    761:     g1 = FpX_div(f,f2,pp);
                    762:     k = 0;
                    763:     while (lgef(g1)>3)
                    764:     {
                    765:       long du,dg;
                    766:       GEN S;
                    767:       k++; if (p && !(k%p)) { k++; f2 = FpX_div(f2,g1,pp); }
                    768:       u = g1; g1 = FpX_gcd(f2,g1, pp);
                    769:       if (lgef(g1)>3)
                    770:       {
                    771:         u = FpX_div( u,g1,pp);
                    772:         f2= FpX_div(f2,g1,pp);
                    773:       }
                    774:       du = degpol(u);
                    775:       if (du <= 0) continue;
                    776:
                    777:       /* here u is square-free (product of irred. of multiplicity e * k) */
                    778:       S = init_pow_p_mod_pT(pp, u);
                    779:       pd=gun; v=polx[vf];
                    780:       for (d=1; d <= du>>1; d++)
                    781:       {
                    782:         if (!flag) pd = mulii(pd,pp);
                    783:         v = spec_FpXQ_pow(v, pp, S);
                    784:         g = FpX_gcd(gadd(v, gneg(polx[vf])), u, pp);
                    785:         dg = degpol(g);
                    786:         if (dg <= 0) continue;
                    787:
                    788:         /* Ici g est produit de pol irred ayant tous le meme degre d; */
                    789:         j=nbfact+dg/d;
                    790:
                    791:         if (flag)
                    792:         {
                    793:           if (flag > 1) return NULL;
                    794:           for ( ; nbfact<j; nbfact++) { t[nbfact]=(GEN)d; ex[nbfact]=e*k; }
                    795:         }
                    796:         else
                    797:         {
                    798:           long r;
                    799:           g = FpX_normalize(g, pp);
                    800:           t[nbfact]=g; q = subis(pd,1); /* also ok for p=2: unused */
                    801:           r = vali(q); q = shifti(q,-r);
                    802:          /* le premier parametre est un entier variable m qui sera
                    803:           * converti en un polynome w dont les coeff sont ses digits en
                    804:           * base p (initialement m = p --> X) pour faire pgcd de g avec
                    805:           * w^(p^d-1)/2 jusqu'a casser. p = 2 is treated separately.
                    806:           */
                    807:           if (p)
                    808:             split(p,t+nbfact,d,pp,q,r,S);
                    809:           else
                    810:             splitgen(pp,t+nbfact,d,pp,q,r);
                    811:           for (; nbfact<j; nbfact++) ex[nbfact]=e*k;
                    812:         }
                    813:         du -= dg;
                    814:         u = FpX_div(u,g,pp);
                    815:         v = FpX_res(v,u,pp);
                    816:       }
                    817:       if (du)
                    818:       {
                    819:         t[nbfact] = flag? (GEN)du: FpX_normalize(u, pp);
                    820:         ex[nbfact++]=e*k;
                    821:       }
                    822:     }
                    823:     j = lgef(f2); if (j==3) break;
                    824:
                    825:     e*=p; j=(j-3)/p+3; setlg(f,j); setlgef(f,j);
                    826:     for (i=2; i<j; i++) f[i]=f2[p*(i-2)+2];
                    827:   }
                    828:   if (flag > 1) { avma = av; return gun; } /* irreducible */
                    829:   tetpil=avma; y=cgetg(3,t_MAT);
                    830:   if (!flag)
                    831:   {
                    832:     y[1]=(long)t; setlg(t, nbfact);
                    833:     y[2]=(long)ex; (void)sort_factor(y,cmpii);
                    834:   }
                    835:   u=cgetg(nbfact,t_COL); y[1]=(long)u;
                    836:   v=cgetg(nbfact,t_COL); y[2]=(long)v;
                    837:   if (flag)
                    838:     for (j=1; j<nbfact; j++)
                    839:     {
                    840:       u[j] = lstoi((long)t[j]);
                    841:       v[j] = lstoi(ex[j]);
                    842:     }
                    843:   else
                    844:     for (j=1; j<nbfact; j++)
                    845:     {
                    846:       u[j] = (long)FpX(t[j], pp);
                    847:       v[j] = lstoi(ex[j]);
                    848:     }
                    849:   return gerepile(av,tetpil,y);
                    850: }
                    851:
                    852: GEN
                    853: factcantor(GEN f, GEN p)
                    854: {
                    855:   return factcantor0(f,p,0);
                    856: }
                    857:
                    858: GEN
                    859: simplefactmod(GEN f, GEN p)
                    860: {
                    861:   return factcantor0(f,p,1);
                    862: }
                    863:
                    864: /* vector of polynomials (in v) whose coeffs are given by the columns of x */
                    865: GEN
                    866: mat_to_vecpol(GEN x, long v)
                    867: {
                    868:   long i,j, lx = lg(x), lcol = lg(x[1]);
                    869:   GEN y = cgetg(lx, t_VEC);
                    870:
                    871:   for (j=1; j<lx; j++)
                    872:   {
                    873:     GEN p1, col = (GEN)x[j];
                    874:     long k = lcol;
                    875:
                    876:     while (k-- && gcmp0((GEN)col[k]));
                    877:     i=k+2; p1=cgetg(i,t_POL);
                    878:     p1[1] = evalsigne(1) | evallgef(i) | evalvarn(v);
                    879:     col--; for (k=2; k<i; k++) p1[k] = col[k];
                    880:     y[j] = (long)p1;
                    881:   }
                    882:   return y;
                    883: }
                    884:
                    885: /* matrix whose entries are given by the coeffs of the polynomials in
                    886:  * vector v (considered as degree n-1 polynomials) */
                    887: GEN
                    888: vecpol_to_mat(GEN v, long n)
                    889: {
                    890:   long i,j,d,N = lg(v);
                    891:   GEN p1,w, y = cgetg(N, t_MAT);
                    892:   if (typ(v) != t_VEC) err(typeer,"vecpol_to_mat");
                    893:   n++;
                    894:   for (j=1; j<N; j++)
                    895:   {
                    896:     p1 = cgetg(n,t_COL); y[j] = (long)p1;
                    897:     w = (GEN)v[j];
                    898:     if (typ(w) != t_POL) { p1[1] = (long)w; i=2; }
                    899:     else
                    900:     {
                    901:       d=lgef(w)-1; w++;
                    902:       for (i=1; i<d; i++) p1[i] = w[i];
                    903:     }
                    904:     for ( ; i<n; i++) p1[i] = zero;
                    905:   }
                    906:   return y;
                    907: }
                    908: /* polynomial (in v) of polynomials (in w) whose coeffs are given by the columns of x */
                    909: GEN
                    910: mat_to_polpol(GEN x, long v,long w)
                    911: {
                    912:   long i,j, lx = lg(x), lcol = lg(x[1]);
                    913:   GEN y = cgetg(lx+1, t_POL);
                    914:   y[1]=evalsigne(1) | evallgef(lx+1) | evalvarn(v);
                    915:   y++;
                    916:   for (j=1; j<lx; j++)
                    917:   {
                    918:     GEN p1, col = (GEN)x[j];
                    919:     long k;
                    920:     i=lcol+1; p1=cgetg(i,t_POL);
                    921:     p1[1] = evalsigne(1) | evallgef(i) | evalvarn(w);
                    922:     col--; for (k=2; k<i; k++) p1[k] = col[k];
                    923:     y[j] = (long)normalizepol_i(p1,i);
                    924:   }
                    925:   return normalizepol_i(--y,lx+1);
                    926: }
                    927:
                    928: /* matrix whose entries are given by the coeffs of the polynomial v in
                    929:  * two variables (considered as degree n polynomials) */
                    930: GEN
                    931: polpol_to_mat(GEN v, long n)
                    932: {
                    933:   long i,j,d,N = lgef(v)-1;
                    934:   GEN p1,w, y = cgetg(N, t_MAT);
                    935:   if (typ(v) != t_POL) err(typeer,"polpol_to_mat");
                    936:   n++;v++;
                    937:   for (j=1; j<N; j++)
                    938:   {
                    939:     p1 = cgetg(n,t_COL); y[j] = (long)p1;
                    940:     w = (GEN)v[j];
                    941:     if (typ(w) != t_POL) { p1[1] = (long)w; i=2; }
                    942:     else
                    943:     {
                    944:       d=lgef(w)-1; w++;
                    945:       for (i=1; i<d; i++) p1[i] = w[i];
                    946:     }
                    947:     for ( ; i<n; i++) p1[i] = zero;
                    948:   }
                    949:   return y;
                    950: }
                    951:
                    952:
                    953: /* set x <-- x + c*y mod p */
                    954: static void
                    955: split_berlekamp_addmul(GEN x, GEN y, long c, long p)
                    956: {
                    957:   long i,lx,ly,l;
                    958:   if (!c) return;
                    959:   lx = lgef(x); ly = lgef(y); l = min(lx,ly);
                    960:   if (p & ~MAXHALFULONG)
                    961:   {
                    962:     for (i=2; i<l;  i++) x[i] = ((ulong)x[i]+ (ulong)mulssmod(c,y[i],p)) % p;
                    963:     for (   ; i<ly; i++) x[i] = mulssmod(c,y[i],p);
                    964:   }
                    965:   else
                    966:   {
                    967:     for (i=2; i<l;  i++) x[i] = ((ulong)x[i] + (ulong)(c*y[i])) % p;
                    968:     for (   ; i<ly; i++) x[i] = (c*y[i]) % p;
                    969:   }
                    970:   do i--; while (i>1 && !x[i]);
                    971:   if (i==1) setsigne(x,0); else { setsigne(x,1); setlgef(x,i+1); }
                    972: }
                    973:
                    974: long
                    975: split_berlekamp(GEN *t, GEN pp, GEN pps2)
                    976: {
                    977:   GEN u = *t, p1, p2, vker,pol;
                    978:   long av,N = degpol(u), d,i,kk,l1,l2,p, vu = varn(u);
                    979:   ulong av0 = avma;
                    980:
                    981:   vker = Berlekamp_ker(u,pp);
                    982:   vker = mat_to_vecpol(vker,vu);
                    983:   d = lg(vker)-1;
                    984:   p = is_bigint(pp)? 0: pp[2];
                    985:   if (p)
                    986:   {
                    987:     avma = av0; p1 = cgetg(d+1, t_VEC); /* hack: hidden gerepile */
                    988:     for (i=1; i<=d; i++) p1[i] = (long)pol_to_small((GEN)vker[i]);
                    989:     vker = p1;
                    990:   }
                    991:   pol = cgetg(N+3,t_POL);
                    992:
                    993:   for (kk=1; kk<d; )
                    994:   {
                    995:     GEN polt;
                    996:     if (p)
                    997:     {
                    998:       if (p==2)
                    999:       {
                   1000:         pol[2] = ((mymyrand() & 0x1000) == 0);
                   1001:         pol[1] = evallgef(pol[2]? 3: 2);
                   1002:         for (i=2; i<=d; i++)
                   1003:           split_berlekamp_addmul(pol,(GEN)vker[i],(mymyrand()&0x1000)?0:1, p);
                   1004:       }
                   1005:       else
                   1006:       {
                   1007:         pol[2] = mymyrand()%p; /* vker[1] = 1 */
                   1008:         pol[1] = evallgef(pol[2]? 3: 2);
                   1009:         for (i=2; i<=d; i++)
                   1010:           split_berlekamp_addmul(pol,(GEN)vker[i],mymyrand()%p, p);
                   1011:       }
                   1012:       polt = small_to_pol(pol,vu);
                   1013:     }
                   1014:     else
                   1015:     {
                   1016:       pol[2] = (long)genrand(pp);
                   1017:       pol[1] = evallgef(signe(pol[2])? 3: 2) | evalvarn(vu);
                   1018:       for (i=2; i<=d; i++)
                   1019:         pol = gadd(pol, gmul((GEN)vker[i], genrand(pp)));
                   1020:       polt = FpX_red(pol,pp);
                   1021:     }
                   1022:     for (i=1; i<=kk && kk<d; i++)
                   1023:     {
                   1024:       p1=t[i-1]; l1=degpol(p1);
                   1025:       if (l1>1)
                   1026:       {
                   1027:         av = avma; p2 = FpX_res(polt, p1, pp);
                   1028:         if (lgef(p2) <= 3) { avma=av; continue; }
                   1029:         p2 = FpXQ_pow(p2,pps2, p1,pp);
                   1030:         if (!signe(p2)) err(talker,"%Z not a prime in split_berlekamp",pp);
                   1031:         p2 = ZX_s_add(p2, -1);
                   1032:         p2 = FpX_gcd(p1,p2, pp); l2=degpol(p2);
                   1033:         if (l2>0 && l2<l1)
                   1034:         {
                   1035:           p2 = FpX_normalize(p2, pp);
                   1036:           t[i-1] = p2; kk++;
                   1037:           t[kk-1] = FpX_div(p1,p2,pp);
                   1038:           if (DEBUGLEVEL > 7) msgtimer("new factor");
                   1039:         }
                   1040:         else avma = av;
                   1041:       }
                   1042:     }
                   1043:   }
                   1044:   return d;
                   1045: }
                   1046:
                   1047: GEN
                   1048: factmod0(GEN f, GEN pp)
                   1049: {
                   1050:   long i,j,k,e,p,N,nbfact,av = avma,tetpil,d;
                   1051:   GEN pps2,ex,y,f2,p1,g1,u, *t;
                   1052:
                   1053:   if (!(d = factmod_init(&f, pp, &p))) { avma=av; return trivfact(); }
                   1054:   /* to hold factors and exponents */
                   1055:   t = (GEN*)cgetg(d+1,t_VEC); ex = cgetg(d+1,t_VECSMALL);
                   1056:   e = nbfact = 1;
                   1057:   pps2 = shifti(pp,-1);
                   1058:
                   1059:   for(;;)
                   1060:   {
                   1061:     f2 = FpX_gcd(f,derivpol(f), pp);
                   1062:     g1 = lgef(f2)==3? f: FpX_div(f,f2,pp);
                   1063:     k = 0;
                   1064:     while (lgef(g1)>3)
                   1065:     {
                   1066:       k++; if (p && !(k%p)) { k++; f2 = FpX_div(f2,g1,pp); }
                   1067:       p1 = FpX_gcd(f2,g1, pp); u = g1; g1 = p1;
                   1068:       if (lgef(p1)!=3)
                   1069:       {
                   1070:         u = FpX_div( u,p1,pp);
                   1071:         f2= FpX_div(f2,p1,pp);
                   1072:       }
                   1073:       N = degpol(u);
                   1074:       if (N)
                   1075:       {
                   1076:         /* here u is square-free (product of irred. of multiplicity e * k) */
                   1077:         t[nbfact] = FpX_normalize(u,pp);
                   1078:         d = (N==1)? 1: split_berlekamp(t+nbfact, pp, pps2);
                   1079:         for (j=0; j<d; j++) ex[nbfact+j] = e*k;
                   1080:         nbfact += d;
                   1081:       }
                   1082:     }
                   1083:     if (!p) break;
                   1084:     j=(degpol(f2))/p+3; if (j==3) break;
                   1085:
                   1086:     e*=p; setlg(f,j); setlgef(f,j);
                   1087:     for (i=2; i<j; i++) f[i] = f2[p*(i-2)+2];
                   1088:   }
                   1089:   tetpil=avma; y=cgetg(3,t_VEC);
                   1090:   setlg((GEN)t, nbfact);
                   1091:   setlg(ex, nbfact);
                   1092:   y[1]=lcopy((GEN)t);
                   1093:   y[2]=lcopy(ex);
                   1094:   (void)sort_factor(y,cmpii);
                   1095:   return gerepile(av,tetpil,y);
                   1096: }
                   1097: GEN
                   1098: factmod(GEN f, GEN pp)
                   1099: {
                   1100:   long tetpil,av=avma;
                   1101:   long nbfact;
                   1102:   long j;
                   1103:   GEN y,u,v;
                   1104:   GEN z=factmod0(f,pp),t=(GEN)z[1],ex=(GEN)z[2];
                   1105:   nbfact=lg(t);
                   1106:   tetpil=avma; y=cgetg(3,t_MAT);
                   1107:   u=cgetg(nbfact,t_COL); y[1]=(long)u;
                   1108:   v=cgetg(nbfact,t_COL); y[2]=(long)v;
                   1109:   for (j=1; j<nbfact; j++)
                   1110:   {
                   1111:     u[j] = (long)FpX((GEN)t[j], pp);
                   1112:     v[j] = lstoi(ex[j]);
                   1113:   }
                   1114:   return gerepile(av,tetpil,y);
                   1115: }
                   1116: GEN
                   1117: factormod0(GEN f, GEN p, long flag)
                   1118: {
                   1119:   switch(flag)
                   1120:   {
                   1121:     case 0: return factmod(f,p);
                   1122:     case 1: return simplefactmod(f,p);
                   1123:     default: err(flagerr,"factormod");
                   1124:   }
                   1125:   return NULL; /* not reached */
                   1126: }
                   1127:
                   1128: /*******************************************************************/
                   1129: /*                                                                 */
                   1130: /*                Recherche de racines  p-adiques                  */
                   1131: /*                                                                 */
                   1132: /*******************************************************************/
                   1133: /* make f suitable for [root|factor]padic */
                   1134: static GEN
                   1135: padic_pol_to_int(GEN f)
                   1136: {
                   1137:   long i, l = lgef(f);
                   1138:   f = gdiv(f,content(f));
                   1139:   for (i=2; i<l; i++)
                   1140:     switch(typ(f[i]))
                   1141:     {
                   1142:       case t_INT: break;
                   1143:       case t_PADIC: f[i] = ltrunc((GEN)f[i]); break;
                   1144:       default: err(talker,"incorrect coeffs in padic_pol_to_int");
                   1145:     }
                   1146:   return f;
                   1147: }
                   1148:
                   1149: /* return invlead * (x + O(pr)), x in Z or Z_p, pr = p^r */
                   1150: static GEN
                   1151: int_to_padic(GEN x, GEN p, GEN pr, long r, GEN invlead)
                   1152: {
                   1153:   GEN p1,y;
                   1154:   long v,sx, av = avma;
                   1155:
                   1156:   if (typ(x) == t_PADIC)
                   1157:   {
                   1158:     v = valp(x);
                   1159:     if (r >= precp(x) + v) return invlead? gmul(x, invlead): gcopy(x);
                   1160:     sx = !gcmp0(x);
                   1161:     p1 = (GEN)x[4];
                   1162:   }
                   1163:   else
                   1164:   {
                   1165:     sx = signe(x);
                   1166:     if (!sx) return gzero;
                   1167:     v = pvaluation(x,p,&p1);
                   1168:   }
                   1169:   y = cgetg(5,t_PADIC);
                   1170:   if (sx && v < r)
                   1171:   {
                   1172:     y[4] = lmodii(p1,pr); r -= v;
                   1173:   }
                   1174:   else
                   1175:   {
                   1176:     y[4] = zero; v = r; r = 0;
                   1177:   }
                   1178:   y[3] = (long)pr;
                   1179:   y[2] = (long)p;
                   1180:   y[1] = evalprecp(r)|evalvalp(v);
                   1181:   return invlead? gerepileupto(av, gmul(invlead,y)): y;
                   1182: }
                   1183:
                   1184: /* return (x + O(p^r)) normalized (multiply by a unit such that leading coeff
                   1185:  * is a power of p), x in Z[X] (or Z_p[X]) */
                   1186: static GEN
                   1187: pol_to_padic(GEN x, GEN pr, GEN p, long r)
                   1188: {
                   1189:   long v = 0,i,lx = lgef(x);
                   1190:   GEN z = cgetg(lx,t_POL), lead = leading_term(x);
                   1191:
                   1192:   if (gcmp1(lead)) lead = NULL;
                   1193:   else
                   1194:   {
                   1195:     long av = avma;
                   1196:     v = ggval(lead,p);
                   1197:     if (v) lead = gdiv(lead, gpowgs(p,v));
                   1198:     lead = int_to_padic(lead,p,pr,r,NULL);
                   1199:     lead = gerepileupto(av, ginv(lead));
                   1200:   }
                   1201:   for (i=lx-1; i>1; i--)
                   1202:     z[i] = (long)int_to_padic((GEN)x[i],p,pr,r,lead);
                   1203:   z[1] = x[1]; return z;
                   1204: }
                   1205:
                   1206: static GEN
                   1207: padic_trivfact(GEN x, GEN p, long r)
                   1208: {
                   1209:   GEN p1, y = cgetg(3,t_MAT);
                   1210:   p1=cgetg(2,t_COL); y[1]=(long)p1; p = icopy(p);
                   1211:   p1[1]=(long)pol_to_padic(x,gpowgs(p,r),p,r);
                   1212:   p1=cgetg(2,t_COL); y[2]=(long)p1;
                   1213:   p1[1]=un; return y;
                   1214: }
                   1215:
                   1216: /* a etant un p-adique, retourne le vecteur des racines p-adiques de f
                   1217:  * congrues a a modulo p dans le cas ou on suppose f(a) congru a 0 modulo p
                   1218:  * (ou a 4 si p=2).
                   1219:  */
                   1220: GEN
                   1221: apprgen(GEN f, GEN a)
                   1222: {
                   1223:   GEN fp,p1,p,P,pro,x,x2,u,ip;
                   1224:   long av=avma,tetpil,v,Ps,i,j,k,lu,n,fl2;
                   1225:
                   1226:   if (typ(f)!=t_POL) err(notpoler,"apprgen");
                   1227:   if (gcmp0(f)) err(zeropoler,"apprgen");
                   1228:   if (typ(a) != t_PADIC) err(rootper1);
                   1229:   f = padic_pol_to_int(f);
                   1230:   fp=derivpol(f); p1=ggcd(f,fp);
                   1231:   if (lgef(p1)>3) { f=gdeuc(f,p1); fp=derivpol(f); }
                   1232:   p=(GEN)a[2]; p1=poleval(f,a);
                   1233:   v=ggval(p1,p); if (v <= 0) err(rootper2);
                   1234:   fl2=egalii(p,gdeux);
                   1235:   if (fl2 && v==1) err(rootper2);
                   1236:   v=ggval(poleval(fp,a),p);
                   1237:   if (!v) /* simple zero */
                   1238:   {
                   1239:     while (!gcmp0(p1))
                   1240:     {
                   1241:       a = gsub(a,gdiv(p1,poleval(fp,a)));
                   1242:       p1 = poleval(f,a);
                   1243:     }
                   1244:     tetpil=avma; pro=cgetg(2,t_VEC); pro[1]=lcopy(a);
                   1245:     return gerepile(av,tetpil,pro);
                   1246:   }
                   1247:   n=degpol(f); pro=cgetg(n+1,t_VEC);
                   1248:
                   1249:   if (is_bigint(p)) err(impl,"apprgen for p>=2^31");
                   1250:   x = ggrandocp(p, valp(a) | precp(a));
                   1251:   if (fl2)
                   1252:   {
                   1253:     x2=ggrandocp(p,2); P = stoi(4);
                   1254:   }
                   1255:   else
                   1256:   {
                   1257:     x2=ggrandocp(p,1); P = p;
                   1258:   }
                   1259:   f = poleval(f, gadd(a,gmul(P,polx[varn(f)])));
                   1260:   if (!gcmp0(f)) f = gdiv(f,gpuigs(p,ggval(f, p)));
                   1261:   Ps = itos(P);
                   1262:   for (j=0,i=0; i<Ps; i++)
                   1263:   {
                   1264:     ip=stoi(i);
                   1265:     if (gcmp0(poleval(f,gadd(ip,x2))))
                   1266:     {
                   1267:       u=apprgen(f,gadd(x,ip)); lu=lg(u);
                   1268:       for (k=1; k<lu; k++)
                   1269:       {
                   1270:         j++; pro[j]=ladd(a,gmul(P,(GEN)u[k]));
                   1271:       }
                   1272:     }
                   1273:   }
                   1274:   setlg(pro,j+1); return gerepilecopy(av,pro);
                   1275: }
                   1276:
                   1277: /* Retourne le vecteur des racines p-adiques de f en precision r */
                   1278: GEN
                   1279: rootpadic(GEN f, GEN p, long r)
                   1280: {
                   1281:   GEN fp,y,z,p1,pr,rac;
                   1282:   long lx,i,j,k,n,av=avma,tetpil,fl2;
                   1283:
                   1284:   if (typ(f)!=t_POL) err(notpoler,"rootpadic");
                   1285:   if (gcmp0(f)) err(zeropoler,"rootpadic");
                   1286:   if (r<=0) err(rootper4);
                   1287:   f = padic_pol_to_int(f);
                   1288:   fp=derivpol(f); p1=ggcd(f,fp);
                   1289:   if (lgef(p1)>3) { f=gdeuc(f,p1); fp=derivpol(f); }
                   1290:   fl2=egalii(p,gdeux); rac=(fl2 && r>=2)? rootmod(f,stoi(4)): rootmod(f,p);
                   1291:   lx=lg(rac); p=gclone(p);
                   1292:   if (r==1)
                   1293:   {
                   1294:     tetpil=avma; y=cgetg(lx,t_COL);
                   1295:     for (i=1; i<lx; i++)
                   1296:     {
                   1297:       z=cgetg(5,t_PADIC); y[i]=(long)z;
                   1298:       z[1] = evalprecp(1)|evalvalp(0);
                   1299:       z[2] = z[3] = (long)p;
                   1300:       z[4] = lcopy(gmael(rac,i,2));
                   1301:     }
                   1302:     return gerepile(av,tetpil,y);
                   1303:   }
                   1304:   n=degpol(f); y=cgetg(n+1,t_COL);
                   1305:   j=0; pr = NULL;
                   1306:   z = cgetg(5,t_PADIC);
                   1307:   z[2] = (long)p;
                   1308:   for (i=1; i<lx; i++)
                   1309:   {
                   1310:     p1 = gmael(rac,i,2);
                   1311:     if (signe(p1))
                   1312:     {
                   1313:       if (!fl2 || mod2(p1))
                   1314:       {
                   1315:         z[1] = evalvalp(0)|evalprecp(r);
                   1316:         z[4] = (long)p1;
                   1317:       }
                   1318:       else
                   1319:       {
                   1320:         z[1] = evalvalp(1)|evalprecp(r);
                   1321:         z[4] = un;
                   1322:       }
                   1323:       if (!pr) pr=gpuigs(p,r);
                   1324:       z[3] = (long)pr;
                   1325:     }
                   1326:     else
                   1327:     {
                   1328:       z[1] = evalvalp(r);
                   1329:       z[3] = un;
                   1330:       z[4] = (long)p1;
                   1331:     }
                   1332:     p1 = apprgen(f,z);
                   1333:     for (k=1; k<lg(p1); k++) y[++j]=p1[k];
                   1334:   }
                   1335:   setlg(y,j+1); return gerepilecopy(av,y);
                   1336: }
                   1337: /*************************************************************************/
                   1338: /*                             rootpadicfast                             */
                   1339: /*************************************************************************/
                   1340:
                   1341: /*lift accelerator. The author of the idea is unknown.*/
                   1342: long hensel_lift_accel(long n, long *pmask)
                   1343: {
                   1344:   long a,j;
                   1345:   long mask;
                   1346:   mask=0;
                   1347:   for(j=BITS_IN_LONG-1, a=n ;; j--)
                   1348:   {
                   1349:     mask|=(a&1)<<j;
                   1350:     a=(a>>1)+(a&1);
                   1351:     if (a==1) break;
                   1352:   }
                   1353:   *pmask=mask>>j;
                   1354:   return BITS_IN_LONG-j;
                   1355: }
                   1356: /*
                   1357:   SPEC:
                   1358:   q is an integer > 1
                   1359:   e>=0
                   1360:   f in ZZ[X], with leading term prime to q.
                   1361:   S must be a simple root mod p for all p|q.
                   1362:
                   1363:   return roots of f mod q^e, as integers (implicitly mod Q)
                   1364: */
                   1365:
                   1366: /* STANDARD USE
                   1367:    There exists p a prime number and a>0 such that
                   1368:    q=p^a
                   1369:    f in ZZ[X], with leading term prime to p.
                   1370:    S must be a simple root mod p.
                   1371:
                   1372:    return p-adics roots of f with prec b, as integers (implicitly mod q^e)
                   1373: */
                   1374:
                   1375: GEN
                   1376: rootpadiclift(GEN T, GEN S, GEN p, long e)
                   1377: {
                   1378:   ulong   ltop=avma;
                   1379:   long    x;
                   1380:   GEN     qold, q, qm1;
                   1381:   GEN     W, Tr, Sr, Wr = gzero;
                   1382:   long     i, nb, mask;
                   1383:   x = varn(T);
                   1384:   qold = p ;  q = p; qm1 = gun;
                   1385:   nb=hensel_lift_accel(e, &mask);
                   1386:   Tr = FpX_red(T,q);
                   1387:   W=FpX_eval(deriv(Tr, x),S,q);
                   1388:   W=mpinvmod(W,q);
                   1389:   for(i=0;i<nb;i++)
                   1390:   {
                   1391:     qm1 = (mask&(1<<i))?sqri(qm1):mulii(qm1, q);
                   1392:     q   =  mulii(qm1, p);
                   1393:     Tr = FpX_red(T,q);
                   1394:     Sr = S;
                   1395:     if (i)
                   1396:     {
                   1397:       W = modii(mulii(Wr,FpX_eval(deriv(Tr,x),Sr,qold)),qold);
                   1398:       W = subii(gdeux,W);
                   1399:       W = modii(mulii(Wr, W),qold);
                   1400:     }
                   1401:     Wr = W;
                   1402:     S = subii(Sr, mulii(Wr, FpX_eval(Tr, Sr,q)));
                   1403:     S = modii(S,q);
                   1404:     qold = q;
                   1405:   }
                   1406:   return gerepileupto(ltop,S);
                   1407: }
                   1408: /*
                   1409:  * Apply rootpadiclift to all roots in S and trace trick.
                   1410:  * Elements of S must be distinct simple roots mod p for all p|q.
                   1411:  */
                   1412:
                   1413: GEN
                   1414: rootpadicliftroots(GEN f, GEN S, GEN q, long e)
                   1415: {
                   1416:   GEN y;
                   1417:   long i,n=lg(S);
                   1418:   if (n==1)
                   1419:     return gcopy(S);
                   1420:   y=cgetg(n,typ(S));
                   1421:   for (i=1; i<n-1; i++)
                   1422:     y[i]=(long) rootpadiclift(f, (GEN) S[i], q, e);
                   1423:   if (n!=lgef(f)-2)/* non totally split*/
                   1424:     y[n-1]=(long) rootpadiclift(f, (GEN) S[n-1], q, e);
                   1425:   else/* distinct-->totally split-->use trace trick */
                   1426:   {
                   1427:     ulong av=avma;
                   1428:     GEN z;
                   1429:     z=(GEN)f[lgef(f)-2];/*-trace(roots)*/
                   1430:     for(i=1; i<n-1;i++)
                   1431:       z=addii(z,(GEN) y[i]);
                   1432:     z=modii(negi(z),gpowgs(q,e));
                   1433:     y[n-1]=lpileupto(av,z);
                   1434:   }
                   1435:   return y;
                   1436: }
                   1437: /*
                   1438:  p is a prime number, pr a power of p,
                   1439:
                   1440:  f in ZZ[X], with leading term prime to p.
                   1441:  f must have no multiple roots mod p.
                   1442:
                   1443:  return p-adics roots of f with prec pr, as integers (implicitly mod pr)
                   1444:
                   1445: */
                   1446: GEN
                   1447: rootpadicfast(GEN f, GEN p, long e)
                   1448: {
                   1449:   ulong ltop=avma;
                   1450:   GEN S,y;
                   1451:   S=lift(rootmod(f,p));/*no multiplicity*/
                   1452:   if (lg(S)==1)/*no roots*/
                   1453:   {
                   1454:     avma=ltop;
                   1455:     return cgetg(1,t_COL);
                   1456:   }
                   1457:   S=gclone(S);
                   1458:   avma=ltop;
                   1459:   y=rootpadicliftroots(f,S,p,e);
                   1460:   gunclone(S);
                   1461:   return y;
                   1462: }
                   1463: /* Same as rootpadiclift for the polynomial X^n-a,
                   1464:  * but here, n can be much larger.
                   1465:  * TODO: generalize to sparse polynomials.
                   1466:  */
                   1467: GEN
                   1468: padicsqrtnlift(GEN a, GEN n, GEN S, GEN p, long e)
                   1469: {
                   1470:   ulong   ltop=avma;
                   1471:   GEN     qold, q, qm1;
                   1472:   GEN     W, Sr, Wr = gzero;
                   1473:   long    i, nb, mask;
                   1474:   qold = p ; q = p; qm1 = gun;
                   1475:   nb   = hensel_lift_accel(e, &mask);
                   1476:   W    = modii(mulii(n,powmodulo(S,subii(n,gun),q)),q);
                   1477:   W    = mpinvmod(W,q);
                   1478:   for(i=0;i<nb;i++)
                   1479:   {
                   1480:     qm1 = (mask&(1<<i))?sqri(qm1):mulii(qm1, q);
                   1481:     q   =  mulii(qm1, p);
                   1482:     Sr = S;
                   1483:     if (i)
                   1484:     {
                   1485:       W = modii(mulii(Wr,mulii(n,powmodulo(Sr,subii(n,gun),qold))),qold);
                   1486:       W = subii(gdeux,W);
                   1487:       W = modii(mulii(Wr, W),qold);
                   1488:     }
                   1489:     Wr = W;
                   1490:     S = subii(Sr, mulii(Wr, subii(powmodulo(Sr,n,q),a)));
                   1491:     S = modii(S,q);
                   1492:     qold = q;
                   1493:   }
                   1494:   return gerepileupto(ltop,S);
                   1495: }
                   1496: /**************************************************************************/
                   1497: static long
                   1498: getprec(GEN x, long prec, GEN *p)
                   1499: {
                   1500:   long i,e;
                   1501:   GEN p1;
                   1502:
                   1503:   for (i = lgef(x)-1; i>1; i--)
                   1504:   {
                   1505:     p1=(GEN)x[i];
                   1506:     if (typ(p1)==t_PADIC)
                   1507:     {
                   1508:       e=valp(p1); if (signe(p1[4])) e += precp(p1);
                   1509:       if (e<prec) prec = e; *p = (GEN)p1[2];
                   1510:     }
                   1511:   }
                   1512:   return prec;
                   1513: }
                   1514:
                   1515: /* a appartenant a une extension finie de Q_p, retourne le vecteur des
                   1516:  * racines de f congrues a a modulo p dans le cas ou on suppose f(a) congru a
                   1517:  * 0 modulo p (ou a 4 si p=2).
                   1518:  */
                   1519: GEN
                   1520: apprgen9(GEN f, GEN a)
                   1521: {
                   1522:   GEN fp,p1,p,pro,x,x2,u,ip,t,vecg;
                   1523:   long av=avma,tetpil,v,ps_1,i,j,k,lu,n,prec,d,va,fl2;
                   1524:
                   1525:   if (typ(f)!=t_POL) err(notpoler,"apprgen9");
                   1526:   if (gcmp0(f)) err(zeropoler,"apprgen9");
                   1527:   if (typ(a)==t_PADIC) return apprgen(f,a);
                   1528:   if (typ(a)!=t_POLMOD || typ(a[2])!=t_POL) err(rootper1);
                   1529:   fp=derivpol(f); p1=ggcd(f,fp);
                   1530:   if (lgef(p1)>3) { f=gdeuc(f,p1); fp=derivpol(f); }
                   1531:   t=(GEN)a[1];
                   1532:   prec = getprec((GEN)a[2], BIGINT, &p);
                   1533:   prec = getprec(t, prec, &p);
                   1534:   if (prec==BIGINT) err(rootper1);
                   1535:
                   1536:   p1=poleval(f,a); v=ggval(lift_intern(p1),p); if (v<=0) err(rootper2);
                   1537:   fl2=egalii(p,gdeux);
                   1538:   if (fl2 && v==1) err(rootper2);
                   1539:   v=ggval(lift_intern(poleval(fp,a)), p);
                   1540:   if (!v)
                   1541:   {
                   1542:     while (!gcmp0(p1))
                   1543:     {
                   1544:       a = gsub(a, gdiv(p1,poleval(fp,a)));
                   1545:       p1 = poleval(f,a);
                   1546:     }
                   1547:     tetpil=avma; pro=cgetg(2,t_COL); pro[1]=lcopy(a);
                   1548:     return gerepile(av,tetpil,pro);
                   1549:   }
                   1550:   n=degpol(f); pro=cgetg(n+1,t_COL); j=0;
                   1551:
                   1552:   if (is_bigint(p)) err(impl,"apprgen9 for p>=2^31");
                   1553:   x=gmodulcp(ggrandocp(p,prec), t);
                   1554:   if (fl2)
                   1555:   {
                   1556:     ps_1=3; x2=ggrandocp(p,2); p=stoi(4);
                   1557:   }
                   1558:   else
                   1559:   {
                   1560:     ps_1=itos(p)-1; x2=ggrandocp(p,1);
                   1561:   }
                   1562:   f = poleval(f,gadd(a,gmul(p,polx[varn(f)])));
                   1563:   if (!gcmp0(f)) f=gdiv(f,gpuigs(p,ggval(f,p)));
                   1564:   d=degpol(t); vecg=cgetg(d+1,t_COL);
                   1565:   for (i=1; i<=d; i++)
                   1566:     vecg[i] = (long)setloop(gzero);
                   1567:   va=varn(t);
                   1568:   for(;;) /* loop through F_q */
                   1569:   {
                   1570:     ip=gmodulcp(gtopoly(vecg,va),t);
                   1571:     if (gcmp0(poleval(f,gadd(ip,x2))))
                   1572:     {
                   1573:       u=apprgen9(f,gadd(ip,x)); lu=lg(u);
                   1574:       for (k=1; k<lu; k++)
                   1575:       {
                   1576:         j++; pro[j]=ladd(a,gmul(p,(GEN)u[k]));
                   1577:       }
                   1578:     }
                   1579:     for (i=d; i; i--)
                   1580:     {
                   1581:       p1 = (GEN)vecg[i];
                   1582:       if (p1[2] != ps_1) { (void)incloop(p1); break; }
                   1583:       affsi(0, p1);
                   1584:     }
                   1585:     if (!i) break;
                   1586:   }
                   1587:   setlg(pro,j+1); return gerepilecopy(av,pro);
                   1588: }
                   1589:
                   1590: /*****************************************/
                   1591: /*  Factorisation p-adique d'un polynome */
                   1592: /*****************************************/
                   1593: int
                   1594: cmp_padic(GEN x, GEN y)
                   1595: {
                   1596:   long vx, vy;
                   1597:   if (x == gzero) return -1;
                   1598:   if (y == gzero) return  1;
                   1599:   vx = valp(x);
                   1600:   vy = valp(y);
                   1601:   if (vx < vy) return  1;
                   1602:   if (vx > vy) return -1;
                   1603:   return cmpii((GEN)x[4], (GEN)y[4]);
                   1604: }
                   1605:
                   1606: /* factorise le polynome T=nf[1] dans Zp avec la precision pr */
                   1607: static GEN
                   1608: padicff2(GEN nf,GEN p,long pr)
                   1609: {
                   1610:   long N=degpol(nf[1]),i,j,d,l;
                   1611:   GEN mat,V,D,fa,p1,pk,dec_p,pke,a,theta;
                   1612:
                   1613:   pk=gpuigs(p,pr); dec_p=primedec(nf,p);
                   1614:   l=lg(dec_p); fa=cgetg(l,t_COL);
                   1615:   for (i=1; i<l; i++)
                   1616:   {
                   1617:     p1 = (GEN)dec_p[i];
                   1618:     pke = idealpows(nf,p1, pr * itos((GEN)p1[3]));
                   1619:     p1=smith2(pke); V=(GEN)p1[3]; D=(GEN)p1[1];
                   1620:     for (d=1; d<=N; d++)
                   1621:       if (! egalii(gcoeff(V,d,d),pk)) break;
                   1622:     a=ginv(D); theta=gmael(nf,8,2); mat=cgetg(d,t_MAT);
                   1623:     for (j=1; j<d; j++)
                   1624:     {
                   1625:       p1 = gmul(D, element_mul(nf,theta,(GEN)a[j]));
                   1626:       setlg(p1,d); mat[j]=(long)p1;
                   1627:     }
                   1628:     fa[i]=(long)caradj(mat,0,NULL);
                   1629:   }
                   1630:   a = cgetg(l,t_COL); pk = icopy(pk);
                   1631:   for (i=1; i<l; i++)
                   1632:     a[i] = (long)pol_to_padic((GEN)fa[i],pk,p,pr);
                   1633:   return a;
                   1634: }
                   1635:
                   1636: static GEN
                   1637: padicff(GEN x,GEN p,long pr)
                   1638: {
                   1639:   GEN q,basden,bas,invbas,mul,dx,nf,mat;
                   1640:   long n=degpol(x),av=avma;
                   1641:
                   1642:   nf=cgetg(10,t_VEC); nf[1]=(long)x; dx=discsr(x);
                   1643:   mat=cgetg(3,t_MAT); mat[1]=lgetg(3,t_COL); mat[2]=lgetg(3,t_COL);
                   1644:   coeff(mat,1,1)=(long)p; coeff(mat,1,2)=lstoi(pvaluation(dx,p,&q));
                   1645:   coeff(mat,2,1)=(long)q; coeff(mat,2,2)=un;
                   1646:   bas=allbase4(x,(long)mat,(GEN*)(nf+3),NULL);
                   1647:   if (!carrecomplet(divii(dx,(GEN)nf[3]),(GEN*)(nf+4)))
                   1648:     err(bugparier,"factorpadic2 (incorrect discriminant)");
                   1649:   basden = get_bas_den(bas);
                   1650:   invbas = QM_inv(vecpol_to_mat(bas,n), gun);
                   1651:   mul = get_mul_table(x,basden,invbas,NULL);
                   1652:   nf[7]=(long)bas;
                   1653:   nf[8]=(long)invbas;
                   1654:   nf[9]=(long)mul; nf[2]=nf[5]=nf[6]=zero;
                   1655:   return gerepileupto(av,padicff2(nf,p,pr));
                   1656: }
                   1657:
                   1658: GEN
                   1659: factorpadic2(GEN x, GEN p, long r)
                   1660: {
                   1661:   long av=avma,av2,k,i,j,i1,f,nbfac;
                   1662:   GEN res,p1,p2,y,d,a,ap,t,v,w;
                   1663:   GEN *fa;
                   1664:
                   1665:   if (typ(x)!=t_POL) err(notpoler,"factorpadic");
                   1666:   if (gcmp0(x)) err(zeropoler,"factorpadic");
                   1667:   if (r<=0) err(rootper4);
                   1668:
                   1669:   if (lgef(x)==3) return trivfact();
                   1670:  if (!gcmp1(leading_term(x)))
                   1671:     err(impl,"factorpadic2 for non-monic polynomial");
                   1672:   if (lgef(x)==4) return padic_trivfact(x,p,r);
                   1673:   y=cgetg(3,t_MAT);
                   1674:   fa = (GEN*)new_chunk(lgef(x)-2);
                   1675:   d=content(x); a=gdiv(x,d);
                   1676:   ap=derivpol(a); t=ggcd(a,ap); v=gdeuc(a,t);
                   1677:   w=gdeuc(ap,t); j=0; f=1; nbfac=0;
                   1678:   while (f)
                   1679:   {
                   1680:     j++; w=gsub(w,derivpol(v)); f=signe(w);
                   1681:     if (f) { res=ggcd(v,w); v=gdeuc(v,res); w=gdeuc(w,res); }
                   1682:     else res=v;
                   1683:     fa[j]=(lgef(res)>3) ? padicff(res,p,r) : cgetg(1,t_COL);
                   1684:     nbfac += (lg(fa[j])-1);
                   1685:   }
                   1686:   av2=avma; y=cgetg(3,t_MAT);
                   1687:   p1=cgetg(nbfac+1,t_COL); y[1]=(long)p1;
                   1688:   p2=cgetg(nbfac+1,t_COL); y[2]=(long)p2;
                   1689:   for (i=1,k=0; i<=j; i++)
                   1690:     for (i1=1; i1<lg(fa[i]); i1++)
                   1691:     {
                   1692:       p1[++k]=lcopy((GEN)fa[i][i1]); p2[k]=lstoi(i);
                   1693:     }
                   1694:   y = gerepile(av,av2,y);
                   1695:   sort_factor(y, cmp_padic); return y;
                   1696: }
                   1697:
                   1698: /*******************************************************************/
                   1699: /*                                                                 */
                   1700: /*                FACTORISATION P-adique avec ROUND 4              */
                   1701: /*                                                                 */
                   1702: /*******************************************************************/
                   1703: extern GEN Decomp(GEN p,GEN f,long mf,GEN theta,GEN chi,GEN nu,long r);
                   1704: extern GEN nilord(GEN p, GEN fx, long mf, GEN gx, long flag);
                   1705: extern GEN hensel_lift_fact(GEN pol, GEN Q, GEN T, GEN p, GEN pev, long e);
                   1706:
                   1707: static GEN
                   1708: squarefree(GEN f, GEN *ex)
                   1709: {
                   1710:   GEN T,V,W,A,B;
                   1711:   long n,i,k;
                   1712:
                   1713:   T=ggcd(derivpol(f),f); V=gdeuc(f,T);
                   1714:   n=lgef(f)-2; A=cgetg(n,t_COL); B=cgetg(n,t_COL);
                   1715:   k=1; i=1;
                   1716:   do
                   1717:   {
                   1718:     W=ggcd(T,V); T=gdeuc(T,W);
                   1719:     if (lgef(V) != lgef(W))
                   1720:     {
                   1721:       A[i]=ldeuc(V,W); B[i]=k; i++;
                   1722:     }
                   1723:     k++; V=W;
                   1724:   }
                   1725:   while (lgef(V)>3);
                   1726:   setlg(A,i); *ex=B; return A;
                   1727: }
                   1728:
                   1729: #define swap(x,y) { long _t=x; x=y; y=_t; }
                   1730:
                   1731: /* reverse x in place */
                   1732: static void
                   1733: polreverse(GEN x)
                   1734: {
                   1735:   long i, j;
                   1736:   if (typ(x) != t_POL) err(typeer,"polreverse");
                   1737:   for (i=2, j=lgef(x)-1; i<j; i++, j--) swap(x[i], x[j]);
                   1738:   (void)normalizepol(x);
                   1739: }
                   1740:
                   1741: GEN
                   1742: factorpadic4(GEN f,GEN p,long prec)
                   1743: {
                   1744:   GEN w,g,poly,fx,y,p1,p2,ex,pols,exps,ppow,lead;
                   1745:   long v=varn(f),n=degpol(f),av,tetpil,mfx,i,k,j,r,pr;
                   1746:   int reverse = 0;
                   1747:
                   1748:   if (typ(f)!=t_POL) err(notpoler,"factorpadic");
                   1749:   if (typ(p)!=t_INT) err(arither1);
                   1750:   if (gcmp0(f)) err(zeropoler,"factorpadic");
                   1751:   if (prec<=0) err(rootper4);
                   1752:
                   1753:   if (n==0) return trivfact();
                   1754:   av=avma; f = padic_pol_to_int(f);
                   1755:   if (n==1) return gerepileupto(av, padic_trivfact(f,p,prec));
                   1756:   lead = leading_term(f); pr = prec;
                   1757:   if (!gcmp1(lead))
                   1758:   {
                   1759:     long val = ggval(lead,p), val1 = ggval(constant_term(f),p);
                   1760:     if (val1 < val)
                   1761:     {
                   1762:       reverse = 1; polreverse(f);
                   1763:      /* take care of loss of precision from leading coeff of factor
                   1764:       * (whose valuation is <= val) */
                   1765:       pr += val;
                   1766:       val = val1;
                   1767:     }
                   1768:     pr += val * (n-1);
                   1769:   }
                   1770:   f = pol_to_monic(f, &lead);
                   1771:
                   1772:   poly=squarefree(f,&ex);
                   1773:   pols=cgetg(n+1,t_COL);
                   1774:   exps=cgetg(n+1,t_COL); n = lg(poly);
                   1775:   for (j=1,i=1; i<n; i++)
                   1776:   {
                   1777:     long av1 = avma;
                   1778:     fx=(GEN)poly[i]; mfx=ggval(discsr(fx),p);
                   1779:     w = (GEN)factmod(fx,p)[1];
                   1780:     if (!mfx)
                   1781:     { /* no repeated factors: Hensel lift */
                   1782:       p1 = hensel_lift_fact(fx, lift_intern(w), NULL, p, gpowgs(p,pr), pr);
                   1783:       p2 = stoi(ex[i]);
                   1784:       for (k=1; k<lg(p1); k++,j++)
                   1785:       {
                   1786:         pols[j] = p1[k];
                   1787:         exps[j] = (long)p2;
                   1788:       }
                   1789:       continue;
                   1790:     }
                   1791:     /* use Round 4 */
                   1792:     r = lg(w)-1;
                   1793:     g = lift_intern((GEN)w[r]);
                   1794:     p2 = (r == 1)? nilord(p,fx,mfx,g,pr)
                   1795:                  : Decomp(p,fx,mfx,polx[v],fx,g, (pr<=mfx)? mfx+1: pr);
                   1796:     if (p2)
                   1797:     {
                   1798:       p2 = gerepileupto(av1,p2);
                   1799:       p1 = (GEN)p2[1];
                   1800:       p2 = (GEN)p2[2];
                   1801:       for (k=1; k<lg(p1); k++,j++)
                   1802:       {
                   1803:         pols[j]=p1[k];
                   1804:         exps[j]=lmulis((GEN)p2[k],ex[i]);
                   1805:       }
                   1806:     }
                   1807:     else
                   1808:     {
                   1809:       avma=av1;
                   1810:       pols[j]=(long)fx;
                   1811:       exps[j]=lstoi(ex[i]); j++;
                   1812:     }
                   1813:   }
                   1814:   if (lead)
                   1815:   {
                   1816:     p1 = gmul(polx[v],lead);
                   1817:     for (i=1; i<j; i++)
                   1818:     {
                   1819:       p2 = poleval((GEN)pols[i], p1);
                   1820:       pols[i] = ldiv(p2, content(p2));
                   1821:     }
                   1822:   }
                   1823:
                   1824:   tetpil=avma; y=cgetg(3,t_MAT);
                   1825:   p1 = cgetg(j,t_COL); ppow = gpowgs(p,prec); p = icopy(p);
                   1826:   for (i=1; i<j; i++)
                   1827:   {
                   1828:     if (reverse) polreverse((GEN)pols[i]);
                   1829:     p1[i] = (long)pol_to_padic((GEN)pols[i],ppow,p,prec);
                   1830:   }
                   1831:   y[1]=(long)p1; setlg(exps,j);
                   1832:   y[2]=lcopy(exps); y = gerepile(av,tetpil,y);
                   1833:   sort_factor(y, cmp_padic); return y;
                   1834: }
                   1835:
                   1836: GEN
                   1837: factorpadic0(GEN f,GEN p,long r,long flag)
                   1838: {
                   1839:   switch(flag)
                   1840:   {
                   1841:      case 0: return factorpadic4(f,p,r);
                   1842:      case 1: return factorpadic2(f,p,r);
                   1843:      default: err(flagerr,"factorpadic");
                   1844:   }
                   1845:   return NULL; /* not reached */
                   1846: }
                   1847:
                   1848: /*******************************************************************/
                   1849: /*                                                                 */
                   1850: /*                     FACTORISATION DANS F_q                      */
                   1851: /*                                                                 */
                   1852: /*******************************************************************/
                   1853: extern GEN to_Kronecker(GEN P, GEN Q);
                   1854: extern GEN from_Kronecker(GEN z, GEN pol);
                   1855: static GEN spec_Fq_pow_mod_pol(GEN x, GEN p, GEN a, GEN S);
                   1856:
                   1857: static GEN
                   1858: to_fq(GEN x, GEN a, GEN p)
                   1859: {
                   1860:   long i,lx = lgef(x);
                   1861:   GEN z = cgetg(3,t_POLMOD), pol = cgetg(lx,t_POL);
                   1862:   pol[1] = x[1];
                   1863:   if (lx == 2) setsigne(pol, 0);
                   1864:   else
                   1865:     for (i=2; i<lx; i++) pol[i] = (long)mod((GEN)x[i], p);
                   1866:   /* assume deg(pol) < deg(a) */
                   1867:   z[1] = (long)a;
                   1868:   z[2] = (long)pol; return z;
                   1869: }
                   1870:
                   1871: /* x POLMOD over Fq, return lift(x^n) */
                   1872: static GEN
                   1873: Kronecker_powmod(GEN x, GEN mod, GEN n)
                   1874: {
                   1875:   long lim,av,av0 = avma, i,j,m,v = varn(x);
                   1876:   GEN y, p1, p = NULL, pol = NULL;
                   1877:
                   1878:   for (i=lgef(mod)-1; i>1; i--)
                   1879:   {
                   1880:     p1 = (GEN)mod[i];
                   1881:     if (typ(p1) == t_POLMOD) { pol = (GEN)p1[1] ; break; }
                   1882:   }
                   1883:   if (!pol) err(talker,"need POLMOD coeffs in Kronecker_powmod");
                   1884:   for (i=lgef(pol)-1; i>1; i--)
                   1885:   {
                   1886:     p1 = (GEN)pol[i];
                   1887:     if (typ(p1) == t_INTMOD) { p = (GEN)p1[1] ; break; }
                   1888:   }
                   1889:   if (!p) err(talker,"need Fq coeffs in Kronecker_powmod");
                   1890:   x = lift_intern(to_Kronecker(x,pol));
                   1891:
                   1892:   /* adapted from powgi */
                   1893:   av=avma; lim=stack_lim(av,1);
                   1894:   p1 = n+2; m = *p1;
                   1895:
                   1896:   y=x; j=1+bfffo(m); m<<=j; j = BITS_IN_LONG-j;
                   1897:   for (i=lgefint(n)-2;;)
                   1898:   {
                   1899:     for (; j; m<<=1,j--)
                   1900:     {
                   1901:       y = gsqr(y);
                   1902:       y = from_Kronecker(FpX(y,p), pol);
                   1903:       setvarn(y, v);
                   1904:       y = gres(y, mod);
                   1905:       y = lift_intern(to_Kronecker(y,pol));
                   1906:
                   1907:       if (m<0)
                   1908:       {
                   1909:         y = gmul(y,x);
                   1910:         y = from_Kronecker(FpX(y,p), pol);
                   1911:         setvarn(y, v);
                   1912:         y = gres(y, mod);
                   1913:         y = lift_intern(to_Kronecker(y,pol));
                   1914:       }
                   1915:       if (low_stack(lim, stack_lim(av,1)))
                   1916:       {
                   1917:         if(DEBUGMEM>1) err(warnmem,"Kronecker_powmod");
                   1918:         y = gerepilecopy(av, y);
                   1919:       }
                   1920:     }
                   1921:     if (--i == 0) break;
                   1922:     m = *++p1, j = BITS_IN_LONG;
                   1923:   }
                   1924:   y = from_Kronecker(FpX(y,p),pol);
                   1925:   setvarn(y, v); return gerepileupto(av0, y);
                   1926: }
                   1927:
                   1928: GEN
                   1929: FpX_rand(long d1, long v, GEN p)
                   1930: {
                   1931:   long i, d = d1+2;
                   1932:   GEN y;
                   1933:   y = cgetg(d,t_POL); y[1] = evalsigne(1) | evalvarn(v);
                   1934:   for (i=2; i<d; i++) y[i] = (long)genrand(p);
                   1935:   normalizepol_i(y,d); return y;
                   1936: }
                   1937:
                   1938: /* return a random polynomial in F_q[v], degree < d1 */
                   1939: static GEN
                   1940: FqX_rand(long d1, long v, GEN p, GEN a)
                   1941: {
                   1942:   long i,j, d = d1+2, k = lgef(a)-1;
                   1943:   GEN y,t;
                   1944:
                   1945:   y = cgetg(d,t_POL); y[1] = evalsigne(1) | evalvarn(v);
                   1946:   t = cgetg(k,t_POL); t[1] = a[1];
                   1947:   for (i=2; i<d; i++)
                   1948:   {
                   1949:     for (j=2; j<k; j++) t[j] = (long)genrand(p);
                   1950:     normalizepol_i(t,k); y[i]=(long)to_fq(t,a,p);
                   1951:   }
                   1952:   normalizepol_i(y,d); return y;
                   1953: }
                   1954:
                   1955: /* split into r factors of degree d */
                   1956: static void
                   1957: split9(GEN *t, long d, GEN p, GEN q, GEN a, GEN S)
                   1958: {
                   1959:   long l,v,av,is2,cnt, dt = degpol(*t), da = degpol(a);
                   1960:   GEN w,w0;
                   1961:
                   1962:   if (dt == d) return;
                   1963:   v = varn(*t);
                   1964:   if (DEBUGLEVEL > 6) timer2();
                   1965:   av = avma; is2 = egalii(p, gdeux);
                   1966:   for(cnt = 1;;cnt++)
                   1967:   { /* splits *t with probability ~ 1 - 2^(1-r) */
                   1968:     w = w0 = FqX_rand(dt,v, p,a);
                   1969:     for (l=1; l<d; l++) /* sum_{0<i<d} w^(q^i), result in (F_q)^r */
                   1970:       w = gadd(w0, spec_Fq_pow_mod_pol(w, p, a, S));
                   1971:     if (is2)
                   1972:     {
                   1973:       w0 = w;
                   1974:       for (l=1; l<da; l++) /* sum_{0<i<k} w^(2^i), result in (F_2)^r */
                   1975:         w = gadd(w0, gres(gsqr(w), *t));
                   1976:     }
                   1977:     else
                   1978:     {
                   1979:       w = Kronecker_powmod(w, *t, shifti(q,-1));
                   1980:       /* w in {-1,0,1}^r */
                   1981:       if (lgef(w) == 3) continue;
                   1982:       w[2] = ladd((GEN)w[2], gun);
                   1983:     }
                   1984:     w = ggcd(*t,w); l = degpol(w);
                   1985:     if (l && l != dt) break;
                   1986:     avma = av;
                   1987:   }
                   1988:   w = gerepileupto(av,w);
                   1989:   if (DEBUGLEVEL > 6)
                   1990:     fprintferr("[split9] time for splitting: %ld (%ld trials)\n",timer2(),cnt);
                   1991:   l /= d; t[l]=gdeuc(*t,w); *t=w;
                   1992:   split9(t+l,d,p,q,a,S);
                   1993:   split9(t  ,d,p,q,a,S);
                   1994: }
                   1995:
                   1996: /* to "compare" (real) scalars and t_INTMODs */
                   1997: static int
                   1998: cmp_coeff(GEN x, GEN y)
                   1999: {
                   2000:   if (typ(x) == t_INTMOD) x = (GEN)x[2];
                   2001:   if (typ(y) == t_INTMOD) y = (GEN)y[2];
                   2002:   return gcmp(x,y);
                   2003: }
                   2004:
                   2005: int
                   2006: cmp_pol(GEN x, GEN y)
                   2007: {
                   2008:   long fx[3], fy[3];
                   2009:   long i,lx,ly;
                   2010:   int fl;
                   2011:   if (typ(x) == t_POLMOD) x = (GEN)x[2];
                   2012:   if (typ(y) == t_POLMOD) y = (GEN)y[2];
                   2013:   if (typ(x) == t_POL) lx = lgef(x); else { lx = 3; fx[2] = (long)x; x = fx; }
                   2014:   if (typ(y) == t_POL) ly = lgef(y); else { ly = 3; fy[2] = (long)y; y = fy; }
                   2015:   if (lx > ly) return  1;
                   2016:   if (lx < ly) return -1;
                   2017:   for (i=lx-1; i>1; i--)
                   2018:     if ((fl = cmp_coeff((GEN)x[i], (GEN)y[i]))) return fl;
                   2019:   return 0;
                   2020: }
                   2021:
                   2022: /* assume n > 1, X a POLMOD over Fq */
                   2023: /* return S = [ X^q, X^2q, ... X^(n-1)q ] mod T (in Fq[X]) in Kronecker form */
                   2024: static GEN
                   2025: init_pow_q_mod_pT(GEN Xmod, GEN q, GEN a, GEN T)
                   2026: {
                   2027:   long i, n = degpol(T);
                   2028:   GEN p1, S = cgetg(n, t_VEC);
                   2029:
                   2030:   S[1] = (long)Kronecker_powmod((GEN)Xmod[2], (GEN)Xmod[1], q);
                   2031: #if 1 /* use as many squarings as possible */
                   2032:   for (i=2; i < n; i+=2)
                   2033:   {
                   2034:     p1 = gsqr((GEN)S[i>>1]);
                   2035:     S[i]   = lres(p1, T);
                   2036:     if (i == n-1) break;
                   2037:     p1 = gmul((GEN)S[i], (GEN)S[1]);
                   2038:     S[i+1] = lres(p1, T);
                   2039:   }
                   2040: #else
                   2041:   for (i=2; i < n; i++)
                   2042:   {
                   2043:     p1 = gmul((GEN)S[i-1], (GEN)S[1]);
                   2044:     S[i] = lres(p1, T);
                   2045:   }
                   2046: #endif
                   2047:   for (i=1; i < n; i++)
                   2048:     S[i] = (long)lift_intern(to_Kronecker((GEN)S[i], a));
                   2049:   return S;
                   2050: }
                   2051:
                   2052: /* compute x^q, S is as above */
                   2053: static GEN
                   2054: spec_Fq_pow_mod_pol(GEN x, GEN p, GEN a, GEN S)
                   2055: {
                   2056:   long av = avma, lim = stack_lim(av,1), i,dx = degpol(x);
                   2057:   GEN x0 = x+2, z,c;
                   2058:
                   2059:   c = (GEN)x0[0];
                   2060:   z = lift_intern(lift(c));
                   2061:   for (i = 1; i <= dx; i++)
                   2062:   {
                   2063:     GEN d;
                   2064:     c = (GEN)x0[i];
                   2065:     if (gcmp0(c)) continue;
                   2066:     d = (GEN)S[i];
                   2067:     if (!gcmp1(c)) d = gmul(lift_intern(lift(c)),d);
                   2068:     z = gadd(z, d);
                   2069:     if (low_stack(lim, stack_lim(av,1)))
                   2070:     {
                   2071:       if(DEBUGMEM>1) err(warnmem,"spec_Fq_pow_mod_pol");
                   2072:       z = gerepileupto(av, z);
                   2073:     }
                   2074:   }
                   2075:   z = FpX(z, p);
                   2076:   z = from_Kronecker(z, a);
                   2077:   setvarn(z, varn(x)); return gerepileupto(av, z);
                   2078: }
                   2079:
                   2080: static long isabsolutepol(GEN f, GEN pp, GEN a)
                   2081: {
                   2082:   int i,res=1;
                   2083:   GEN c;
                   2084:   for(i=2; i<lg(f); i++)
                   2085:   {
                   2086:     c = (GEN) f[i];
                   2087:     switch(typ(c))
                   2088:     {
                   2089:     case t_INT: /* OK*/
                   2090:       break;
                   2091:     case t_INTMOD:
                   2092:       if (gcmp((GEN)c[1],pp))
                   2093:        err(typeer,"factmod9");
                   2094:       break;
                   2095:     case t_POLMOD:
                   2096:       if (gcmp((GEN)c[1],a))
                   2097:        err(typeer,"factmod9");
                   2098:       isabsolutepol((GEN)c[1],pp,gzero);
                   2099:       isabsolutepol((GEN)c[2],pp,gzero);
                   2100:       if (degpol(c[1])>0)
                   2101:        res = 0;
                   2102:       break;
                   2103:     case t_POL:
                   2104:       isabsolutepol(c,pp,gzero);
                   2105:       if (degpol(c)>0)
                   2106:        res = 0;
                   2107:       break;
                   2108:     default:
                   2109:       err(typeer,"factmod9");
                   2110:     }
                   2111:   }
                   2112:   return res;
                   2113: }
                   2114:
                   2115: GEN
                   2116: factmod9(GEN f, GEN pp, GEN a)
                   2117: {
                   2118:   long av = avma, tetpil,p,i,j,k,d,e,vf,va,nbfact,nbf,pk;
                   2119:   GEN S,ex,y,f2,f3,df1,df2,g,g1,xmod,u,v,qqd,qq,unfp,unfq, *t;
                   2120:   GEN frobinv,X;
                   2121:
                   2122:   if (typ(a)!=t_POL || typ(f)!=t_POL || gcmp0(a)) err(typeer,"factmod9");
                   2123:   vf=varn(f); va=varn(a);
                   2124:   if (va<=vf) err(talker,"polynomial variable must be of higher priority than finite field\nvariable in factorff");
                   2125:   if (isabsolutepol(f, pp, a))
                   2126:   {
                   2127:     GEN z= Fp_factor_rel0(simplify(lift(lift(f))), pp, lift(a));
                   2128:     GEN t=(GEN)z[1],ex=(GEN)z[2];
                   2129:     unfp = gmodulsg(1,pp);
                   2130:     unfq = gmodulcp(gmul(unfp, polun[va]), gmul(unfp,a));
                   2131:     nbfact=lg(t);
                   2132:     tetpil=avma;
                   2133:     y=cgetg(3,t_MAT);
                   2134:     u=cgetg(nbfact,t_COL); y[1]=(long)u;
                   2135:     v=cgetg(nbfact,t_COL); y[2]=(long)v;
                   2136:     for (j=1; j<nbfact; j++)
                   2137:     {
                   2138:       u[j] = lmul((GEN)t[j],unfq);
                   2139:       v[j] = lstoi(ex[j]);
                   2140:     }
                   2141:     return gerepile(av,tetpil,y);
                   2142:   }
                   2143:   p = is_bigint(pp)? 0: itos(pp);
                   2144:   unfp=gmodulsg(1,pp); a=gmul(unfp,a);
                   2145:   unfq=gmodulo(gmul(unfp,polun[va]), a); a = (GEN)unfq[1];
                   2146:   f = gmul(unfq,f); if (!signe(f)) err(zeropoler,"factmod9");
                   2147:   d = degpol(f); if (!d) { avma=av; gunclone(a); return trivfact(); }
                   2148:
                   2149:   S = df2  = NULL; /* gcc -Wall */
                   2150:   pp = gmael(a,2,1); /* out of the stack */
                   2151:   t = (GEN*)cgetg(d+1,t_VEC); ex = new_chunk(d+1);
                   2152:
                   2153:   frobinv = gpowgs(pp, lgef(a)-4);
                   2154:   xmod = cgetg(3,t_POLMOD);
                   2155:   X = gmul(polx[vf],unfq);
                   2156:   xmod[2] = (long)X;
                   2157:   qq=gpuigs(pp,degpol(a));
                   2158:   e = nbfact = 1;
                   2159:   pk=1; df1=derivpol(f); f3=NULL;
                   2160:   for(;;)
                   2161:   {
                   2162:     long du,dg;
                   2163:     while (gcmp0(df1))
                   2164:     { /* needs d >= pp: p = 0 can't happen  */
                   2165:       pk *= p; e=pk;
                   2166:       j=(degpol(f))/p+3; setlg(f,j); setlgef(f,j);
                   2167:       for (i=2; i<j; i++) f[i] = (long)powgi((GEN)f[p*(i-2)+2], frobinv);
                   2168:       df1=derivpol(f); f3=NULL;
                   2169:     }
                   2170:     f2 = f3? f3: ggcd(f,df1);
                   2171:     if (lgef(f2)==3) u = f;
                   2172:     else
                   2173:     {
                   2174:       g1=gdeuc(f,f2); df2=derivpol(f2);
                   2175:       if (gcmp0(df2)) { u=g1; f3=f2; }
                   2176:       else
                   2177:       {
                   2178:         f3=ggcd(f2,df2);
                   2179:         if (lgef(f3)==3) u=gdeuc(g1,f2);
                   2180:         else
                   2181:           u=gdeuc(g1,gdeuc(f2,f3));
                   2182:       }
                   2183:     }
                   2184:     /* u is square-free (product of irreducibles of multiplicity e) */
                   2185:     qqd=gun; xmod[1]=(long)u;
                   2186:
                   2187:     du = degpol(u); v = X;
                   2188:     if (du > 1) S = init_pow_q_mod_pT(xmod, qq, a, u);
                   2189:     for (d=1; d <= du>>1; d++)
                   2190:     {
                   2191:       qqd=mulii(qqd,qq);
                   2192:       v = spec_Fq_pow_mod_pol(v, pp, a, S);
                   2193:       g = ggcd(gsub(v,X),u);
                   2194:       dg = degpol(g);
                   2195:       if (dg <= 0) continue;
                   2196:
                   2197:       /* all factors of g have degree d */
                   2198:       j = nbfact+dg/d;
                   2199:
                   2200:       t[nbfact] = g;
                   2201:       split9(t+nbfact,d,pp,qq,a,S);
                   2202:       for (; nbfact<j; nbfact++) ex[nbfact]=e;
                   2203:       du -= dg;
                   2204:       u = gdeuc(u,g);
                   2205:       v = gres(v,u); xmod[1] = (long)u;
                   2206:     }
                   2207:     if (du) { t[nbfact]=u; ex[nbfact++]=e; }
                   2208:     if (lgef(f2) == 3) break;
                   2209:
                   2210:     f=f2; df1=df2; e += pk;
                   2211:   }
                   2212:
                   2213:   nbf=nbfact; tetpil=avma; y=cgetg(3,t_MAT);
                   2214:   for (j=1; j<nbfact; j++)
                   2215:   {
                   2216:     t[j]=gdiv((GEN)t[j],leading_term(t[j]));
                   2217:     for (k=1; k<j; k++)
                   2218:       if (ex[k] && gegal(t[j],t[k]))
                   2219:       {
                   2220:         ex[k] += ex[j]; ex[j]=0;
                   2221:         nbf--; break;
                   2222:       }
                   2223:   }
                   2224:   u=cgetg(nbf,t_COL); y[1]=(long)u;
                   2225:   v=cgetg(nbf,t_COL); y[2]=(long)v;
                   2226:   for (j=1,k=0; j<nbfact; j++)
                   2227:     if (ex[j])
                   2228:     {
                   2229:       k++;
                   2230:       u[k]=(long)t[j];
                   2231:       v[k]=lstoi(ex[j]);
                   2232:     }
                   2233:   y = gerepile(av,tetpil,y);
                   2234:   u=(GEN)y[1];
                   2235:   { /* put a back on the stack */
                   2236:     GEN tokill = a;
                   2237:     a = forcecopy(a);
                   2238:     gunclone(tokill);
                   2239:   }
                   2240:   pp = (GEN)leading_term(a)[1];
                   2241:   for (j=1; j<nbf; j++) fqunclone((GEN)u[j], a, pp);
                   2242:   (void)sort_factor(y, cmp_pol); return y;
                   2243: }
                   2244: /* See also: Isomorphisms between finite field and relative
                   2245:  * factorization in polarit3.c */
                   2246:
                   2247: /*******************************************************************/
                   2248: /*                                                                 */
                   2249: /*                         RACINES COMPLEXES                       */
                   2250: /*        l represente la longueur voulue pour les parties         */
                   2251: /*            reelles et imaginaires des racines de x              */
                   2252: /*                                                                 */
                   2253: /*******************************************************************/
                   2254: GEN square_free_factorization(GEN pol);
                   2255: static GEN laguer(GEN pol,long N,GEN y0,GEN EPS,long PREC);
                   2256: GEN zrhqr(GEN a,long PREC);
                   2257:
                   2258: GEN
                   2259: rootsold(GEN x, long l)
                   2260: {
                   2261:   long av1=avma,i,j,f,g,gg,fr,deg,l0,l1,l2,l3,l4,ln;
                   2262:   long exc,expmin,m,deg0,k,ti,h,ii,e,e1,emax,v;
                   2263:   GEN y,xc,xd0,xd,xdabs,p1,p2,p3,p4,p5,p6,p7,p8;
                   2264:   GEN p9,p10,p11,p12,p14,p15,pa,pax,pb,pp,pq,ps;
                   2265:
                   2266:   if (typ(x)!=t_POL) err(typeer,"rootsold");
                   2267:   v=varn(x); deg0=degpol(x); expmin=12 - bit_accuracy(l);
                   2268:   if (!signe(x)) err(zeropoler,"rootsold");
                   2269:   y=cgetg(deg0+1,t_COL); if (!deg0) return y;
                   2270:   for (i=1; i<=deg0; i++)
                   2271:   {
                   2272:     p1=cgetg(3,t_COMPLEX); p1[1]=lgetr(l); p1[2]=lgetr(l); y[i]=(long)p1;
                   2273:     for (j=3; j<l; j++) ((GEN)p1[2])[j]=((GEN)p1[1])[j]=0;
                   2274:   }
                   2275:   g=1; gg=1;
                   2276:   for (i=2; i<=deg0+2; i++)
                   2277:   {
                   2278:     ti=typ(x[i]);
                   2279:     if (ti==t_REAL) gg=0;
                   2280:     else if (ti==t_QUAD)
                   2281:     {
                   2282:       p2=gmael3(x,i,1,2);
                   2283:       if (gsigne(p2)>0) g=0;
                   2284:     } else if (ti != t_INT && ti != t_INTMOD && !is_frac_t(ti)) g=0;
                   2285:   }
                   2286:   l1=avma; p2=cgetg(3,t_COMPLEX);
                   2287:   p2[1]=lmppi(DEFAULTPREC); p2[2]=ldivrs((GEN)p2[1],10);
                   2288:   p11=cgetg(4,t_POL); p11[1]=evalsigne(1)+evallgef(4);
                   2289:   setvarn(p11,v); p11[3]=un;
                   2290:
                   2291:   p12=cgetg(5,t_POL); p12[1]=evalsigne(1)+evallgef(5);
                   2292:   setvarn(p12,v); p12[4]=un;
                   2293:   for (i=2; i<=deg0+2 && gcmp0((GEN)x[i]); i++) gaffsg(0,(GEN)y[i-1]);
                   2294:   k=i-2;
                   2295:   if (k!=deg0)
                   2296:   {
                   2297:     if (k)
                   2298:     {
                   2299:       j=deg0+3-k; pax=cgetg(j,t_POL);
                   2300:       pax[1] = evalsigne(1) | evalvarn(v) | evallgef(j);
                   2301:       for (i=2; i<j; i++) pax[i]=x[i+k];
                   2302:     }
                   2303:     else pax=x;
                   2304:     xd0=deriv(pax,v); m=1; pa=pax;
                   2305:     pq = NULL; /* for lint */
                   2306:     if (gg) { pp=ggcd(pax,xd0); h=isnonscalar(pp); if (h) pq=gdeuc(pax,pp); }
                   2307:     else{ pp=gun; h=0; }
                   2308:     do
                   2309:     {
                   2310:       if (h)
                   2311:       {
                   2312:         pa=pp; pb=pq; pp=ggcd(pa,deriv(pa,v)); h=isnonscalar(pp);
                   2313:         if (h) pq=gdeuc(pa,pp); else pq=pa; ps=gdeuc(pb,pq);
                   2314:       }
                   2315:       else ps=pa;
                   2316:           /* calcul des racines d'ordre exactement m */
                   2317:       deg=degpol(ps);
                   2318:       if (deg)
                   2319:       {
                   2320:         l3=avma; e=gexpo((GEN)ps[deg+2]); emax=e;
                   2321:         for (i=2; i<deg+2; i++)
                   2322:         {
                   2323:           p3=(GEN)(ps[i]);
                   2324:           e1=gexpo(p3); if (e1>emax) emax=e1;
                   2325:         }
                   2326:         e=emax-e; if (e<0) e=0; avma=l3; if (ps!=pax) xd0=deriv(ps,v);
                   2327:         xdabs=cgetg(deg+2,t_POL); xdabs[1]=xd0[1];
                   2328:         for (i=2; i<deg+2; i++)
                   2329:         {
                   2330:           l3=avma; p3=(GEN)xd0[i];
                   2331:           p4=gabs(greal(p3),l);
                   2332:           p5=gabs(gimag(p3),l); l4=avma;
                   2333:           xdabs[i]=lpile(l3,l4,gadd(p4,p5));
                   2334:         }
                   2335:         l0=avma; xc=gcopy(ps); xd=gcopy(xd0); l2=avma;
                   2336:         for (i=1; i<=deg; i++)
                   2337:         {
                   2338:           if (i==deg)
                   2339:           {
                   2340:             p1=(GEN)y[k+m*i]; gdivz(gneg_i((GEN)xc[2]),(GEN)xc[3],p1);
                   2341:             p14=(GEN)p1[1]; p15=(GEN)p1[2];
                   2342:           }
                   2343:           else
                   2344:           {
                   2345:             p3=gshift(p2,e); p4=poleval(xc,p3); p5=gnorm(p4); exc=0;
                   2346:             while (exc >= -20)
                   2347:             {
                   2348:               p7 = gneg_i(gdiv(p4, poleval(xd,p3)));
                   2349:               l3 = avma;
                   2350:               if (gcmp0(p5)) exc = -32;
                   2351:               else exc = expo(gnorm(p7))-expo(gnorm(p3));
                   2352:               avma = l3;
                   2353:               for (j=1; j<=10; j++)
                   2354:               {
                   2355:                 p8=gadd(p3,p7); p9=poleval(xc,p8); p10=gnorm(p9);
                   2356:                 if (exc < -20 || cmprr(p10,p5) < 0)
                   2357:                 {
                   2358:                   GEN *gptr[3];
                   2359:                   p3=p8; p4=p9; p5=p10;
                   2360:                   gptr[0]=&p3; gptr[1]=&p4; gptr[2]=&p5;
                   2361:                   gerepilemanysp(l2,l3,gptr,3);
                   2362:                   break;
                   2363:                 }
                   2364:                 gshiftz(p7,-2,p7); avma=l3;
                   2365:               }
                   2366:               if (j > 10)
                   2367:               {
                   2368:                 avma=av1;
                   2369:                 if (DEBUGLEVEL)
                   2370:                 {
                   2371:                   fprintferr("too many iterations in rootsold(): ");
                   2372:                   fprintferr("using roots2()\n"); flusherr();
                   2373:                 }
                   2374:                 return roots2(x,l);
                   2375:               }
                   2376:             }
                   2377:             p1=(GEN)y[k+m*i]; setlg(p1[1],3); setlg(p1[2],3); gaffect(p3,p1);
                   2378:             avma=l2; p14=(GEN)p1[1]; p15=(GEN)p1[2];
                   2379:             for (ln=4; ln<=l; ln=(ln<<1)-2)
                   2380:             {
                   2381:               setlg(p14,ln); setlg(p15,ln);
                   2382:               if (gcmp0(p14)) { settyp(p14,t_INT); p14[1]=2; }
                   2383:               if (gcmp0(p15)) { settyp(p15,t_INT); p15[1]=2; }
                   2384:               p4=poleval(xc,p1);
                   2385:               p5=poleval(xd,p1); p6=gneg_i(gdiv(p4,p5));
                   2386:               settyp(p14,t_REAL); settyp(p15,t_REAL);
                   2387:               gaffect(gadd(p1,p6),p1); avma=l2;
                   2388:             }
                   2389:           }
                   2390:           setlg(p14,l); setlg(p15,l);
                   2391:           p7=gcopy(p1); p14=(GEN)(p7[1]); p15=(GEN)(p7[2]);
                   2392:           setlg(p14,l+1); setlg(p15,l+1);
                   2393:           if (gcmp0(p14)) { settyp(p14,t_INT); p14[1]=2; }
                   2394:           if (gcmp0(p15)) { settyp(p15,t_INT); p15[1]=2; }
                   2395:           for (ii=1; ii<=5; ii++)
                   2396:           {
                   2397:             p4=poleval(ps,p7); p5=poleval(xd0,p7);
                   2398:             p6=gneg_i(gdiv(p4,p5)); p7=gadd(p7,p6);
                   2399:             p14=(GEN)(p7[1]); p15=(GEN)(p7[2]);
                   2400:             if (gcmp0(p14)) { settyp(p14,t_INT); p14[1]=2; }
                   2401:             if (gcmp0(p15)) { settyp(p15,t_INT); p15[1]=2; }
                   2402:           }
                   2403:           gaffect(p7,p1); p4=poleval(ps,p7);
                   2404:           p6=gdiv(p4,poleval(xdabs,gabs(p7,l)));
                   2405:           if (gexpo(p6)>=expmin)
                   2406:           {
                   2407:             avma=av1;
                   2408:             if (DEBUGLEVEL)
                   2409:             {
                   2410:               fprintferr("internal error in rootsold(): using roots2()\n");
                   2411:               flusherr();
                   2412:             }
                   2413:             return roots2(x,l);
                   2414:           }
                   2415:           avma=l2;
                   2416:           if (expo(p1[2])<expmin && g)
                   2417:           {
                   2418:             gaffect(gzero,(GEN)p1[2]);
                   2419:             for (j=1; j<m; j++) gaffect(p1,(GEN)y[k+(i-1)*m+j]);
                   2420:             p11[2]=lneg((GEN)p1[1]);
                   2421:             l4=avma; xc=gerepile(l0,l4,gdeuc(xc,p11));
                   2422:           }
                   2423:           else
                   2424:           {
                   2425:             for (j=1; j<m; j++) gaffect(p1,(GEN)y[k+(i-1)*m+j]);
                   2426:             if (g)
                   2427:             {
                   2428:               p1=gconj(p1);
                   2429:               for (j=1; j<=m; j++) gaffect(p1,(GEN)y[k+i*m+j]);
                   2430:               i++;
                   2431:               p12[2]=lnorm(p1); p12[3]=lmulsg(-2,(GEN)p1[1]); l4=avma;
                   2432:               xc=gerepile(l0,l4,gdeuc(xc,p12));
                   2433:             }
                   2434:             else
                   2435:             {
                   2436:               p11[2]=lneg(p1); l4=avma;
                   2437:               xc=gerepile(l0,l4,gdeuc(xc,p11));
                   2438:             }
                   2439:           }
                   2440:           xd=deriv(xc,v); l2=avma;
                   2441:         }
                   2442:         k += deg*m;
                   2443:       }
                   2444:       m++;
                   2445:     }
                   2446:     while (k!=deg0);
                   2447:   }
                   2448:   avma=l1;
                   2449:   for (j=2; j<=deg0; j++)
                   2450:   {
                   2451:     p1 = (GEN)y[j];
                   2452:     if (gcmp0((GEN)p1[2])) fr=0; else fr=1;
                   2453:     for (k=j-1; k>=1; k--)
                   2454:     {
                   2455:       p2 = (GEN)y[k];
                   2456:       if (gcmp0((GEN)p2[2])) f=0; else f=1;
                   2457:       if (f<fr) break;
                   2458:       if (f==fr && gcmp((GEN)p2[1],(GEN)p1[1]) <= 0) break;
                   2459:       y[k+1]=y[k];
                   2460:     }
                   2461:     y[k+1]=(long)p1;
                   2462:   }
                   2463:   return y;
                   2464: }
                   2465:
                   2466: GEN
                   2467: roots2(GEN pol,long PREC)
                   2468: {
                   2469:   ulong av = avma;
                   2470:   long N,flagexactpol,flagrealpol,flagrealrac,ti,i,j;
                   2471:   long nbpol,k,av1,multiqol,deg,nbroot,fr,f;
                   2472:   GEN p1,p2,rr,EPS,qol,qolbis,x,b,c,*ad,v,tabqol;
                   2473:
                   2474:   if (typ(pol)!=t_POL) err(typeer,"roots2");
                   2475:   if (!signe(pol)) err(zeropoler,"roots2");
                   2476:   N=degpol(pol);
                   2477:   if (!N) return cgetg(1,t_COL);
                   2478:   if (N==1)
                   2479:   {
                   2480:     p1=gmul(realun(PREC),(GEN)pol[3]);
                   2481:     p2=gneg_i(gdiv((GEN)pol[2],p1));
                   2482:     return gerepilecopy(av,p2);
                   2483:   }
                   2484:   EPS=realun(3); setexpo(EPS, 12 - bit_accuracy(PREC));
                   2485:   flagrealpol=1; flagexactpol=1;
                   2486:   for (i=2; i<=N+2; i++)
                   2487:   {
                   2488:     ti=typ(pol[i]);
                   2489:     if (ti!=t_INT && ti!=t_INTMOD && !is_frac_t(ti))
                   2490:     {
                   2491:       flagexactpol=0;
                   2492:       if (ti!=t_REAL) flagrealpol=0;
                   2493:     }
                   2494:     if (ti==t_QUAD)
                   2495:     {
                   2496:       p1=gmael3(pol,i,1,2);
                   2497:       flagrealpol = (gsigne(p1)>0)? 0 : 1;
                   2498:     }
                   2499:   }
                   2500:   rr=cgetg(N+1,t_COL);
                   2501:   for (i=1; i<=N; i++)
                   2502:   {
                   2503:     p1 = cgetc(PREC); rr[i] = (long)p1;
                   2504:     for (j=3; j<PREC; j++) mael(p1,2,j)=mael(p1,1,j)=0;
                   2505:   }
                   2506:   if (flagexactpol) tabqol=square_free_factorization(pol);
                   2507:   else
                   2508:   {
                   2509:     tabqol=cgetg(3,t_MAT);
                   2510:     tabqol[1]=lgetg(2,t_COL); mael(tabqol,1,1)=un;
                   2511:     tabqol[2]=lgetg(2,t_COL); mael(tabqol,2,1)=lcopy(pol);
                   2512:   }
                   2513:   nbpol=lg(tabqol[1])-1; nbroot=0;
                   2514:   for (k=1; k<=nbpol; k++)
                   2515:   {
                   2516:     av1=avma; qol=gmael(tabqol,2,k); qolbis=gcopy(qol);
                   2517:     multiqol=itos(gmael(tabqol,1,k)); deg=degpol(qol);
                   2518:     for (j=deg; j>=1; j--)
                   2519:     {
                   2520:       x=gzero; flagrealrac=0;
                   2521:       if (j==1) x=gneg_i(gdiv((GEN)qolbis[2],(GEN)qolbis[3]));
                   2522:       else
                   2523:       {
                   2524:         x=laguer(qolbis,j,x,EPS,PREC);
                   2525:         if (x == NULL) goto RLAB;
                   2526:       }
                   2527:       if (flagexactpol)
                   2528:       {
                   2529:         x=gprec(x,(long)((PREC-1)*pariK));
                   2530:         x=laguer(qol,deg,x,gmul2n(EPS,-32),PREC+1);
                   2531:       }
                   2532:       else x=laguer(qol,deg,x,EPS,PREC);
                   2533:       if (x == NULL) goto RLAB;
                   2534:
                   2535:       if (typ(x)==t_COMPLEX &&
                   2536:           gcmp(gabs(gimag(x),PREC),gmul2n(gmul(EPS,gabs(greal(x),PREC)),1))<=0)
                   2537:         { x[2]=zero; flagrealrac=1; }
                   2538:       else if (j==1 && flagrealpol)
                   2539:         { x[2]=zero; flagrealrac=1; }
                   2540:       else if (typ(x)!=t_COMPLEX) flagrealrac=1;
                   2541:
                   2542:       for (i=1; i<=multiqol; i++) gaffect(x,(GEN)rr[nbroot+i]);
                   2543:       nbroot+=multiqol;
                   2544:       if (!flagrealpol || flagrealrac)
                   2545:       {
                   2546:         ad = (GEN*) new_chunk(j+1);
                   2547:         for (i=0; i<=j; i++) ad[i]=(GEN)qolbis[i+2];
                   2548:         b=(GEN)ad[j];
                   2549:         for (i=j-1; i>=0; i--)
                   2550:         {
                   2551:           c=(GEN)ad[i]; ad[i]=b;
                   2552:           b=gadd(gmul((GEN)rr[nbroot],b),c);
                   2553:         }
                   2554:         v=cgetg(j+1,t_VEC); for (i=1; i<=j; i++) v[i]=(long)ad[j-i];
                   2555:         qolbis=gtopoly(v,varn(qolbis));
                   2556:         if (flagrealpol)
                   2557:           for (i=2; i<=j+1; i++)
                   2558:             if (typ(qolbis[i])==t_COMPLEX) mael(qolbis,i,2)=zero;
                   2559:       }
                   2560:       else
                   2561:       {
                   2562:         ad = (GEN*) new_chunk(j-1); ad[j-2]=(GEN)qolbis[j+2];
                   2563:         p1=gmulsg(2,greal((GEN)rr[nbroot])); p2=gnorm((GEN)rr[nbroot]);
                   2564:         ad[j-3]=gadd((GEN)qolbis[j+1],gmul(p1,ad[j-2]));
                   2565:         for (i=j-2; i>=2; i--)
                   2566:           ad[i-2] = gadd((GEN)qolbis[i+2],gsub(gmul(p1,ad[i-1]),gmul(p2,ad[i])));
                   2567:         v=cgetg(j,t_VEC); for (i=1; i<=j-1; i++) v[i]=(long)ad[j-1-i];
                   2568:         qolbis=gtopoly(v,varn(qolbis));
                   2569:         for (i=2; i<=j; i++)
                   2570:           if (typ(qolbis[i])==t_COMPLEX) mael(qolbis,i,2)=zero;
                   2571:         for (i=1; i<=multiqol; i++)
                   2572:           gaffect(gconj((GEN)rr[nbroot]), (GEN)rr[nbroot+i]);
                   2573:         nbroot+=multiqol; j--;
                   2574:       }
                   2575:     }
                   2576:     avma=av1;
                   2577:   }
                   2578:   for (j=2; j<=N; j++)
                   2579:   {
                   2580:     x=(GEN)rr[j]; if (gcmp0((GEN)x[2])) fr=0; else fr=1;
                   2581:     for (i=j-1; i>=1; i--)
                   2582:     {
                   2583:       if (gcmp0(gmael(rr,i,2))) f=0; else f=1;
                   2584:       if (f<fr) break;
                   2585:       if (f==fr && gcmp(greal((GEN)rr[i]),greal(x)) <= 0) break;
                   2586:       rr[i+1]=rr[i];
                   2587:     }
                   2588:     rr[i+1]=(long)x;
                   2589:   }
                   2590:   return gerepilecopy(av,rr);
                   2591:
                   2592:  RLAB:
                   2593:   avma = av;
                   2594:   for(i=2;i<=N+2;i++)
                   2595:   {
                   2596:     ti = typ(pol[i]);
                   2597:     if (!is_intreal_t(ti)) err(talker,"too many iterations in roots");
                   2598:   }
                   2599:   if (DEBUGLEVEL)
                   2600:   {
                   2601:     fprintferr("too many iterations in roots2() ( laguer() ): \n");
                   2602:     fprintferr("     real coefficients polynomial, using zrhqr()\n");
                   2603:     flusherr();
                   2604:   }
                   2605:   return zrhqr(pol,PREC);
                   2606: }
                   2607:
                   2608: #define MR 8
                   2609: #define MT 10
                   2610:
                   2611: static GEN
                   2612: laguer(GEN pol,long N,GEN y0,GEN EPS,long PREC)
                   2613: {
                   2614:   long av = avma, av1,MAXIT,iter,i,j;
                   2615:   GEN rac,erre,I,x,abx,abp,abm,dx,x1,b,d,f,g,h,sq,gp,gm,g2,*ffrac;
                   2616:
                   2617:   MAXIT=MR*MT; rac=cgetg(3,t_COMPLEX);
                   2618:   rac[1]=lgetr(PREC); rac[2]=lgetr(PREC);
                   2619:   av1 = avma;
                   2620:   I=cgetg(3,t_COMPLEX); I[1]=un; I[2]=un;
                   2621:   ffrac=(GEN*)new_chunk(MR+1); for (i=0; i<=MR; i++) ffrac[i]=cgetr(PREC);
                   2622:   affrr(dbltor(0.0), ffrac[0]); affrr(dbltor(0.5), ffrac[1]);
                   2623:   affrr(dbltor(0.25),ffrac[2]); affrr(dbltor(0.75),ffrac[3]);
                   2624:   affrr(dbltor(0.13),ffrac[4]); affrr(dbltor(0.38),ffrac[5]);
                   2625:   affrr(dbltor(0.62),ffrac[6]); affrr(dbltor(0.88),ffrac[7]);
                   2626:   affrr(dbltor(1.0),ffrac[8]);
                   2627:   x=y0;
                   2628:   for (iter=1; iter<=MAXIT; iter++)
                   2629:   {
                   2630:     b=(GEN)pol[N+2]; erre=QuickNormL1(b,PREC);
                   2631:     d=gzero; f=gzero; abx=QuickNormL1(x,PREC);
                   2632:     for (j=N-1; j>=0; j--)
                   2633:     {
                   2634:       f=gadd(gmul(x,f),d); d=gadd(gmul(x,d),b);
                   2635:       b=gadd(gmul(x,b),(GEN)pol[j+2]);
                   2636:       erre=gadd(QuickNormL1(b,PREC),gmul(abx,erre));
                   2637:     }
                   2638:     erre=gmul(erre,EPS);
                   2639:     if (gcmp(QuickNormL1(b,PREC),erre)<=0)
                   2640:     {
                   2641:       gaffect(x,rac); avma = av1; return rac;
                   2642:     }
                   2643:     g=gdiv(d,b); g2=gsqr(g); h=gsub(g2, gmul2n(gdiv(f,b),1));
                   2644:     sq=gsqrt(gmulsg(N-1,gsub(gmulsg(N,h),g2)),PREC);
                   2645:     gp=gadd(g,sq); gm=gsub(g,sq); abp=gnorm(gp); abm=gnorm(gm);
                   2646:     if (gcmp(abp,abm)<0) gp=gcopy(gm);
                   2647:     if (gsigne(gmax(abp,abm))==1)
                   2648:       dx = gdivsg(N,gp);
                   2649:     else
                   2650:       dx = gmul(gadd(gun,abx),gexp(gmulgs(I,iter),PREC));
                   2651:     x1=gsub(x,dx);
                   2652:     if (gcmp(QuickNormL1(gsub(x,x1),PREC),EPS)<0)
                   2653:     {
                   2654:       gaffect(x,rac); avma = av1; return rac;
                   2655:     }
                   2656:     if (iter%MT) x=gcopy(x1); else x=gsub(x,gmul(ffrac[iter/MT],dx));
                   2657:   }
                   2658:   avma=av; return NULL;
                   2659: }
                   2660:
                   2661: #undef MR
                   2662: #undef MT
                   2663:
                   2664: /***********************************************************************/
                   2665: /**                                                                   **/
                   2666: /**             ROOTS of a polynomial with REAL coeffs                **/
                   2667: /**                                                                   **/
                   2668: /***********************************************************************/
                   2669: #define RADIX 1L
                   2670: #define COF 0.95
                   2671:
                   2672: /* ONLY FOR REAL COEFFICIENTS MATRIX : replace the matrix x with
                   2673:    a symmetric matrix a with the same eigenvalues */
                   2674: static GEN
                   2675: balanc(GEN x)
                   2676: {
                   2677:   ulong av = avma;
                   2678:   long last,i,j, sqrdx = (RADIX<<1), n = lg(x);
                   2679:   GEN r,c,cofgen,a;
                   2680:
                   2681:   a = dummycopy(x);
                   2682:   last = 0; cofgen = dbltor(COF);
                   2683:   while (!last)
                   2684:   {
                   2685:     last = 1;
                   2686:     for (i=1; i<n; i++)
                   2687:     {
                   2688:       r = c = gzero;
                   2689:       for (j=1; j<n; j++)
                   2690:         if (j!=i)
                   2691:         {
                   2692:           c = gadd(c, gabs(gcoeff(a,j,i),0));
                   2693:           r = gadd(r, gabs(gcoeff(a,i,j),0));
                   2694:         }
                   2695:       if (!gcmp0(r) && !gcmp0(c))
                   2696:       {
                   2697:         GEN g, s = gmul(cofgen, gadd(c,r));
                   2698:         long ex = 0;
                   2699:         g = gmul2n(r,-RADIX); while (gcmp(c,g) < 0) {ex++; c=gmul2n(c, sqrdx);}
                   2700:         g = gmul2n(r, RADIX); while (gcmp(c,g) > 0) {ex--; c=gmul2n(c,-sqrdx);}
                   2701:         if (gcmp(gadd(c,r), gmul2n(s,ex)) < 0)
                   2702:         {
                   2703:           last = 0;
                   2704:           for (j=1; j<n; j++) coeff(a,i,j)=lmul2n(gcoeff(a,i,j),-ex);
                   2705:           for (j=1; j<n; j++) coeff(a,j,i)=lmul2n(gcoeff(a,j,i), ex);
                   2706:         }
                   2707:       }
                   2708:     }
                   2709:   }
                   2710:   return gerepilecopy(av, a);
                   2711: }
                   2712:
                   2713: #define SIGN(a,b) ((b)>=0.0 ? fabs(a) : -fabs(a))
                   2714: static GEN
                   2715: hqr(GEN mat) /* find all the eigenvalues of the matrix mat */
                   2716: {
                   2717:   long nn,n,m,l,k,j,its,i,mmin,flj,flk;
                   2718:   double **a,p,q,r,s,t,u,v,w,x,y,z,anorm,*wr,*wi;
                   2719:   const double eps = 0.000001;
                   2720:   GEN eig;
                   2721:
                   2722:   n=lg(mat)-1; a=(double**)gpmalloc(sizeof(double*)*(n+1));
                   2723:   for (i=1; i<=n; i++) a[i]=(double*)gpmalloc(sizeof(double)*(n+1));
                   2724:   for (j=1; j<=n; j++)
                   2725:     for (i=1; i<=n; i++) a[i][j]=gtodouble((GEN)((GEN)mat[j])[i]);
                   2726:   wr=(double*)gpmalloc(sizeof(double)*(n+1));
                   2727:   wi=(double*)gpmalloc(sizeof(double)*(n+1));
                   2728:
                   2729:   anorm=fabs(a[1][1]);
                   2730:   for (i=2; i<=n; i++) for (j=(i-1); j<=n; j++) anorm+=fabs(a[i][j]);
                   2731:   nn=n; t=0.0;
                   2732:   if (DEBUGLEVEL>3) { fprintferr("* Finding eigenvalues\n"); flusherr(); }
                   2733:   while (nn>=1)
                   2734:   {
                   2735:     its=0;
                   2736:     do
                   2737:     {
                   2738:       for (l=nn; l>=2; l--)
                   2739:       {
                   2740:         s=fabs(a[l-1][l-1])+fabs(a[l][l]); if (s==0.0) s=anorm;
                   2741:         if ((double)(fabs(a[l][l-1])+s)==s) break;
                   2742:       }
                   2743:       x=a[nn][nn];
                   2744:       if (l==nn){ wr[nn]=x+t; wi[nn--]=0.0; }
                   2745:       else
                   2746:       {
                   2747:         y=a[nn-1][nn-1];
                   2748:         w=a[nn][nn-1]*a[nn-1][nn];
                   2749:         if (l == nn-1)
                   2750:         {
                   2751:           p=0.5*(y-x); q=p*p+w; z=sqrt(fabs(q)); x+=t;
                   2752:           if (q>=0.0 || fabs(q)<=eps)
                   2753:           {
                   2754:             z=p+SIGN(z,p); wr[nn-1]=wr[nn]=x+z;
                   2755:             if (fabs(z)>eps) wr[nn]=x-w/z;
                   2756:             wi[nn-1]=wi[nn]=0.0;
                   2757:           }
                   2758:           else{ wr[nn-1]=wr[nn]=x+p; wi[nn-1]=-(wi[nn]=z); }
                   2759:           nn-=2;
                   2760:         }
                   2761:         else
                   2762:         {
                   2763:           p = q = r = 0.0; /* for lint */
                   2764:           if (its==30) err(talker,"too many iterations in hqr");
                   2765:           if (its==10 || its==20)
                   2766:           {
                   2767:             t+=x; for (i=1; i<=nn; i++) a[i][i]-=x;
                   2768:             s = fabs(a[nn][nn-1]) + fabs(a[nn-1][nn-2]);
                   2769:             y=x=0.75*s; w=-0.4375*s*s;
                   2770:           }
                   2771:           its++;
                   2772:           for (m=nn-2; m>=l; m--)
                   2773:           {
                   2774:             z=a[m][m]; r=x-z; s=y-z;
                   2775:             p=(r*s-w)/a[m+1][m]+a[m][m+1];
                   2776:             q=a[m+1][m+1]-z-r-s;
                   2777:             r=a[m+2][m+1]; s=fabs(p)+fabs(q)+fabs(r); p/=s; q/=s; r/=s;
                   2778:             if (m==l) break;
                   2779:             u=fabs(a[m][m-1])*(fabs(q)+fabs(r));
                   2780:             v=fabs(p)*(fabs(a[m-1][m-1])+fabs(z)+fabs(a[m+1][m+1]));
                   2781:             if ((double)(u+v)==v) break;
                   2782:           }
                   2783:           for (i=m+2; i<=nn; i++){ a[i][i-2]=0.0; if (i!=(m+2)) a[i][i-3]=0.0; }
                   2784:           for (k=m; k<=nn-1; k++)
                   2785:           {
                   2786:             if (k!=m)
                   2787:             {
                   2788:               p=a[k][k-1]; q=a[k+1][k-1];
                   2789:               r = (k != nn-1)? a[k+2][k-1]: 0.0;
                   2790:               x = fabs(p)+fabs(q)+fabs(r);
                   2791:               if (x != 0.0) { p/=x; q/=x; r/=x; }
                   2792:             }
                   2793:             s = SIGN(sqrt(p*p+q*q+r*r),p);
                   2794:             if (s == 0.0) continue;
                   2795:
                   2796:             if (k==m)
                   2797:               { if (l!=m) a[k][k-1] = -a[k][k-1]; }
                   2798:             else
                   2799:               a[k][k-1] = -s*x;
                   2800:             p+=s; x=p/s; y=q/s; z=r/s; q/=p; r/=p;
                   2801:             for (j=k; j<=nn; j++)
                   2802:             {
                   2803:               p = a[k][j]+q*a[k+1][j];
                   2804:               if (k != nn-1) { p+=r*a[k+2][j]; a[k+2][j]-=p*z; }
                   2805:               a[k+1][j] -= p*y; a[k][j] -= p*x;
                   2806:             }
                   2807:             mmin = (nn < k+3)? nn: k+3;
                   2808:             for (i=l; i<=mmin; i++)
                   2809:             {
                   2810:               p = x*a[i][k]+y*a[i][k+1];
                   2811:               if (k != nn-1) { p+=z*a[i][k+2]; a[i][k+2]-=p*r; }
                   2812:               a[i][k+1] -= p*q; a[i][k] -= p;
                   2813:             }
                   2814:           }
                   2815:         }
                   2816:       }
                   2817:     }
                   2818:     while (l<nn-1);
                   2819:   }
                   2820:   for (j=2; j<=n; j++) /* ordering the roots */
                   2821:   {
                   2822:     x=wr[j]; y=wi[j]; if (y) flj=1; else flj=0;
                   2823:     for (k=j-1; k>=1; k--)
                   2824:     {
                   2825:       if (wi[k]) flk=1; else flk=0;
                   2826:       if (flk<flj) break;
                   2827:       if (!flk && !flj && wr[k]<=x) break;
                   2828:       if (flk&&flj&& wr[k]<x) break;
                   2829:       if (flk&&flj&& wr[k]==x && wi[k]>0) break;
                   2830:       wr[k+1]=wr[k]; wi[k+1]=wi[k];
                   2831:     }
                   2832:     wr[k+1]=x; wi[k+1]=y;
                   2833:   }
                   2834:   if (DEBUGLEVEL>3) { fprintferr("* Eigenvalues computed\n"); flusherr(); }
                   2835:   for (i=1; i<=n; i++) free(a[i]); free(a); eig=cgetg(n+1,t_COL);
                   2836:   for (i=1; i<=n; i++)
                   2837:   {
                   2838:     if (wi[i])
                   2839:     {
                   2840:       GEN p1 = cgetg(3,t_COMPLEX);
                   2841:       eig[i]=(long)p1;
                   2842:       p1[1]=(long)dbltor(wr[i]);
                   2843:       p1[2]=(long)dbltor(wi[i]);
                   2844:     }
                   2845:     else eig[i]=(long)dbltor(wr[i]);
                   2846:   }
                   2847:   free(wr); free(wi); return eig;
                   2848: }
                   2849:
                   2850: /* ONLY FOR POLYNOMIAL WITH REAL COEFFICIENTS : give the roots of the
                   2851:  * polynomial a (first, the real roots, then the non real roots) in
                   2852:  * increasing order of their real parts MULTIPLE ROOTS ARE FORBIDDEN.
                   2853:  */
                   2854: GEN
                   2855: zrhqr(GEN a,long prec)
                   2856: {
                   2857:   ulong av = avma;
                   2858:   long i,j,prec2, n = degpol(a), ex = -bit_accuracy(prec);
                   2859:   GEN aa,b,p1,rt,rr,hess,x,dx,y,newval,oldval;
                   2860:
                   2861:   hess = cgetg(n+1,t_MAT);
                   2862:   for (j=1; j<=n; j++)
                   2863:   {
                   2864:     p1 = cgetg(n+1,t_COL); hess[j] = (long)p1;
                   2865:     p1[1] = lneg(gdiv((GEN)a[n-j+2],(GEN)a[n+2]));
                   2866:     for (i=2; i<=n; i++) p1[i] = (i==(j+1))? un: zero;
                   2867:   }
                   2868:   rt = hqr(balanc(hess));
                   2869:   prec2 = 2*prec; /* polishing the roots */
                   2870:   aa = gprec_w(a, prec2);
                   2871:   b = derivpol(aa); rr = cgetg(n+1,t_COL);
                   2872:   for (i=1; i<=n; i++)
                   2873:   {
                   2874:     x = gprec_w((GEN)rt[i], prec2);
                   2875:     for (oldval=NULL;; oldval=newval, x=y)
                   2876:     { /* Newton iteration */
                   2877:       dx = poleval(b,x);
                   2878:       if (gexpo(dx) < ex)
                   2879:         err(talker,"polynomial has probably multiple roots in zrhqr");
                   2880:       y = gsub(x, gdiv(poleval(aa,x),dx));
                   2881:       newval = gabs(poleval(aa,y),prec2);
                   2882:       if (gexpo(newval) < ex || (oldval && gcmp(newval,oldval) > 0)) break;
                   2883:     }
                   2884:     if (DEBUGLEVEL>3) fprintferr("%ld ",i);
                   2885:     rr[i] = (long)cgetc(prec); gaffect(y, (GEN)rr[i]);
                   2886:   }
                   2887:   if (DEBUGLEVEL>3) { fprintferr("\npolished roots = %Z",rr); flusherr(); }
                   2888:   return gerepilecopy(av, rr);
                   2889: }

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