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

Annotation of OpenXM_contrib/pari-2.2/src/modules/nffactor.c, Revision 1.1.1.1

1.1       noro        1: /* $Id: nffactor.c,v 1.29 2001/10/01 12:11:33 karim Exp $
                      2:
                      3: Copyright (C) 2000  The PARI group.
                      4:
                      5: This file is part of the PARI/GP package.
                      6:
                      7: PARI/GP is free software; you can redistribute it and/or modify it under the
                      8: terms of the GNU General Public License as published by the Free Software
                      9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     10: ANY WARRANTY WHATSOEVER.
                     11:
                     12: Check the License for details. You should have received a copy of it, along
                     13: with the package; see the file 'COPYING'. If not, write to the Free Software
                     14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
                     15:
                     16: /*******************************************************************/
                     17: /*                                                                 */
                     18: /*            POLYNOMIAL FACTORIZATION IN A NUMBER FIELD           */
                     19: /*                                                                 */
                     20: /*******************************************************************/
                     21: #include "pari.h"
                     22: #include "parinf.h"
                     23:
                     24: extern GEN hensel_lift_fact(GEN pol, GEN fact, GEN T, GEN p, GEN pev, long e);
                     25: extern GEN nf_get_T2(GEN base, GEN polr);
                     26: extern GEN nfreducemodpr_i(GEN x, GEN prh);
                     27: extern GEN sort_factor(GEN y, int (*cmp)(GEN,GEN));
                     28: extern GEN pidealprimeinv(GEN nf, GEN x);
                     29:
                     30: static GEN nffactormod2(GEN nf,GEN pol,GEN pr);
                     31: static GEN nfmod_split2(GEN nf, GEN prhall, GEN polb, GEN v, GEN q);
                     32: static GEN nf_pol_mul(GEN nf,GEN pol1,GEN pol2);
                     33: static GEN nf_pol_divres(GEN nf,GEN pol1,GEN pol2, GEN *pr);
                     34: static GEN nf_pol_subres(GEN nf,GEN pol1,GEN pol2);
                     35: static GEN nfmod_pol_reduce(GEN nf,GEN prhall,GEN pol);
                     36: static GEN nfmod_pol_divres(GEN nf,GEN prhall,GEN pol1,GEN pol2, GEN *pr);
                     37: static GEN nfmod_pol_gcd(GEN nf,GEN prhall,GEN pol1,GEN pol2);
                     38: static GEN nf_bestlift(GEN id,GEN idinv,GEN den,GEN elt);
                     39: static GEN nf_pol_lift(GEN id,GEN idinv,GEN den,GEN pol);
                     40: static GEN nfsqff(GEN nf,GEN pol,long fl);
                     41: static int nf_combine_factors(GEN nf,long fxn,GEN psf,long dlim,long hint);
                     42:
                     43: typedef struct Nfcmbf /* for use in nfsqff */
                     44: {
                     45:   GEN pol, h, hinv, fact, res, lt, den;
                     46:   long nfact, nfactmod;
                     47: } Nfcmbf;
                     48: static Nfcmbf nfcmbf;
                     49:
                     50: static GEN
                     51: unifpol0(GEN nf,GEN pol,long flag)
                     52: {
                     53:   static long n = 0;
                     54:   static GEN vun = NULL;
                     55:   GEN f = (GEN) nf[1];
                     56:   long i = degpol(f), av;
                     57:
                     58:   if (i != n)
                     59:   {
                     60:     n=i; if (vun) free(vun);
                     61:     vun = (GEN) gpmalloc((n+1)*sizeof(long));
                     62:     vun[0] = evaltyp(t_COL) | evallg(n+1); vun[1]=un;
                     63:     for ( ; i>=2; i--) vun[i]=zero;
                     64:   }
                     65:
                     66:   av = avma;
                     67:   switch(typ(pol))
                     68:   {
                     69:     case t_INT: case t_FRAC: case t_RFRAC:
                     70:       pol = gmul(pol,vun); break;
                     71:
                     72:     case t_POL:
                     73:       pol = gmodulcp(pol,f); /* fall through */
                     74:     case t_POLMOD:
                     75:       pol = algtobasis(nf,pol);
                     76:   }
                     77:   if (flag) pol = basistoalg(nf, lift(pol));
                     78:   return gerepileupto(av,pol);
                     79: }
                     80:
                     81: /* Let pol be a polynomial with coefficients in Z or nf (vectors or polymods)
                     82:  * return the same polynomial with coefficients expressed:
                     83:  *  if flag=0: as vectors (on the integral basis).
                     84:  *  if flag=1: as polymods.
                     85:  */
                     86: GEN
                     87: unifpol(GEN nf,GEN pol,long flag)
                     88: {
                     89:   if (typ(pol)==t_POL && varn(pol) < varn(nf[1]))
                     90:   {
                     91:     long i, d = lgef(pol);
                     92:     GEN p1 = pol;
                     93:
                     94:     pol=cgetg(d,t_POL); pol[1]=p1[1];
                     95:     for (i=2; i<d; i++)
                     96:       pol[i] = (long) unifpol0(nf,(GEN) p1[i],flag);
                     97:
                     98:     return pol;
                     99:   }
                    100:   return unifpol0(nf,(GEN) pol, flag);
                    101: }
                    102:
                    103: #if 0
                    104: /* return a monic polynomial of degree d with random coefficients in Z_nf */
                    105: static GEN
                    106: random_pol(GEN nf,long d)
                    107: {
                    108:   long i,j, n = degpol(nf[1]);
                    109:   GEN pl,p;
                    110:
                    111:   pl=cgetg(d+3,t_POL);
                    112:   for (i=2; i<d+2; i++)
                    113:   {
                    114:     p=cgetg(n+1,t_COL); pl[i]=(long)p;
                    115:     for (j=1; j<=n; j++)
                    116:       p[j] = lstoi(mymyrand()%101 - 50);
                    117:   }
                    118:   p=cgetg(n+1,t_COL); pl[i]=(long)p;
                    119:   p[1]=un; for (i=2; i<=n; i++) p[i]=zero;
                    120:
                    121:   pl[1] = evalsigne(1) | evallgef(d+3) | evalvarn(0);
                    122:   return pl;
                    123: }
                    124: #endif
                    125:
                    126: /* multiplication of x by y */
                    127: static GEN
                    128: nf_pol_mul(GEN nf,GEN x,GEN y)
                    129: {
                    130:   long tetpil,av=avma;
                    131:   GEN res = gmul(unifpol(nf,x,1), unifpol(nf,y,1));
                    132:
                    133:   tetpil = avma;
                    134:   return gerepile(av,tetpil,unifpol(nf,res,0));
                    135: }
                    136:
                    137: /* compute x^2 in nf */
                    138: static GEN
                    139: nf_pol_sqr(GEN nf,GEN x)
                    140: {
                    141:   long tetpil,av=avma;
                    142:   GEN res = gsqr(unifpol(nf,x,1));
                    143:
                    144:   tetpil = avma;
                    145:   return gerepile(av,tetpil,unifpol(nf,res,0));
                    146: }
                    147:
                    148: /* reduce the coefficients of pol modulo prhall */
                    149: static GEN
                    150: nfmod_pol_reduce(GEN nf,GEN prhall,GEN pol)
                    151: {
                    152:   long av=avma,tetpil,i;
                    153:   GEN p1;
                    154:
                    155:   if (typ(pol)!=t_POL) return nfreducemodpr(nf,pol,prhall);
                    156:   pol=unifpol(nf,pol,0);
                    157:
                    158:   tetpil=avma; i=lgef(pol);
                    159:   p1=cgetg(i,t_POL); p1[1]=pol[1];
                    160:   for (i--; i>=2; i--)
                    161:     p1[i] = (long) nfreducemodpr(nf,(GEN)pol[i],prhall);
                    162:   return gerepile(av,tetpil, normalizepol(p1));
                    163: }
                    164:
                    165: /* x^2 modulo prhall */
                    166: static GEN
                    167: nfmod_pol_sqr(GEN nf,GEN prhall,GEN x)
                    168: {
                    169:   long av=avma,tetpil;
                    170:   GEN px;
                    171:
                    172:   px = nfmod_pol_reduce(nf,prhall,x);
                    173:   px = unifpol(nf,lift(px),1);
                    174:   px = unifpol(nf,nf_pol_sqr(nf,px),0);
                    175:   tetpil=avma;
                    176:   return gerepile(av,tetpil,nfmod_pol_reduce(nf,prhall,px));
                    177: }
                    178:
                    179: /* multiplication of x by y modulo prhall */
                    180: static GEN
                    181: nfmod_pol_mul(GEN nf,GEN prhall,GEN x,GEN y)
                    182: {
                    183:   long av=avma,tetpil;
                    184:   GEN px,py;
                    185:
                    186:   px = nfmod_pol_reduce(nf,prhall,x); px = unifpol(nf,lift(px),1);
                    187:   py = nfmod_pol_reduce(nf,prhall,y); py = unifpol(nf,lift(py),1);
                    188:   px = unifpol(nf,nf_pol_mul(nf,px,py),0);
                    189:   tetpil=avma;
                    190:   return gerepile(av,tetpil,nfmod_pol_reduce(nf,prhall,px));
                    191: }
                    192:
                    193: /* Euclidan division of x by y */
                    194: static GEN
                    195: nf_pol_divres(GEN nf,GEN x,GEN y,GEN *pr)
                    196: {
                    197:   long av = avma,tetpil;
                    198:   GEN nq = poldivres(unifpol(nf,x,1),unifpol(nf,y,1),pr);
                    199:   GEN *gptr[2];
                    200:
                    201:   tetpil=avma; nq=unifpol(nf,nq,0);
                    202:   if (pr) *pr = unifpol(nf,*pr,0);
                    203:   gptr[0]=&nq; gptr[1]=pr;
                    204:   gerepilemanysp(av,tetpil,gptr,pr ? 2:1);
                    205:   return nq;
                    206: }
                    207:
                    208: /* Euclidan division of x by y modulo prhall */
                    209: static GEN
                    210: nfmod_pol_divres(GEN nf,GEN prhall,GEN x,GEN y, GEN *pr)
                    211: {
                    212:   long av=avma,dx,dy,dz,i,j,k,l,n,tetpil;
                    213:   GEN z,p1,p3,px,py;
                    214:
                    215:   py = nfmod_pol_reduce(nf,prhall,y);
                    216:   if (gcmp0(py))
                    217:     err(talker, "division by zero in nfmod_pol_divres");
                    218:
                    219:   tetpil=avma;
                    220:   px=nfmod_pol_reduce(nf,prhall,x);
                    221:   dx=degpol(px); dy=degpol(py); dz=dx-dy;
                    222:   if (dx<dy)
                    223:   {
                    224:     GEN vzero;
                    225:
                    226:     if (pr) *pr = gerepile(av,tetpil,px);
                    227:     else avma = av;
                    228:
                    229:     n=degpol(nf[1]);
                    230:     vzero = cgetg(n+1,t_COL);
                    231:     n=degpol(nf[1]);
                    232:     for (i=1; i<=n; i++) vzero[i]=zero;
                    233:
                    234:     z=cgetg(3,t_POL); z[2]=(long)vzero;
                    235:     z[1]=evallgef(2) | evalvarn(varn(px));
                    236:     return z;
                    237:   }
                    238:   p1 = NULL; /* gcc -Wall */
                    239:
                    240:   z=cgetg(dz+3,t_POL); z[1]=evalsigne(1) | evallgef(3+dz);
                    241:   setvarn(z,varn(px));
                    242:   z[dz+2] = (long) element_divmodpr(nf,(GEN)px[dx+2],(GEN)py[dy+2],prhall);
                    243:   for (i=dx-1; i>=dy; --i)
                    244:   {
                    245:     l=avma; p1=(GEN)px[i+2];
                    246:     for (j=i-dy+1; j<=i && j<=dz; j++)
                    247:       p1 = gsub(p1, element_mul(nf,(GEN)z[j+2],(GEN)py[i-j+2]));
                    248:     p1 = nfreducemodpr(nf,p1,prhall);
                    249:     tetpil=avma; p3=element_divmodpr(nf,p1,(GEN)py[dy+2],prhall);
                    250:     z[i-dy+2]=lpile(l,tetpil,p3);
                    251:     z[i-dy+2]=(long)nfreducemodpr(nf,(GEN)z[i-dy+2],prhall);
                    252:   }
                    253:   l=avma;
                    254:   for (i=dy-1; i>=0; --i)
                    255:   {
                    256:     l=avma; p1=((GEN)px[i+2]);
                    257:     for (j=0; j<=i && j<=dz; j++)
                    258:       p1 = gsub(p1, element_mul(nf,(GEN)z[j+2],(GEN)py[i-j+2]));
                    259:     p1 = gerepileupto(l, nfreducemodpr(nf,p1,prhall));
                    260:     if (!gcmp0(p1)) break;
                    261:   }
                    262:
                    263:   if (!pr) { avma = l; return z; }
                    264:
                    265:   if (i<0)
                    266:   {
                    267:     avma=l;
                    268:     p3 = cgetg(3,t_POL); p3[2]=zero;
                    269:     p3[1] = evallgef(2) | evalvarn(varn(px));
                    270:     *pr=p3; return z;
                    271:   }
                    272:
                    273:   p3=cgetg(i+3,t_POL);
                    274:   p3[1]=evalsigne(1) | evallgef(i+3) | evalvarn(varn(px));
                    275:   p3[i+2]=(long)nfreducemodpr(nf,p1,prhall);
                    276:   for (k=i-1; k>=0; --k)
                    277:   {
                    278:     l=avma; p1=((GEN)px[k+2]);
                    279:     for (j=0; j<=k && j<=dz; j++)
                    280:       p1 = gsub(p1, element_mul(nf,(GEN)z[j+2],(GEN)py[k-j+2]));
                    281:     p3[k+2]=lpileupto(l,nfreducemodpr(nf,p1,prhall));
                    282:   }
                    283:   *pr=p3; return z;
                    284: }
                    285:
                    286: /* GCD of x and y */
                    287: static GEN
                    288: nf_pol_subres(GEN nf,GEN x,GEN y)
                    289: {
                    290:   long av=avma,tetpil;
                    291:   GEN s = srgcd(unifpol(nf,x,1), unifpol(nf,y,1));
                    292:
                    293:   tetpil=avma; return gerepile(av,tetpil,unifpol(nf,s,1));
                    294: }
                    295:
                    296: /* GCD of x and y modulo prhall */
                    297: static GEN
                    298: nfmod_pol_gcd(GEN nf,GEN prhall,GEN x,GEN y)
                    299: {
                    300:   long av=avma;
                    301:   GEN p1,p2;
                    302:
                    303:   if (lgef(x)<lgef(y)) { p1=y; y=x; x=p1; }
                    304:   p1=nfmod_pol_reduce(nf,prhall,x);
                    305:   p2=nfmod_pol_reduce(nf,prhall,y);
                    306:   while (!isexactzero(p2))
                    307:   {
                    308:     GEN p3;
                    309:
                    310:     nfmod_pol_divres(nf,prhall,p1,p2,&p3);
                    311:     p1=p2; p2=p3;
                    312:   }
                    313:   return gerepileupto(av,p1);
                    314: }
                    315:
                    316: /* return pol^e modulo prhall and the polynomial pmod */
                    317: static GEN
                    318: nfmod_pol_pow(GEN nf,GEN prhall,GEN pmod,GEN pol,GEN e)
                    319: {
                    320:   long i, av = avma, n = degpol(nf[1]);
                    321:   GEN p1,p2,vun;
                    322:
                    323:   vun=cgetg(n+1,t_COL); vun[1]=un; for (i=2; i<=n; i++) vun[i]=zero;
                    324:   p1=gcopy(polun[varn(pol)]); p1[2]=(long)vun;
                    325:   if (gcmp0(e)) return p1;
                    326:
                    327:   p2=nfmod_pol_reduce(nf,prhall,pol);
                    328:   for(;;)
                    329:   {
                    330:     if (!vali(e))
                    331:     {
                    332:       p1=nfmod_pol_mul(nf,prhall,p1,p2);
                    333:       nfmod_pol_divres(nf,prhall,p1,pmod,&p1);
                    334:     }
                    335:     if (gcmp1(e)) break;
                    336:
                    337:     e=shifti(e,-1);
                    338:     p2=nfmod_pol_sqr(nf,prhall,p2);
                    339:     nfmod_pol_divres(nf,prhall,p2,pmod,&p2);
                    340:   }
                    341:   return gerepileupto(av,p1);
                    342: }
                    343:
                    344: static long
                    345: isdivbyprime(GEN nf, GEN x, GEN pr)
                    346: {
                    347:   GEN elt, p = (GEN)pr[1], tau = (GEN)pr[5];
                    348:
                    349:   elt = element_mul(nf, x, tau);
                    350:   if (divise(content(elt), p)) return 1;
                    351:
                    352:   return 0;
                    353: }
                    354:
                    355: /* return the factor of nf.pol modulo p corresponding to pr */
                    356: static GEN
                    357: localpol(GEN nf, GEN pr)
                    358: {
                    359:   long i, l;
                    360:   GEN fct, pol = (GEN)nf[1], p = (GEN)pr[1];
                    361:
                    362:   fct = lift((GEN)factmod(pol, p)[1]);
                    363:   l = lg(fct) - 1;
                    364:   for (i = 1; i <= l; i++)
                    365:     if (isdivbyprime(nf, (GEN)fct[i], pr)) return (GEN)fct[i];
                    366:
                    367:   err(talker, "cannot find a suitable factor in localpol");
                    368:   return NULL; /* not reached */
                    369: }
                    370:
                    371: /* factorization of x modulo pr */
                    372: static GEN
                    373: nffactormod0(GEN nf, GEN x, GEN pr)
                    374: {
                    375:   long av = avma, j, l, vx = varn(x), vn;
                    376:   GEN rep, pol, xrd, prh, p1;
                    377:
                    378:   nf=checknf(nf);
                    379:   vn = varn((GEN)nf[1]);
                    380:   if (typ(x)!=t_POL) err(typeer,"nffactormod");
                    381:   if (vx >= vn)
                    382:     err(talker,"polynomial variable must have highest priority in nffactormod");
                    383:
                    384:   prh = nfmodprinit(nf, pr);
                    385:
                    386:   if (divise((GEN)nf[4], (GEN)pr[1]))
                    387:     return gerepileupto(av, nffactormod2(nf,x,pr));
                    388:
                    389:   xrd = nfmod_pol_reduce(nf, prh, x);
                    390:   if (gcmp1((GEN)pr[4]))
                    391:   {
                    392:     pol = gun; /* dummy */
                    393:     for (j = 2; j < lg(xrd); j++)
                    394:       xrd[j] = mael(xrd, j, 1);
                    395:     rep = factmod(xrd, (GEN)pr[1]);
                    396:     rep = lift(rep);
                    397:   }
                    398:   else
                    399:   {
                    400:     pol = localpol(nf, pr);
                    401:     xrd = lift(unifpol(nf, xrd, 1));
                    402:     p1  = gun;
                    403:     for (j = 2; j < lg(xrd); j++)
                    404:     {
                    405:       xrd[j] = lmod((GEN)xrd[j], pol);
                    406:       p1 = mpppcm(p1, denom(content((GEN)xrd[j])));
                    407:     }
                    408:     rep = factmod9(gmul(xrd, p1), (GEN)pr[1], pol);
                    409:     rep = lift(lift(rep));
                    410:   }
                    411:
                    412:   l = lg((GEN)rep[1]);
                    413:   for (j = 1; j < l; j++)
                    414:     mael(rep, 1, j) = (long)unifpol(nf, gmael(rep, 1, j), 1);
                    415:
                    416:   return gerepilecopy(av, rep);
                    417: }
                    418:
                    419: GEN
                    420: nffactormod(GEN nf, GEN x, GEN pr)
                    421: {
                    422:   return nffactormod0(nf, x, pr);
                    423: }
                    424:
                    425: extern GEN trivfact(void);
                    426:
                    427: /* factorization of x modulo pr */
                    428: GEN
                    429: nffactormod2(GEN nf,GEN pol,GEN pr)
                    430: {
                    431:   long av = avma, tetpil,lb,nbfact,psim,N,n,i,j,k,d,e,vf,r,kk;
                    432:   GEN y,ex,*t,f1,f2,f3,df1,g1,polb,pold,polu,vker;
                    433:   GEN Q,f,x,u,v,v2,v3,vz,q,vun,vzero,prhall;
                    434:
                    435:   nf=checknf(nf);
                    436:   if (typ(pol)!=t_POL) err(typeer,"nffactormod");
                    437:   if (varn(pol) >= varn(nf[1]))
                    438:     err(talker,"polynomial variable must have highest priority in nffactormod");
                    439:
                    440:   prhall=nfmodprinit(nf,pr); n=degpol(nf[1]);
                    441:   vun = gscalcol_i(gun, n);
                    442:   vzero = gscalcol_i(gzero, n);
                    443:   q = vker = NULL; /* gcc -Wall */
                    444:
                    445:   f=unifpol(nf,pol,0); f=nfmod_pol_reduce(nf,prhall,f);
                    446:   if (!signe(f)) err(zeropoler,"nffactormod");
                    447:   d=degpol(f); vf=varn(f);
                    448:   if (d == 0) return trivfact();
                    449:   t  = (GEN*)new_chunk(d+1); ex = cgetg(d+1, t_VECSMALL);
                    450:   x=gcopy(polx[vf]); x[3]=(long)vun; x[2]=(long)vzero;
                    451:   if (d<=1) { nbfact=2; t[1] = f; ex[1]=1; }
                    452:   else
                    453:   {
                    454:     q = (GEN)pr[1]; psim = VERYBIGINT;
                    455:     if (!is_bigint(q)) psim = itos(q);
                    456:    /* psim has an effect only when p is small. If too big, set it to a huge
                    457:     * number (i.e ignore it) to avoid an error in itos on next line.
                    458:     */
                    459:     q=gpuigs(q, itos((GEN)pr[4]));
                    460:     f1=f; e=1; nbfact=1;
                    461:     while (lgef(f1)>3)
                    462:     {
                    463:       df1=deriv(f1,vf); f2=nfmod_pol_gcd(nf,prhall,f1,df1);
                    464:       g1=nfmod_pol_divres(nf,prhall,f1,f2,NULL); k=0;
                    465:       while (lgef(g1)>3)
                    466:       {
                    467:        k++;
                    468:        if (k%psim == 0)
                    469:        {
                    470:          k++; f2=nfmod_pol_divres(nf,prhall,f2,g1,NULL);
                    471:        }
                    472:        f3=nfmod_pol_gcd(nf,prhall,f2,g1);
                    473:        u = nfmod_pol_divres(nf,prhall,g1,f3,NULL);
                    474:        f2= nfmod_pol_divres(nf,prhall,f2,f3,NULL);
                    475:        g1=f3;
                    476:        if (lgef(u)>3)
                    477:        {
                    478:          N=degpol(u); Q=cgetg(N+1,t_MAT);
                    479:          v3=cgetg(N+1,t_COL); Q[1]=(long)v3;
                    480:          v3[1]=(long)vun; for (i=2; i<=N; i++) v3[i]=(long)vzero;
                    481:
                    482:          v2 = v = nfmod_pol_pow(nf,prhall,u,x,q);
                    483:          for (j=2; j<=N; j++)
                    484:          {
                    485:            v3=cgetg(N+1,t_COL); Q[j]=(long)v3;
                    486:            for (i=1; i<=lgef(v2)-2; i++) v3[i]=v2[i+1];
                    487:            for (; i<=N; i++) v3[i]=(long)vzero;
                    488:            if (j<N)
                    489:            {
                    490:              v2=nfmod_pol_mul(nf,prhall,v2,v);
                    491:              nfmod_pol_divres(nf,prhall,v2,u,&v2);
                    492:            }
                    493:          }
                    494:          for (i=1; i<=N; i++)
                    495:            coeff(Q,i,i)=lsub((GEN)coeff(Q,i,i),vun);
                    496:          v2=nfkermodpr(nf,Q,prhall); r=lg(v2)-1; t[nbfact]=gcopy(u); kk=1;
                    497:          if (r>1)
                    498:          {
                    499:            vker=cgetg(r+1,t_COL);
                    500:            for (i=1; i<=r; i++)
                    501:            {
                    502:              v3=cgetg(N+2,t_POL);
                    503:              v3[1]=evalsigne(1)+evallgef(2+N); setvarn(v3,vf);
                    504:              vker[i]=(long)v3; for (j=1; j<=N; j++) v3[j+1]=coeff(v2,j,i);
                    505:              normalizepol(v3);
                    506:            }
                    507:          }
                    508:          while (kk<r)
                    509:          {
                    510:            v=gcopy(polun[vf]); v[2]=(long)vzero;
                    511:            for (i=1; i<=r; i++)
                    512:            {
                    513:              vz=cgetg(n+1,t_COL);
                    514:              for (j=1; j<=n; j++)
                    515:                vz[j] = lmodsi(mymyrand()>>8, q);
                    516:              vz=nfreducemodpr(nf,vz,prhall);
                    517:              v=gadd(v,nfmod_pol_mul(nf,prhall,vz,(GEN)vker[i]));
                    518:            }
                    519:            for (i=1; i<=kk && kk<r; i++)
                    520:            {
                    521:              polb=t[nbfact+i-1]; lb=lgef(polb);
                    522:              if (lb>4)
                    523:              {
                    524:                if(psim==2)
                    525:                  polu=nfmod_split2(nf,prhall,polb,v,q);
                    526:                else
                    527:                {
                    528:                  polu=nfmod_pol_pow(nf,prhall,polb,v,shifti(q,-1));
                    529:                   polu=gsub(polu,vun);
                    530:                }
                    531:                 pold=nfmod_pol_gcd(nf,prhall,polb,polu);
                    532:                if (lgef(pold)>3 && lgef(pold)<lb)
                    533:                {
                    534:                  t[nbfact+i-1]=pold; kk++;
                    535:                  t[nbfact+kk-1]=nfmod_pol_divres(nf,prhall,polb,pold,NULL);
                    536:                }
                    537:              }
                    538:            }
                    539:          }
                    540:          for (i=nbfact; i<nbfact+r; i++) ex[i]=e*k;
                    541:          nbfact+=r;
                    542:        }
                    543:       }
                    544:       e*=psim; j=(degpol(f2))/psim+3; f1=cgetg(j,t_POL);
                    545:       f1[1] = evalsigne(1) | evallgef(j) | evalvarn(vf);
                    546:       for (i=2; i<j; i++)
                    547:        f1[i]=(long)element_powmodpr(nf,(GEN)f2[psim*(i-2)+2],
                    548:                                     gdiv(q,(GEN)pr[1]),prhall);
                    549:     }
                    550:   }
                    551:   if (nbfact < 2)
                    552:     err(talker, "%Z not a prime (nffactormod)", q);
                    553:   for (j=1; j<nbfact; j++)
                    554:   {
                    555:     v = element_divmodpr(nf,vun,gmael(t,j,lgef(t[j])-1),prhall);
                    556:     t[j] = unifpol(nf,nfmod_pol_mul(nf,prhall,v,(GEN)t[j]),1);
                    557:   }
                    558:
                    559:   tetpil=avma; y=cgetg(3,t_MAT);
                    560:   u=cgetg(nbfact,t_COL); y[1]=(long)u;
                    561:   v=cgetg(nbfact,t_COL); y[2]=(long)v;
                    562:   for (j=1,k=0; j<nbfact; j++)
                    563:     if (ex[j])
                    564:     {
                    565:       k++;
                    566:       u[k]=lcopy((GEN)t[j]);
                    567:       v[k]=lstoi(ex[j]);
                    568:     }
                    569:   return gerepile(av,tetpil,y);
                    570: }
                    571:
                    572: /* return pol + pol^2 + ... + pol^(q/2) modulo prhall and
                    573:    the polynomial pmod */
                    574: static GEN
                    575: nfmod_split2(GEN nf,GEN prhall,GEN pmod,GEN pol,GEN exp)
                    576: {
                    577:   long av = avma;
                    578:   GEN p1,p2,q;
                    579:
                    580:   if (cmpis(exp,2)<=0) return pol;
                    581:   p2=p1=pol; q=shifti(exp,-1);
                    582:   while (!gcmp1(q))
                    583:   {
                    584:     p2=nfmod_pol_sqr(nf,prhall,p2);
                    585:     nfmod_pol_divres(nf,prhall,p2,pmod,&p2);
                    586:     q=shifti(q,-1); p1=gadd(p1,p2);
                    587:   }
                    588:   return gerepileupto(av,p1);
                    589: }
                    590:
                    591: /* If p doesn't divide either a or b and has a divisor of degree 1, return it.
                    592:  * Return NULL otherwise.
                    593:  */
                    594: static GEN
                    595: p_ok(GEN nf, GEN p, GEN a)
                    596: {
                    597:   long av,m,i;
                    598:   GEN dec;
                    599:
                    600:   if (divise(a,p)) return NULL;
                    601:   av = avma; dec = primedec(nf,p); m=lg(dec);
                    602:   for (i=1; i<m; i++)
                    603:   {
                    604:     GEN pr = (GEN)dec[i];
                    605:     if (is_pm1(pr[4]))
                    606:       return pr;
                    607:   }
                    608:   avma = av; return NULL;
                    609: }
                    610:
                    611: /* for each new prime ct--, if ct = 0, return NULL */
                    612: static GEN
                    613: choose_prime(GEN nf, GEN dk, GEN lim, long ct)
                    614: {
                    615:   GEN p, pr;
                    616:
                    617:   p = nextprime(lim);
                    618:   for (;;)
                    619:   {
                    620:     if ((pr = p_ok(nf,p,dk))) break;
                    621:     ct--;
                    622:     if (!ct) return NULL;
                    623:     p = nextprime(addis(p,2));
                    624:   }
                    625:
                    626:   return pr;
                    627: }
                    628:
                    629: /* test if the discriminant of polbase modulo some few primes
                    630:    is non-zero. Return 1 if it is so (=> polbase is square-free)
                    631:    and 0 otherwise (=> polbase may or may not be square-free) */
                    632: static int
                    633: is_sqf(GEN nf, GEN polbase)
                    634: {
                    635:   GEN lt, pr, prh, p2, p;
                    636:   long i, d = lgef(polbase), ct = 5;
                    637:
                    638:   lt = (GEN)leading_term(polbase)[1];
                    639:   p  = stoi(101);
                    640:
                    641:   while (ct > 0)
                    642:   {
                    643:     /* small primes tend to divide discriminants more often
                    644:        than large ones so we look at primes >= 101 */
                    645:     pr = choose_prime(nf,lt,p,30);
                    646:     if (!pr) break;
                    647:
                    648:     p=(GEN)pr[1];
                    649:     prh=prime_to_ideal(nf,pr);
                    650:
                    651:     p2=gcopy(polbase);
                    652:     lt=mpinvmod(lt,p);
                    653:
                    654:     for (i=2; i<d; i++)
                    655:       p2[i] = nfreducemodpr_i(gmul(lt,(GEN)p2[i]), prh)[1];
                    656:     p2 = normalizepol(p2);
                    657:
                    658:     /* discriminant is non-zero => polynomial is square-free */
                    659:     if (!gcmp0(p2) && !divise(discsr(p2),p))  { return 1; }
                    660:
                    661:     ct--;
                    662:     p=addis(p,1);
                    663:   }
                    664:
                    665:   return 0;
                    666: }
                    667:
                    668: /* rescale p in K[X] (coeffs in algtobasis form) --> primitive in O_K[X] */
                    669: GEN
                    670: nf_pol_to_int(GEN p, GEN *den)
                    671: {
                    672:   long i, l = lgef(p);
                    673:   GEN d = gun;
                    674:   for (i=2; i<l; i++)
                    675:     d = mpppcm(d,denom((GEN)p[i]));
                    676:   if (! gcmp1(d)) p = gmul(p, d);
                    677:   *den = d; return p;
                    678: }
                    679:
                    680: /* return the roots of pol in nf */
                    681: GEN
                    682: nfroots(GEN nf,GEN pol)
                    683: {
                    684:   long av=avma,tetpil,d=lgef(pol),fl;
                    685:   GEN p1,p2,polbase,polmod,den;
                    686:
                    687:   p2=NULL; /* gcc -Wall */
                    688:   nf=checknf(nf);
                    689:   if (typ(pol)!=t_POL) err(talker,"not a polynomial in nfroots");
                    690:   if (varn(pol) >= varn(nf[1]))
                    691:     err(talker,"polynomial variable must have highest priority in nfroots");
                    692:
                    693:   polbase=unifpol(nf,pol,0);
                    694:
                    695:   if (d==3)
                    696:   {
                    697:     tetpil=avma; p1=cgetg(1,t_VEC);
                    698:     return gerepile(av,tetpil,p1);
                    699:   }
                    700:
                    701:   if (d==4)
                    702:   {
                    703:     tetpil=avma; p1=cgetg(2,t_VEC);
                    704:     p1[1] = (long)basistoalg(nf,gneg_i(
                    705:       element_div(nf,(GEN)polbase[2],(GEN)polbase[3])));
                    706:     return gerepile(av,tetpil,p1);
                    707:   }
                    708:
                    709:   p1=element_inv(nf,leading_term(polbase));
                    710:   polbase=nf_pol_mul(nf,p1,polbase);
                    711:
                    712:   polbase = nf_pol_to_int(polbase, &den);
                    713:   polmod=unifpol(nf,polbase,1);
                    714:
                    715:   if (DEBUGLEVEL>=4)
                    716:     fprintferr("test if the polynomial is square-free\n");
                    717:
                    718:   fl = is_sqf(nf, polbase);
                    719:
                    720:   /* the polynomial may not be square-free ... */
                    721:   if (!fl)
                    722:   {
                    723:     p1=derivpol(polmod);
                    724:     p2=nf_pol_subres(nf,polmod,p1);
                    725:     if (degpol(p2) == 0) fl = 1;
                    726:   }
                    727:
                    728:   if (!fl)
                    729:   {
                    730:     p1=element_inv(nf,leading_term(p2));
                    731:     p2=nf_pol_mul(nf,p1,p2);
                    732:     polmod=nf_pol_divres(nf,polmod,p2,NULL);
                    733:
                    734:     p1=element_inv(nf,leading_term(polmod));
                    735:     polmod=nf_pol_mul(nf,p1,polmod);
                    736:
                    737:     polmod = nf_pol_to_int(polmod, &den);
                    738:     polmod=unifpol(nf,polmod,1);
                    739:   }
                    740:
                    741:   p1 = nfsqff(nf,polmod,1);
                    742:   tetpil=avma; return gerepile(av, tetpil, gen_sort(p1, 0, cmp_pol));
                    743: }
                    744:
                    745: /* return a minimal lift of elt modulo id */
                    746: static GEN
                    747: nf_bestlift(GEN id,GEN idinv,GEN den,GEN elt)
                    748: {
                    749:   GEN u = gmul(idinv,elt);
                    750:   long i, l = lg(u);
                    751:   for (i=1; i<l; i++) u[i] = (long)gdivround((GEN)u[i], den);
                    752:   return gsub(elt, gmul(id, u));
                    753: }
                    754:
                    755: /* return the lift of pol with coefficients of T2-norm <= C (if possible) */
                    756: static GEN
                    757: nf_pol_lift(GEN id,GEN idinv,GEN den,GEN pol)
                    758: {
                    759:   long i, d = lgef(pol);
                    760:   GEN x = cgetg(d,t_POL);
                    761:   x[1] = pol[1];
                    762:   for (i=2; i<d; i++)
                    763:     x[i] = (long) nf_bestlift(id,idinv,den,(GEN)pol[i]);
                    764:   return x;
                    765: }
                    766:
                    767: #if 0
                    768: /* return pol(elt) */
                    769: static GEN
                    770: nf_pol_eval(GEN nf,GEN pol,GEN elt)
                    771: {
                    772:   long av=avma,tetpil,i;
                    773:   GEN p1;
                    774:
                    775:   i=lgef(pol)-1; if (i==2) return gcopy((GEN)pol[2]);
                    776:
                    777:   p1=element_mul(nf,(GEN)pol[i],elt);
                    778:   for (i--; i>=3; i--)
                    779:     p1=element_mul(nf,elt,gadd((GEN)pol[i],p1));
                    780:   tetpil=avma; return gerepile(av,tetpil,gadd(p1,(GEN)pol[2]));
                    781: }
                    782: #endif
                    783:
                    784: /* return the factorization of x in nf */
                    785: GEN
                    786: nffactor(GEN nf,GEN pol)
                    787: {
                    788:   GEN y,p1,p2,den,p3,p4,quot,rep=cgetg(3,t_MAT);
                    789:   long av = avma,tetpil,i,j,d,fl;
                    790:
                    791:   if (DEBUGLEVEL >= 4) timer2();
                    792:
                    793:   p3=NULL; /* gcc -Wall */
                    794:   nf=checknf(nf);
                    795:   if (typ(pol)!=t_POL) err(typeer,"nffactor");
                    796:   if (varn(pol) >= varn(nf[1]))
                    797:     err(talker,"polynomial variable must have highest priority in nffactor");
                    798:
                    799:   d=lgef(pol);
                    800:   if (d==3)
                    801:   {
                    802:     rep[1]=lgetg(1,t_COL);
                    803:     rep[2]=lgetg(1,t_COL);
                    804:     return rep;
                    805:   }
                    806:   if (d==4)
                    807:   {
                    808:     p1=cgetg(2,t_COL); rep[1]=(long)p1; p1[1]=lcopy(pol);
                    809:     p1=cgetg(2,t_COL); rep[2]=(long)p1; p1[1]=un;
                    810:     return rep;
                    811:   }
                    812:
                    813:   p1=element_inv(nf,leading_term(pol));
                    814:   pol=nf_pol_mul(nf,p1,pol);
                    815:
                    816:   p1=unifpol(nf,pol,0);
                    817:   p1 = nf_pol_to_int(p1, &den);
                    818:
                    819:   if (DEBUGLEVEL>=4)
                    820:     fprintferr("test if the polynomial is square-free\n");
                    821:
                    822:   fl = is_sqf(nf, p1);
                    823:
                    824:   /* polynomial may not be square-free ... */
                    825:   if (!fl)
                    826:   {
                    827:     p2=derivpol(p1);
                    828:     p3=nf_pol_subres(nf,p1,p2);
                    829:     if (degpol(p3) == 0) fl = 1;
                    830:   }
                    831:
                    832:   if (!fl)
                    833:   {
                    834:     p4=element_inv(nf,leading_term(p3));
                    835:     p3=nf_pol_mul(nf,p4,p3);
                    836:
                    837:     p2=nf_pol_divres(nf,p1,p3,NULL);
                    838:     p4=element_inv(nf,leading_term(p2));
                    839:     p2=nf_pol_mul(nf,p4,p2);
                    840:
                    841:     p2 = nf_pol_to_int(p2, &den);
                    842:
                    843:     p2=unifpol(nf,p2,1);
                    844:     tetpil = avma; y = nfsqff(nf,p2,0);
                    845:     i = nfcmbf.nfact;
                    846:
                    847:     quot=nf_pol_divres(nf,p1,p2,NULL);
                    848:     p3=(GEN)gpmalloc((i+1) * sizeof(long));
                    849:     for (j=i; j>=1; j--)
                    850:     {
                    851:       GEN fact=(GEN)y[j], quo = quot, rem;
                    852:       long e = 0;
                    853:
                    854:       do
                    855:       {
                    856:        quo = nf_pol_divres(nf,quo,fact,&rem);
                    857:        e++;
                    858:       }
                    859:       while (gcmp0(rem));
                    860:       p3[j]=lstoi(e);
                    861:     }
                    862:     avma = (long)y; y = gerepile(av, tetpil, y);
                    863:     p2=cgetg(i+1, t_COL); for (; i>=1; i--) p2[i]=lcopy((GEN)p3[i]);
                    864:     free(p3);
                    865:   }
                    866:   else
                    867:   {
                    868:     tetpil=avma; y = gerepile(av,tetpil,nfsqff(nf,p1,0));
                    869:     i = nfcmbf.nfact;
                    870:     p2=cgetg(i+1, t_COL); for (; i>=1; i--) p2[i]=un;
                    871:   }
                    872:   if (DEBUGLEVEL>=4)
                    873:     fprintferr("number of factor(s) found: %ld\n", nfcmbf.nfact);
                    874:   rep[1]=(long)y;
                    875:   rep[2]=(long)p2; return sort_factor(rep, cmp_pol);
                    876: }
                    877:
                    878: /* test if the matrix M is suitable */
                    879: static long
                    880: test_mat(GEN M, GEN p, GEN C2, long k)
                    881: {
                    882:   long av = avma, i, N = lg(M);
                    883:   GEN min, prod, L2, R;
                    884:
                    885:   min = prod = gcoeff(M,1,1);
                    886:   for (i = 2; i < N; i++)
                    887:   {
                    888:     L2 = gcoeff(M,i,i); prod = mpmul(prod,L2);
                    889:     if (mpcmp(L2,min) < 0) min = L2;
                    890:   }
                    891:   R = mpmul(min, gpowgs(p, k<<1));
                    892:   i = mpcmp(mpmul(C2,prod), R); avma = av;
                    893:   return (i < 0);
                    894: }
                    895:
                    896: /* return the matrix corresponding to pr^e with R(pr^e) > C */
                    897: static GEN
                    898: T2_matrix_pow(GEN nf, GEN pre, GEN p, GEN C, long *kmax, long prec)
                    899: {
                    900:   long av=avma,av1,lim, k = *kmax, N = degpol((GEN)nf[1]);
                    901:   int tot_real = !signe(gmael(nf,2,2));
                    902:   GEN p1,p2,p3,u,C2,T2, x = (GEN)nf[1];
                    903:
                    904:   C2 = gdiv(gmul2n(C,2), absi((GEN)nf[3]));
                    905:   p1 = gmul(pre,lllintpartial(pre)); av1 = avma;
                    906:   T2 = tot_real? gmael(nf,5,4)
                    907:                : nf_get_T2((GEN) nf[7], roots(x,prec));
                    908:   p3 = qf_base_change(T2,p1,1);
                    909:
                    910:   if (N <= 6 && test_mat(p3,p,C2,k))
                    911:   {
                    912:     avma = av1; return gerepileupto(av,p1);
                    913:   }
                    914:
                    915:   av1=avma; lim = stack_lim(av1,2);
                    916:   for (;;)
                    917:   {
                    918:     if (DEBUGLEVEL>2) fprintferr("exponent: %ld\n",k);
                    919:
                    920:     for(;;)
                    921:     {
                    922:       u = tot_real? lllgramall(p3,2,lll_IM) : lllgramintern(p3,2,1,prec);
                    923:       if (u) break;
                    924:
                    925:       prec=(prec<<1)-2;
                    926:       if (DEBUGLEVEL > 1) err(warnprec,"nffactor[1]",prec);
                    927:       T2 = nf_get_T2((GEN) nf[7], roots(x,prec));
                    928:       p3 = qf_base_change(T2,p1,1);
                    929:     }
                    930:     if (DEBUGLEVEL>2) msgtimer("lllgram + base change");
                    931:     p3 = qf_base_change(p3,u,1);
                    932:     if (test_mat(p3,p,C2,k))
                    933:     {
                    934:       *kmax = k;
                    935:       return gerepileupto(av,gmul(p1,u));
                    936:     }
                    937:
                    938:     /* we also need to increase the precision */
                    939:     p2=shifti(gceil(mulsr(k, glog(p,DEFAULTPREC))),-1);
                    940:     prec += (long)(itos(p2)*pariK1);
                    941:     if (DEBUGLEVEL > 1) err(warnprec,"nffactor[2]",prec);
                    942:     k = k<<1; p1 = idealmullll(nf,p1,p1);
                    943:     if (low_stack(lim, stack_lim(av1,2)))
                    944:     {
                    945:       if (DEBUGMEM>1) err(warnmem,"T2_matrix_pow");
                    946:       p1 = gerepileupto(av1,p1);
                    947:     }
                    948:     if (!tot_real) T2 = nf_get_T2((GEN) nf[7], roots(x,prec));
                    949:     p3 = qf_base_change(T2,p1,1);
                    950:   }
                    951: }
                    952:
                    953: /* return the factorization of the square-free polynomial x.
                    954:    The coeff of x are in Z_nf and its leading term is a rational
                    955:    integer. If fl = 1,return only the roots of x in nf */
                    956: static GEN
                    957: nfsqff(GEN nf,GEN pol, long fl)
                    958: {
                    959:   long d=lgef(pol),i,k,m,n,av=avma,tetpil,newprec,prec,nbf=BIGINT,anbf,ct=5;
                    960:   GEN p1,pr,p2,rep,k2,C,h,dk,dki,p,prh,p3,T2,polbase,fact,pk,ap,apr;
                    961:   GEN polmod,polred,hinv,lt,minp,den,maxp=shifti(gun,32),run,aprh;
                    962:
                    963:   if (DEBUGLEVEL>=4) msgtimer("square-free");
                    964:
                    965:   dk=absi((GEN)nf[3]);
                    966:   dki=mulii(dk,(GEN)nf[4]);
                    967:   n=degpol(nf[1]);
                    968:
                    969:   polbase = unifpol(nf,pol,0);
                    970:   polmod  = unifpol(nf,pol,1);
                    971:   dki=mulii(dki,gnorm((GEN)polmod[d-1]));
                    972:
                    973:   prec = DEFAULTPREC;
                    974:   for (;;)
                    975:   {
                    976:     if (prec <= gprecision(nf))
                    977:       T2 = gprec_w(gmael(nf,5,3), prec);
                    978:     else
                    979:       T2 = nf_get_T2((GEN)nf[7], roots((GEN)nf[1], prec));
                    980:
                    981:     run=realun(prec);
                    982:     p1=realzero(prec);
                    983:     for (i=2; i<d; i++)
                    984:     {
                    985:       p2 = gmul(run, (GEN)polbase[i]);
                    986:       p2 = qfeval(T2, p2);
                    987:       p1 = addrr(p1, gdiv(p2, binome(stoi(d), i-2)));
                    988:       if (signe(p1) < 0) break;
                    989:     }
                    990:
                    991:     if (signe(p1) > 0) break;
                    992:
                    993:     prec = (prec<<1)-2;
                    994:     if (DEBUGLEVEL > 1) err(warnprec, "nfsqff", prec);
                    995:   }
                    996:
                    997:   lt = (GEN)leading_term(polbase)[1];
                    998:   p1 = gmul(p1, mulis(sqri(lt), n));
                    999:   C = gpow(stoi(3), gadd(gmulsg(3, ghalf), stoi(d)), prec);
                   1000:   C = gdiv(gmul(C, p1), gmulsg(d, mppi(prec)));
                   1001:
                   1002:   if (DEBUGLEVEL>=4)
                   1003:     fprintferr("the bound on the T2-norm of the coeff. is: %Z\n", C);
                   1004:
                   1005:   /* the theoretical bound for the exponent should be:
                   1006:      k2=gadd(glog(gdivgs(C,n),DEFAULTPREC), mulsr(n*(n-1), dbltor(0.347))); */
                   1007:   k2=gadd(glog(gdivgs(C,n),DEFAULTPREC), mulsr(n*(n-1), dbltor(0.15)));
                   1008:   k2=gmul2n(gmulgs(k2,n),-1);
                   1009:
                   1010:   minp=gmin(gexp(gmul2n(k2,-6),BIGDEFAULTPREC), maxp);
                   1011:   minp=gceil(minp);
                   1012:
                   1013:   if (DEBUGLEVEL>=4)
                   1014:   {
                   1015:     fprintferr("lower bound for the prime numbers: %Z\n", minp);
                   1016:     msgtimer("bounds computation");
                   1017:   }
                   1018:
                   1019:   p = rep = polred = NULL; /* gcc -Wall */
                   1020:   pr=NULL;
                   1021:   for (;;)
                   1022:   {
                   1023:     apr = choose_prime(nf,dki,minp, pr?30:0);
                   1024:     if (!apr) break;
                   1025:
                   1026:     ap=(GEN)apr[1];
                   1027:     aprh=prime_to_ideal(nf,apr);
                   1028:
                   1029:     polred=gcopy(polbase);
                   1030:     lt=(GEN)leading_term(polbase)[1];
                   1031:     lt=mpinvmod(lt,ap);
                   1032:
                   1033:     for (i=2; i<d; i++)
                   1034:       polred[i] = nfreducemodpr_i(gmul(lt,(GEN)polbase[i]), aprh)[1];
                   1035:
                   1036:     if (!divise(discsr(polred),ap))
                   1037:     {
                   1038:       rep=(GEN)simplefactmod(polred,ap)[1];
                   1039:       anbf=lg(rep)-1;
                   1040:       ct--;
                   1041:       if (anbf < nbf)
                   1042:       {
                   1043:        nbf=anbf;
                   1044:        pr=gcopy(apr);
                   1045:        p=gcopy(ap);
                   1046:        if (DEBUGLEVEL>=4)
                   1047:        {
                   1048:          fprintferr("prime ideal considered: %Z\n", pr);
                   1049:          fprintferr("number of irreducible factors: %ld\n", nbf);
                   1050:        }
                   1051:        if (nbf == 1) break;
                   1052:       }
                   1053:     }
                   1054:     if (pr && !ct) break;
                   1055:
                   1056:     minp = addis(ap,1);
                   1057:   }
                   1058:
                   1059:   k = itos(gceil(gdiv(k2,glog(p,BIGDEFAULTPREC))));
                   1060:
                   1061:   if (DEBUGLEVEL>=4)
                   1062:   {
                   1063:     fprintferr("prime ideal chosen: %Z\n", pr);
                   1064:     msgtimer("choice of the prime ideal");
                   1065:   }
                   1066:
                   1067:   if (lg(rep)==2)
                   1068:   {
                   1069:     if (fl) { avma=av; return cgetg(1,t_VEC); }
                   1070:     rep=cgetg(2,t_VEC); rep[1]=lcopy(polmod);
                   1071:     nfcmbf.nfact=1; return gerepileupto(av, rep);
                   1072:   }
                   1073:
                   1074:   p2=cgetr(DEFAULTPREC);
                   1075:   affir(mulii(absi(dk),gpowgs(p,k)),p2);
                   1076:   p2=shifti(gceil(mplog(p2)),-1);
                   1077:
                   1078:   newprec = MEDDEFAULTPREC + (long)(itos(p2)*pariK1);
                   1079:   if (DEBUGLEVEL>=4)
                   1080:     fprintferr("new precision: %ld\n",newprec);
                   1081:
                   1082:   prh = idealpows(nf,pr,k); m = k;
                   1083:   h = T2_matrix_pow(nf,prh,p,C, &k, newprec);
                   1084:   if (m != k) prh=idealpows(nf,pr,k);
                   1085:
                   1086:   if (DEBUGLEVEL>=4)
                   1087:   {
                   1088:     fprintferr("a suitable exponent is: %ld\n",(long)k);
                   1089:     msgtimer("computation of H");
                   1090:   }
                   1091:
                   1092:   pk = gcoeff(prh,1,1);
                   1093:   lt=(GEN)leading_term(polbase)[1];
                   1094:   lt=mpinvmod(lt,pk);
                   1095:
                   1096:   polred[1] = polbase[1];
                   1097:   for (i=2; i<d; i++)
                   1098:     polred[i] = nfreducemodpr_i(gmul(lt,(GEN)polbase[i]), prh)[1];
                   1099:
                   1100:   fact = lift_intern((GEN)factmod(polred,p)[1]);
                   1101:   rep = hensel_lift_fact(polred,fact,NULL,p,pk,k);
                   1102:
                   1103:   if (DEBUGLEVEL >= 4) msgtimer("computation of the p-adic factorization");
                   1104:
                   1105:   den = det(h); /* |den| = NP^k */
                   1106:   hinv= adj(h);
                   1107:   lt=(GEN)leading_term(polbase)[1];
                   1108:
                   1109:   if (fl)
                   1110:   {
                   1111:     long x_a[] = { evaltyp(t_POL)|m_evallg(4), 0,0,0 };
                   1112:     GEN mlt = gneg_i(lt), rem;
                   1113:     x_a[1] = polbase[1]; setlgef(x_a, 4);
                   1114:     x_a[3] = un;
                   1115:     p1=cgetg(lg(rep)+1,t_VEC);
                   1116:     polbase = unifpol(nf,polbase,1);
                   1117:     for (m=1,i=1; i<lg(rep); i++)
                   1118:     {
                   1119:       p2=(GEN)rep[i]; if (lgef(p2)!=4) break;
                   1120:
                   1121:       p3 = algtobasis(nf, gmul(mlt,(GEN)p2[2]));
                   1122:       p3 = nf_bestlift(h,hinv,den,p3);
                   1123:       p3 = gdiv(p3,lt);
                   1124:       x_a[2] = lneg(p3); /* check P(p3) == 0 */
                   1125:       p2 = poldivres(polbase, unifpol(nf,x_a,1), &rem);
                   1126:       if (!signe(rem)) { polbase = p2; p1[m++] = (long)p3; }
                   1127:     }
                   1128:     tetpil=avma; rep=cgetg(m,t_VEC);
                   1129:     for (i=1; i<m; i++) rep[i]=(long)basistoalg(nf,(GEN)p1[i]);
                   1130:     return gerepile(av,tetpil,rep);
                   1131:   }
                   1132:
                   1133:   for (i=1; i<lg(rep); i++)
                   1134:     rep[i] = (long)unifpol(nf,(GEN)rep[i],0);
                   1135:
                   1136:   nfcmbf.pol      = polmod;
                   1137:   nfcmbf.lt       = lt;
                   1138:   nfcmbf.h        = h;
                   1139:   nfcmbf.hinv     = hinv;
                   1140:   nfcmbf.den      = den;
                   1141:   nfcmbf.fact     = rep;
                   1142:   nfcmbf.res      = cgetg(lg(rep)+1,t_VEC);
                   1143:   nfcmbf.nfact    = 0;
                   1144:   nfcmbf.nfactmod = lg(rep)-1;
                   1145:   nf_combine_factors(nf,1,NULL,d-3,1);
                   1146:
                   1147:   if (DEBUGLEVEL >= 4) msgtimer("computation of the factors");
                   1148:
                   1149:   i = nfcmbf.nfact;
                   1150:   if (lgef(nfcmbf.pol)>3)
                   1151:   {
                   1152:     nfcmbf.res[++i] = (long) nf_pol_divres(nf,nfcmbf.pol,nfcmbf.lt,NULL);
                   1153:     nfcmbf.nfact = i;
                   1154:   }
                   1155:
                   1156:   tetpil=avma; rep=cgetg(i+1,t_VEC);
                   1157:   for (  ; i>=1; i--)
                   1158:     rep[i]=(long)unifpol(nf,(GEN)nfcmbf.res[i],1);
                   1159:   return gerepile(av,tetpil,rep);
                   1160: }
                   1161:
                   1162: static int
                   1163: nf_combine_factors(GEN nf,long fxn,GEN psf,long dlim,long hint)
                   1164: {
                   1165:   int val = 0; /* assume failure */
                   1166:   GEN newf, newpsf = NULL;
                   1167:   long av,newd,ltop,i;
                   1168:
                   1169:   /* Assertion: fxn <= nfcmbf.nfactmod && dlim > 0 */
                   1170:
                   1171:   /* first, try deeper factors without considering the current one */
                   1172:   if (fxn != nfcmbf.nfactmod)
                   1173:   {
                   1174:     val = nf_combine_factors(nf,fxn+1,psf,dlim,hint);
                   1175:     if (val && psf) return 1;
                   1176:   }
                   1177:
                   1178:   /* second, try including the current modular factor in the product */
                   1179:   newf = (GEN)nfcmbf.fact[fxn];
                   1180:   if (!newf) return val; /* modular factor already used */
                   1181:   newd = degpol(newf);
                   1182:   if (newd > dlim) return val; /* degree of new factor is too large */
                   1183:
                   1184:   av = avma;
                   1185:   if (newd % hint == 0)
                   1186:   {
                   1187:     GEN p, quot,rem;
                   1188:
                   1189:     newpsf = nf_pol_mul(nf, psf? psf: nfcmbf.lt, newf);
                   1190:     newpsf = nf_pol_lift(nfcmbf.h,nfcmbf.hinv,nfcmbf.den,newpsf);
                   1191:     /* try out the new combination */
                   1192:     ltop=avma;
                   1193:     quot=nf_pol_divres(nf,nfcmbf.pol,newpsf,&rem);
                   1194:     if (gcmp0(rem))  /* found a factor */
                   1195:     {
                   1196:       p = nf_pol_mul(nf,element_inv(nf,leading_term(newpsf)),newpsf);
                   1197:       nfcmbf.res[++nfcmbf.nfact] = (long) p; /* store factor */
                   1198:       nfcmbf.fact[fxn]=0;                    /* remove used modular factor */
                   1199:
                   1200:       /* fix up target */
                   1201:       p=gun; quot=unifpol(nf,quot,0);
                   1202:       for (i=2; i<lgef(quot); i++)
                   1203:         p = mpppcm(p, denom((GEN)quot[i]));
                   1204:
                   1205:       nfcmbf.pol = nf_pol_mul(nf,p,quot);
                   1206:       nfcmbf.lt  = leading_term(nfcmbf.pol);
                   1207:       return 1;
                   1208:     }
                   1209:     avma=ltop;
                   1210:   }
                   1211:
                   1212:   /* If room in degree limit + more modular factors to try, add more factors to
                   1213:    * newpsf */
                   1214:   if (newd < dlim && fxn < nfcmbf.nfactmod
                   1215:                   && nf_combine_factors(nf,fxn+1,newpsf,dlim-newd,hint))
                   1216:   {
                   1217:     nfcmbf.fact[fxn]=0; /* remove used modular factor */
                   1218:     return 1;
                   1219:   }
                   1220:   avma = av; return val;
                   1221: }
                   1222:
                   1223: /* return the characteristic polynomial of alpha over nf, where alpha
                   1224:    is an element of the algebra nf[X]/(T) given as a polynomial in X */
                   1225: GEN
                   1226: rnfcharpoly(GEN nf,GEN T,GEN alpha,int v)
                   1227: {
                   1228:   long av = avma, vnf, vT, lT;
                   1229:   GEN p1;
                   1230:
                   1231:   nf=checknf(nf); vnf = varn(nf[1]);
                   1232:   if (v<0) v = 0;
                   1233:   T = fix_relative_pol(nf,T,1);
                   1234:   if (typ(alpha) == t_POLMOD) alpha = lift_to_pol(alpha);
                   1235:   lT = lgef(T);
                   1236:   if (typ(alpha) != t_POL || varn(alpha) == vnf)
                   1237:     return gerepileupto(av, gpowgs(gsub(polx[v], alpha), lT - 3));
                   1238:   vT = varn(T);
                   1239:   if (varn(alpha) != vT || v >= vnf)
                   1240:     err(talker,"incorrect variables in rnfcharpoly");
                   1241:   if (lgef(alpha) >= lT) alpha = gmod(alpha,T);
                   1242:   if (lT <= 4)
                   1243:     return gerepileupto(av, gsub(polx[v], alpha));
                   1244:   p1 = caract2(unifpol(nf,T,1), unifpol(nf,alpha,1), v);
                   1245:   return gerepileupto(av, unifpol(nf,p1,1));
                   1246: }
                   1247:
                   1248: #if 0
                   1249: /* return the minimal polynomial of alpha over nf, where alpha is
                   1250:    an element of the algebra nf[X]/(T) given as a polynomial in X */
                   1251: GEN
                   1252: rnfminpoly(GEN nf,GEN T,GEN alpha,int n)
                   1253: {
                   1254:   long av=avma,tetpil;
                   1255:   GEN p1,p2;
                   1256:
                   1257:   nf=checknf(nf); p1=rnfcharpoly(nf,T,alpha,n);
                   1258:   tetpil=avma; p2=nf_pol_subres(nf,p1,deriv(p1,varn(T)));
                   1259:   if (lgef(p2)==3) { avma=tetpil; return p1; }
                   1260:
                   1261:   p1 = nf_pol_divres(nf,p1,p2,NULL);
                   1262:   p2 = element_inv(nf,leading_term(p1));
                   1263:   tetpil=avma; return gerepile(av,tetpil,unifpol(nf,nf_pol_mul(nf,p2,p1),1));
                   1264: }
                   1265: #endif
                   1266:
                   1267: /* relative Dedekind criterion over nf, applied to the order defined by a
                   1268:  * root of irreducible polynomial T, modulo the prime ideal pr. Returns
                   1269:  * [flag,basis,val], where basis is a pseudo-basis of the enlarged order,
                   1270:  * flag is 1 iff this order is pr-maximal, and val is the valuation in pr of
                   1271:  * the order discriminant
                   1272:  */
                   1273: GEN
                   1274: rnfdedekind(GEN nf,GEN T,GEN pr)
                   1275: {
                   1276:   long av=avma,vt,r,d,da,n,m,i,j;
                   1277:   GEN p1,p2,p,tau,g,vecun,veczero,matid;
                   1278:   GEN prhall,res,h,k,base,Ca;
                   1279:
                   1280:   nf=checknf(nf); Ca=unifpol(nf,T,0);
                   1281:   res=cgetg(4,t_VEC);
                   1282:   if (typ(pr)==t_VEC && lg(pr)==3)
                   1283:   { prhall = (GEN)pr[2]; pr = (GEN)pr[1]; }
                   1284:   else
                   1285:     prhall=nfmodprinit(nf,pr);
                   1286:   p=(GEN)pr[1]; tau=gdiv((GEN)pr[5],p);
                   1287:   n=degpol(nf[1]); m=degpol(T);
                   1288:
                   1289:   vecun = gscalcol_i(gun,n);
                   1290:   veczero = zerocol(n);
                   1291:
                   1292:   p1=(GEN)nffactormod(nf,Ca,pr)[1];
                   1293:   r=lg(p1); if (r < 2) err(constpoler,"rnfdedekind");
                   1294:   g=lift((GEN)p1[1]);
                   1295:   for (i=2; i<r; i++)
                   1296:     g = nf_pol_mul(nf,g, lift((GEN)p1[i]));
                   1297:   h=nfmod_pol_divres(nf,prhall,Ca,g,NULL);
                   1298:   k=nf_pol_mul(nf,tau,gsub(Ca, nf_pol_mul(nf,lift(g),lift(h))));
                   1299:   p2=nfmod_pol_gcd(nf,prhall,g,h);
                   1300:   k= nfmod_pol_gcd(nf,prhall,p2,k);
                   1301:
                   1302:   d=degpol(k);  /* <= m */
                   1303:   vt = idealval(nf,discsr(T),pr) - 2*d;
                   1304:   res[3]=lstoi(vt);
                   1305:   if (!d || vt<=1) res[1]=un; else res[1]=zero;
                   1306:
                   1307:   base=cgetg(3,t_VEC);
                   1308:   p1=cgetg(m+d+1,t_MAT); base[1]=(long)p1;
                   1309:   p2=cgetg(m+d+1,t_VEC); base[2]=(long)p2;
                   1310:  /* if d > 0, base[2] temporarily multiplied by p, for the final nfhermitemod
                   1311:   * [ which requires integral ideals ] */
                   1312:   matid = gscalmat(d? p: gun, n);
                   1313:   for (j=1; j<=m; j++)
                   1314:   {
                   1315:     p2[j]=(long)matid;
                   1316:     p1[j]=lgetg(m+1,t_COL);
                   1317:     for (i=1; i<=m; i++)
                   1318:       coeff(p1,i,j) = (i==j)?(long)vecun:(long)veczero;
                   1319:   }
                   1320:   if (d)
                   1321:   {
                   1322:     GEN pal = lift(nfmod_pol_divres(nf,prhall,Ca,k,NULL));
                   1323:     GEN prinvp = pidealprimeinv(nf,pr); /* again multiplied by p */
                   1324:     GEN nfx = unifpol(nf,polx[varn(T)],0);
                   1325:
                   1326:     for (   ; j<=m+d; j++)
                   1327:     {
                   1328:       p1[j]=lgetg(m+1,t_COL);
                   1329:       da=degpol(pal);
                   1330:       for (i=1; i<=da+1; i++) coeff(p1,i,j)=pal[i+1];
                   1331:       for (   ; i<=m; i++) coeff(p1,i,j)=(long)veczero;
                   1332:       p2[j]=(long)prinvp;
                   1333:       nf_pol_divres(nf,nf_pol_mul(nf,pal,nfx),T,&pal);
                   1334:     }
                   1335:     /* the modulus is integral */
                   1336:     base = nfhermitemod(nf,base, gmul(gpowgs(p, m-d),
                   1337:                                      idealpows(nf, prinvp, d)));
                   1338:     base[2] = ldiv((GEN)base[2], p); /* cancel the factor p */
                   1339:   }
                   1340:   res[2]=(long)base; return gerepilecopy(av, res);
                   1341: }

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