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

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

1.1       maekawa     1: /*******************************************************************/
                      2: /*                                                                 */
                      3: /*             Factorisation dans un corps de nombres              */
                      4: /*                  et modulo un ideal premier                     */
                      5: /*                                                                 */
                      6: /*******************************************************************/
                      7: /* $Id: nffactor.c,v 1.5 1999/09/23 18:48:42 xavier Exp $ */
                      8: #include "pari.h"
                      9:
                     10: GEN hensel_lift(GEN pol,GEN fk,GEN fkk,GEN p,long e);
                     11: GEN hensel_lift_fact(GEN pol, GEN fact, GEN p, GEN pev, long e);
                     12: GEN nf_get_T2(GEN base, GEN polr);
                     13: GEN nfreducemodpr_i(GEN x, GEN prh);
                     14: GEN sort_factor(GEN y, int (*cmp)(GEN,GEN));
                     15:
                     16: static GEN nf_pol_mul(GEN nf,GEN pol1,GEN pol2);
                     17: static GEN nf_pol_sqr(GEN nf,GEN pol1);
                     18: static GEN nf_pol_divres(GEN nf,GEN pol1,GEN pol2, GEN *pr);
                     19: static GEN nf_pol_subres(GEN nf,GEN pol1,GEN pol2);
                     20: static GEN nfmod_pol_reduce(GEN nf,GEN prhall,GEN pol);
                     21: static GEN nfmod_pol_mul(GEN nf,GEN prhall,GEN pol1,GEN pol2);
                     22: static GEN nfmod_pol_sqr(GEN nf,GEN prhall,GEN pol1);
                     23: static GEN nfmod_pol_divres(GEN nf,GEN prhall,GEN pol1,GEN pol2, GEN *pr);
                     24: static GEN nfmod_split2(GEN nf,GEN prhall,GEN pmod,GEN pol,GEN exp);
                     25: static GEN nfmod_pol_gcd(GEN nf,GEN prhall,GEN pol1,GEN pol2);
                     26: static GEN nfmod_pol_pow(GEN nf,GEN prhall,GEN pmod,GEN pol,GEN exp);
                     27: static GEN nf_bestlift(GEN id,GEN idinv,GEN den,GEN elt);
                     28: static GEN nf_pol_lift(GEN id,GEN idinv,GEN den,GEN pol);
                     29: static GEN nfsqff(GEN nf,GEN pol,long fl);
                     30: static int nf_combine_factors(GEN nf,long fxn,GEN psf,long dlim,long hint);
                     31:
                     32: typedef struct Nfcmbf /* for use in nfsqff */
                     33: {
                     34:   GEN pol, h, hinv, fact, res, lt, den;
                     35:   long nfact, nfactmod;
                     36: } Nfcmbf;
                     37: static Nfcmbf nfcmbf;
                     38:
                     39: static GEN
                     40: unifpol0(GEN nf,GEN pol,long flag)
                     41: {
                     42:   static long n = 0;
                     43:   static GEN vun = NULL;
                     44:   GEN f = (GEN) nf[1];
                     45:   long i = lgef(f)-3, av;
                     46:
                     47:   if (i != n)
                     48:   {
                     49:     n=i; if (vun) free(vun);
                     50:     vun = (GEN) gpmalloc((n+1)*sizeof(long));
                     51:     vun[0] = evaltyp(t_COL) | evallg(n+1); vun[1]=un;
                     52:     for ( ; i>=2; i--) vun[i]=zero;
                     53:   }
                     54:
                     55:   av = avma;
                     56:   switch(typ(pol))
                     57:   {
                     58:     case t_INT: case t_FRAC: case t_RFRAC:
                     59:       pol = gmul(pol,vun); break;
                     60:
                     61:     case t_POL:
                     62:       pol = gmodulcp(pol,f); /* fall through */
                     63:     case t_POLMOD:
                     64:       pol = algtobasis(nf,pol);
                     65:   }
                     66:   if (flag) pol = basistoalg(nf, lift(pol));
                     67:   return gerepileupto(av,pol);
                     68: }
                     69:
                     70: /* Pour pol un polynome a coefficients dans Z, nf ou l'algebre correspondant
                     71:  * renvoie le meme polynome avec pour coefficients:
                     72:  *  si flag=0: des vecteurs sur la base d'entiers.
                     73:  *  si flag=1: des polymods.
                     74:  */
                     75: GEN
                     76: unifpol(GEN nf,GEN pol,long flag)
                     77: {
                     78:   if (typ(pol)==t_POL && varn(pol) < varn(nf[1]))
                     79:   {
                     80:     long i, d = lgef(pol);
                     81:     GEN p1 = pol;
                     82:
                     83:     pol=cgetg(d,t_POL); pol[1]=p1[1];
                     84:     for (i=2; i<d; i++)
                     85:       pol[i] = (long) unifpol0(nf,(GEN) p1[i],flag);
                     86:
                     87:     return pol;
                     88:   }
                     89:   return unifpol0(nf,(GEN) pol, flag);
                     90: }
                     91:
                     92: /* cree un polynome unitaire de degre d a entrees au hazard dans Z_nf */
                     93: GEN
                     94: random_pol(GEN nf,long d)
                     95: {
                     96:   long i,j, n = lgef(nf[1])-3;
                     97:   GEN pl,p;
                     98:
                     99:   pl=cgetg(d+3,t_POL);
                    100:   for (i=2; i<d+2; i++)
                    101:   {
                    102:     p=cgetg(n+1,t_COL); pl[i]=(long)p;
                    103:     for (j=1; j<=n; j++)
                    104:       p[j] = lstoi(mymyrand()%101 - 50);
                    105:   }
                    106:   p=cgetg(n+1,t_COL); pl[i]=(long)p;
                    107:   p[1]=un; for (i=2; i<=n; i++) p[i]=zero;
                    108:
                    109:   pl[1] = evalsigne(1) | evallgef(d+3) | evalvarn(0);
                    110:   return pl;
                    111: }
                    112:
                    113: /* multiplication de x par y dans nf (x element accepte) */
                    114: static GEN
                    115: nf_pol_mul(GEN nf,GEN x,GEN y)
                    116: {
                    117:   long tetpil,av=avma;
                    118:   GEN res = gmul(unifpol(nf,x,1), unifpol(nf,y,1));
                    119:
                    120:   tetpil = avma;
                    121:   return gerepile(av,tetpil,unifpol(nf,res,0));
                    122: }
                    123:
                    124: /* calcule x^2 dans nf (x element accepte) */
                    125: static GEN
                    126: nf_pol_sqr(GEN nf,GEN x)
                    127: {
                    128:   long tetpil,av=avma;
                    129:   GEN res = gsqr(unifpol(nf,x,1));
                    130:
                    131:   tetpil = avma;
                    132:   return gerepile(av,tetpil,unifpol(nf,res,0));
                    133: }
                    134:
                    135: /* Reduction modulo phall des coefficients de pol (pol element accepte) */
                    136: static GEN
                    137: nfmod_pol_reduce(GEN nf,GEN prhall,GEN pol)
                    138: {
                    139:   long av=avma,tetpil,i;
                    140:   GEN p1;
                    141:
                    142:   if (typ(pol)!=t_POL) return nfreducemodpr(nf,pol,prhall);
                    143:   pol=unifpol(nf,pol,0);
                    144:
                    145:   tetpil=avma; i=lgef(pol);
                    146:   p1=cgetg(i,t_POL); p1[1]=pol[1];
                    147:   for (i--; i>=2; i--)
                    148:     p1[i] = (long) nfreducemodpr(nf,(GEN)pol[i],prhall);
                    149:   return gerepile(av,tetpil, normalizepol(p1));
                    150: }
                    151:
                    152: /* x^2 modulo prhall ds nf (x elt accepte) */
                    153: static GEN
                    154: nfmod_pol_sqr(GEN nf,GEN prhall,GEN x)
                    155: {
                    156:   long av=avma,tetpil;
                    157:   GEN px;
                    158:
                    159:   px = nfmod_pol_reduce(nf,prhall,x);
                    160:   px = unifpol(nf,lift(px),1);
                    161:   px = unifpol(nf,nf_pol_sqr(nf,px),0);
                    162:   tetpil=avma;
                    163:   return gerepile(av,tetpil,nfmod_pol_reduce(nf,prhall,px));
                    164: }
                    165:
                    166: /* multiplication des polynomes x et y modulo prhall ds nf (x elt accepte) */
                    167: static GEN
                    168: nfmod_pol_mul(GEN nf,GEN prhall,GEN x,GEN y)
                    169: {
                    170:   long av=avma,tetpil;
                    171:   GEN px,py;
                    172:
                    173:   px = nfmod_pol_reduce(nf,prhall,x); px = unifpol(nf,lift(px),1);
                    174:   py = nfmod_pol_reduce(nf,prhall,y); py = unifpol(nf,lift(py),1);
                    175:   px = unifpol(nf,nf_pol_mul(nf,px,py),0);
                    176:   tetpil=avma;
                    177:   return gerepile(av,tetpil,nfmod_pol_reduce(nf,prhall,px));
                    178: }
                    179:
                    180: /* division euclidienne du polynome x par le polynome y */
                    181: static GEN
                    182: nf_pol_divres(GEN nf,GEN x,GEN y,GEN *pr)
                    183: {
                    184:   long av = avma,tetpil;
                    185:   GEN nq = poldivres(unifpol(nf,x,1),unifpol(nf,y,1),pr);
                    186:   GEN *gptr[2];
                    187:
                    188:   tetpil=avma; nq=unifpol(nf,nq,0);
                    189:   if (pr) *pr = unifpol(nf,*pr,0);
                    190:   gptr[0]=&nq; gptr[1]=pr;
                    191:   gerepilemanysp(av,tetpil,gptr,pr ? 2:1);
                    192:   return nq;
                    193: }
                    194:
                    195: /* division euclidienne du polynome x par le polynome y modulo prhall */
                    196: static GEN
                    197: nfmod_pol_divres(GEN nf,GEN prhall,GEN x,GEN y, GEN *pr)
                    198: {
                    199:   long av=avma,dx,dy,dz,i,j,k,l,n,tetpil;
                    200:   GEN z,p1,p2,p3,px,py;
                    201:
                    202:   py = nfmod_pol_reduce(nf,prhall,y);
                    203:   if (gcmp0(py))
                    204:     err(talker, "division by zero in nfmod_pol_divres");
                    205:
                    206:   tetpil=avma;
                    207:   px=nfmod_pol_reduce(nf,prhall,x);
                    208:   dx=lgef(px)-3; dy=lgef(py)-3; dz=dx-dy;
                    209:   if (dx<dy)
                    210:   {
                    211:     GEN vzero;
                    212:
                    213:     if (pr) *pr = gerepile(av,tetpil,px);
                    214:     else avma = av;
                    215:
                    216:     n=lgef(nf[1])-3;
                    217:     vzero = cgetg(n+1,t_COL);
                    218:     n=lgef(nf[1])-3;
                    219:     for (i=1; i<=n; i++) vzero[i]=zero;
                    220:
                    221:     z=cgetg(3,t_POL); z[2]=(long)vzero;
                    222:     z[1]=evallgef(2) | evalvarn(varn(px));
                    223:     return z;
                    224:   }
                    225:
                    226:   z=cgetg(dz+3,t_POL); z[1]=evalsigne(1) | evallgef(3+dz);
                    227:   setvarn(z,varn(px));
                    228:   z[dz+2] = (long) element_divmodpr(nf,(GEN)px[dx+2],(GEN)py[dy+2],prhall);
                    229:   for (i=dx-1; i>=dy; --i)
                    230:   {
                    231:     l=avma; p1=nfreducemodpr(nf,(GEN)px[i+2],prhall);
                    232:     for (j=i-dy+1; j<=i && j<=dz; j++)
                    233:     {
                    234:       p2=element_mul(nf,(GEN)z[j+2],(GEN)py[i-j+2]);
                    235:       p2=nfreducemodpr(nf,p2,prhall); p1=gsub(p1,p2);
                    236:     }
                    237:     tetpil=avma; p3=element_divmodpr(nf,p1,(GEN)py[dy+2],prhall);
                    238:     z[i-dy+2]=lpile(l,tetpil,p3);
                    239:     z[i-dy+2]=(long)nfreducemodpr(nf,(GEN)z[i-dy+2],prhall);
                    240:   }
                    241:   l=avma;
                    242:   for (i=dy-1; i>=0; --i)
                    243:   {
                    244:     l=avma; p1=((GEN)px[i+2]);
                    245:     for (j=0; j<=i && j<=dz; j++)
                    246:     {
                    247:       p2=element_mul(nf,(GEN)z[j+2],(GEN)py[i-j+2]);
                    248:       p2=nfreducemodpr(nf,p2,prhall); tetpil=avma; p1=gsub(p1,p2);
                    249:     }
                    250:     p1=gerepile(l,tetpil,p1);
                    251:     if (!gcmp0(nfreducemodpr(nf,p1,prhall))) break;
                    252:   }
                    253:
                    254:   if (!pr) { avma = l; return z; }
                    255:
                    256:   if (i<0)
                    257:   {
                    258:     avma=l;
                    259:     p3 = cgetg(3,t_POL); p3[2]=zero;
                    260:     p3[1] = evallgef(2) | evalvarn(varn(px));
                    261:     *pr=p3; return z;
                    262:   }
                    263:
                    264:   p3=cgetg(i+3,t_POL);
                    265:   p3[1]=evalsigne(1) | evallgef(i+3) | evalvarn(varn(px));
                    266:   p3[i+2]=(long)nfreducemodpr(nf,p1,prhall);
                    267:   for (k=i-1; k>=0; --k)
                    268:   {
                    269:     l=avma; p1=((GEN)px[k+2]);
                    270:     for (j=0; j<=k && j<=dz; j++)
                    271:     {
                    272:       p2=element_mul(nf,(GEN)z[j+2],(GEN)py[k-j+2]);
                    273:       p2=nfreducemodpr(nf,p2,prhall); tetpil=avma; p1=gsub(p1,p2);
                    274:     }
                    275:     p3[k+2]=lpile(l,tetpil,nfreducemodpr(nf,p1,prhall));
                    276:   }
                    277:   *pr=p3; return z;
                    278: }
                    279:
                    280: /* PGCD des polynomes x et y, par l'algorithme du sub-resultant */
                    281: static GEN
                    282: nf_pol_subres(GEN nf,GEN x,GEN y)
                    283: {
                    284:   long av=avma,tetpil;
                    285:   GEN s = srgcd(unifpol(nf,x,1), unifpol(nf,y,1));
                    286:
                    287:   tetpil=avma; return gerepile(av,tetpil,unifpol(nf,s,1));
                    288: }
                    289:
                    290: /* PGCD des polynomes x et y modulo prhall */
                    291: static GEN
                    292: nfmod_pol_gcd(GEN nf,GEN prhall,GEN x,GEN y)
                    293: {
                    294:   long av=avma;
                    295:   GEN p1,p2;
                    296:
                    297:   if (lgef(x)<lgef(y)) { p1=y; y=x; x=p1; }
                    298:   p1=nfmod_pol_reduce(nf,prhall,x);
                    299:   p2=nfmod_pol_reduce(nf,prhall,y);
                    300:   while (!isexactzero(p2))
                    301:   {
                    302:     GEN p3;
                    303:
                    304:     nfmod_pol_divres(nf,prhall,p1,p2,&p3);
                    305:     p1=p2; p2=p3;
                    306:   }
                    307:   return gerepileupto(av,p1);
                    308: }
                    309:
                    310: /* Calcul pol^e modulo prhall et le polynome pmod */
                    311: static GEN
                    312: nfmod_pol_pow(GEN nf,GEN prhall,GEN pmod,GEN pol,GEN e)
                    313: {
                    314:   long i, av = avma, n = lgef(nf[1])-3;
                    315:   GEN p1,p2,vun;
                    316:
                    317:   vun=cgetg(n+1,t_COL); vun[1]=un; for (i=2; i<=n; i++) vun[i]=zero;
                    318:   p1=gcopy(polun[varn(pol)]); p1[2]=(long)vun;
                    319:   if (gcmp0(e)) return p1;
                    320:
                    321:   p2=nfmod_pol_reduce(nf,prhall,pol);
                    322:   for(;;)
                    323:   {
                    324:     if (!vali(e))
                    325:     {
                    326:       p1=nfmod_pol_mul(nf,prhall,p1,p2);
                    327:       nfmod_pol_divres(nf,prhall,p1,pmod,&p1);
                    328:     }
                    329:     if (gcmp1(e)) break;
                    330:
                    331:     e=shifti(e,-1);
                    332:     p2=nfmod_pol_sqr(nf,prhall,p2);
                    333:     nfmod_pol_divres(nf,prhall,p2,pmod,&p2);
                    334:   }
                    335:   return gerepileupto(av,p1);
                    336: }
                    337:
                    338: /* factorisation du polynome x modulo pr */
                    339: GEN
                    340: nffactormod(GEN nf,GEN pol,GEN pr)
                    341: {
                    342:   long av = avma, tetpil,lb,nbfact,psim,N,n,i,j,k,d,e,vf,r,kk;
                    343:   GEN y,ex,*t,f1,f2,f3,df1,g1,polb,pold,polu,vker;
                    344:   GEN Q,f,x,u,v,v2,v3,vz,q,vun,vzero,prhall;
                    345:
                    346:   nf=checknf(nf);
                    347:   if (typ(pol)!=t_POL) err(typeer,"nffactormod");
                    348:   if (varn(pol) >= varn(nf[1]))
                    349:     err(talker,"polynomial variable must have highest priority in nffactormod");
                    350:
                    351:   prhall=nfmodprinit(nf,pr); n=lgef(nf[1])-3;
                    352:   vun = gscalcol_i(gun, n);
                    353:   vzero = gscalcol_i(gzero, n);
                    354:
                    355:   f=unifpol(nf,pol,0); f=nfmod_pol_reduce(nf,prhall,f);
                    356:   d=lgef(f)-3; vf=varn(f);
                    357:   t = (GEN*)new_chunk(d+1);
                    358:   ex= new_chunk(d+1);
                    359:   x=gcopy(polx[vf]); x[3]=(long)vun; x[2]=(long)vzero;
                    360:   if (d<=1) { nbfact=2; t[1] = f; ex[1]=1; }
                    361:   else
                    362:   {
                    363:     q = (GEN)pr[1]; psim = VERYBIGINT;
                    364:     if (!is_bigint(q)) psim = itos(q);
                    365:    /* psim has an effect only when p is small. If too big, set it to a huge
                    366:     * number (i.e ignore it) to avoid an error in itos on next line.
                    367:     */
                    368:     q=gpuigs(q, itos((GEN)pr[4]));
                    369:     f1=f; e=1; nbfact=1;
                    370:     while (lgef(f1)>3)
                    371:     {
                    372:       df1=deriv(f1,vf); f2=nfmod_pol_gcd(nf,prhall,f1,df1);
                    373:       g1=nfmod_pol_divres(nf,prhall,f1,f2,NULL); k=0;
                    374:       while (lgef(g1)>3)
                    375:       {
                    376:        k++;
                    377:        if (k%psim == 0)
                    378:        {
                    379:          k++; f2=nfmod_pol_divres(nf,prhall,f2,g1,NULL);
                    380:        }
                    381:        f3=nfmod_pol_gcd(nf,prhall,f2,g1);
                    382:        u = nfmod_pol_divres(nf,prhall,g1,f3,NULL);
                    383:        f2= nfmod_pol_divres(nf,prhall,f2,f3,NULL);
                    384:        g1=f3;
                    385:        if (lgef(u)>3)
                    386:        {
                    387:          N=lgef(u)-3; Q=cgetg(N+1,t_MAT);
                    388:          v3=cgetg(N+1,t_COL); Q[1]=(long)v3;
                    389:          v3[1]=(long)vun; for (i=2; i<=N; i++) v3[i]=(long)vzero;
                    390:
                    391:          v2 = v = nfmod_pol_pow(nf,prhall,u,x,q);
                    392:          for (j=2; j<=N; j++)
                    393:          {
                    394:            v3=cgetg(N+1,t_COL); Q[j]=(long)v3;
                    395:            for (i=1; i<=lgef(v2)-2; i++) v3[i]=v2[i+1];
                    396:            for (; i<=N; i++) v3[i]=(long)vzero;
                    397:            if (j<N)
                    398:            {
                    399:              v2=nfmod_pol_mul(nf,prhall,v2,v);
                    400:              nfmod_pol_divres(nf,prhall,v2,u,&v2);
                    401:            }
                    402:          }
                    403:          for (i=1; i<=N; i++)
                    404:            coeff(Q,i,i)=lsub((GEN)coeff(Q,i,i),vun);
                    405:          v2=nfkermodpr(nf,Q,prhall); r=lg(v2)-1; t[nbfact]=gcopy(u); kk=1;
                    406:          if (r>1)
                    407:          {
                    408:            vker=cgetg(r+1,t_COL);
                    409:            for (i=1; i<=r; i++)
                    410:            {
                    411:              v3=cgetg(N+2,t_POL);
                    412:              v3[1]=evalsigne(1)+evallgef(2+N); setvarn(v3,vf);
                    413:              vker[i]=(long)v3; for (j=1; j<=N; j++) v3[j+1]=coeff(v2,j,i);
                    414:              normalizepol(v3);
                    415:            }
                    416:          }
                    417:          while (kk<r)
                    418:          {
                    419:            v=gcopy(polun[vf]); v[2]=(long)vzero;
                    420:            for (i=1; i<=r; i++)
                    421:            {
                    422:              vz=cgetg(n+1,t_COL);
                    423:              for (j=1; j<=n; j++)
                    424:                vz[j] = lmodsi(mymyrand()>>8, q);
                    425:              vz=nfreducemodpr(nf,vz,prhall);
                    426:              v=gadd(v,nfmod_pol_mul(nf,prhall,vz,(GEN)vker[i]));
                    427:            }
                    428:            for (i=1; i<=kk && kk<r; i++)
                    429:            {
                    430:              polb=t[nbfact+i-1]; lb=lgef(polb);
                    431:              if (lb>4)
                    432:              {
                    433:                if(psim==2)
                    434:                  polu=nfmod_split2(nf,prhall,polb,v,q);
                    435:                else
                    436:                {
                    437:                  polu=nfmod_pol_pow(nf,prhall,polb,v,shifti(q,-1));
                    438:                   polu=gsub(polu,vun);
                    439:                }
                    440:                 pold=nfmod_pol_gcd(nf,prhall,polb,polu);
                    441:                if (lgef(pold)>3 && lgef(pold)<lb)
                    442:                {
                    443:                  t[nbfact+i-1]=pold; kk++;
                    444:                  t[nbfact+kk-1]=nfmod_pol_divres(nf,prhall,polb,pold,NULL);
                    445:                }
                    446:              }
                    447:            }
                    448:          }
                    449:          for (i=nbfact; i<nbfact+r; i++) ex[i]=e*k;
                    450:          nbfact+=r;
                    451:        }
                    452:       }
                    453:       e*=psim; j=(lgef(f2)-3)/psim+3; f1=cgetg(j,t_POL);
                    454:       f1[1] = evalsigne(1) | evallgef(j) | evalvarn(vf);
                    455:       for (i=2; i<j; i++)
                    456:        f1[i]=(long)element_powmodpr(nf,(GEN)f2[psim*(i-2)+2],
                    457:                                     gdiv(q,(GEN)pr[1]),prhall);
                    458:     }
                    459:   }
                    460:   if (nbfact < 2)
                    461:     err(talker, "%Z not a prime (nffactormod)", q);
                    462:   v=element_divmodpr(nf,vun,gmael(t,1,lgef(t[1])-1),prhall);
                    463:   t[1]=unifpol(nf,nfmod_pol_mul(nf,prhall,v,(GEN)t[1]),1);
                    464:   for (j=2; j<nbfact; j++)
                    465:     if (ex[j])
                    466:     {
                    467:       v=element_divmodpr(nf,vun,gmael(t,j,lgef(t[j])-1),prhall);
                    468:       t[j]=unifpol(nf,nfmod_pol_mul(nf,prhall,v,(GEN)t[j]),1);
                    469:     }
                    470:
                    471:   tetpil=avma; y=cgetg(3,t_MAT);
                    472:   u=cgetg(nbfact,t_COL); y[1]=(long)u;
                    473:   v=cgetg(nbfact,t_COL); y[2]=(long)v;
                    474:   for (j=1,k=0; j<nbfact; j++)
                    475:     if (ex[j])
                    476:     {
                    477:       k++;
                    478:       u[k]=lcopy((GEN)t[j]);
                    479:       v[k]=lstoi(ex[j]);
                    480:     }
                    481:   return gerepile(av,tetpil,y);
                    482: }
                    483:
                    484: /* Calcule pol + pol^2 + ... + pol^(q/2) modulo prhall et le polynome pmod */
                    485: static GEN
                    486: nfmod_split2(GEN nf,GEN prhall,GEN pmod,GEN pol,GEN exp)
                    487: {
                    488:   long av = avma;
                    489:   GEN p1,p2,q;
                    490:
                    491:   if (cmpis(exp,2)<=0) return pol;
                    492:   p2=p1=pol; q=shifti(exp,-1);
                    493:   while (!gcmp1(q))
                    494:   {
                    495:     p2=nfmod_pol_sqr(nf,prhall,p2);
                    496:     nfmod_pol_divres(nf,prhall,p2,pmod,&p2);
                    497:     q=shifti(q,-1); p1=gadd(p1,p2);
                    498:   }
                    499:   return gerepileupto(av,p1);
                    500: }
                    501:
                    502: /* If p doesn't divide either a or b and has a divisor of degree 1, return it.
                    503:  * Return NULL otherwise.
                    504:  */
                    505: static GEN
                    506: p_ok(GEN nf, GEN p, GEN a)
                    507: {
                    508:   long av,m,i;
                    509:   GEN dec;
                    510:
                    511:   if (divise(a,p)) return NULL;
                    512:   av = avma; dec = primedec(nf,p); m=lg(dec);
                    513:   for (i=1; i<m; i++)
                    514:   {
                    515:     GEN pr = (GEN)dec[i];
                    516:     if (is_pm1(pr[4]))
                    517:     {
                    518:       if (DEBUGLEVEL>=4)
                    519:         fprintferr("Premier choisi pour decomposition: %Z\n", pr);
                    520:       return pr;
                    521:     }
                    522:   }
                    523:   avma = av; return NULL;
                    524: }
                    525:
                    526: static GEN
                    527: choose_prime(GEN nf, GEN dk, GEN lim)
                    528: {
                    529:   GEN p, pr;
                    530:
                    531:   p = nextprime(lim);
                    532:   for (;;)
                    533:   {
                    534:     if ((pr = p_ok(nf,p,dk))) break;
                    535:     p = nextprime(addis(p,2));
                    536:   }
                    537:
                    538:   return pr;
                    539: }
                    540:
                    541: /* Renvoie les racines de pol contenues dans nf */
                    542: GEN
                    543: nfroots(GEN nf,GEN pol)
                    544: {
                    545:   long av=avma,tetpil,i,d=lgef(pol);
                    546:   GEN p1,p2,polbase,polmod,den;
                    547:
                    548:   nf=checknf(nf);
                    549:   if (typ(pol)!=t_POL) err(talker,"not a polynomial in nfroots");
                    550:   if (varn(pol) >= varn(nf[1]))
                    551:     err(talker,"polynomial variable must have highest priority in nfroots");
                    552:
                    553:   polbase=unifpol(nf,pol,0);
                    554:
                    555:   if (d==3)
                    556:   {
                    557:     tetpil=avma; p1=cgetg(1,t_VEC);
                    558:     return gerepile(av,tetpil,p1);
                    559:   }
                    560:
                    561:   if (d==4)
                    562:   {
                    563:     tetpil=avma; p1=cgetg(2,t_VEC);
                    564:     p1[1] = (long)basistoalg(nf,gneg_i(
                    565:       element_div(nf,(GEN)polbase[2],(GEN)polbase[3])));
                    566:     return gerepile(av,tetpil,p1);
                    567:   }
                    568:
                    569:   p1=element_inv(nf,leading_term(polbase));
                    570:   polbase=nf_pol_mul(nf,p1,polbase);
                    571:
                    572:   den=gun;
                    573:   for (i=2; i<d; i++)
                    574:     if (! gcmp0((GEN)polbase[i]))
                    575:       den = glcm(den,denom((GEN)polbase[i]));
                    576:   if (! gcmp1(absi(den)))
                    577:     for (i=2; i<d; i++)
                    578:       polbase[i] = lmul(den,(GEN)polbase[i]);
                    579:
                    580:   polmod=unifpol(nf,polbase,1);
                    581:
                    582:   if (DEBUGLEVEL>=4)
                    583:     fprintferr("On teste si le polynome est square-free\n");
                    584:
                    585:   p1=derivpol(polmod);
                    586:   p2=nf_pol_subres(nf,polmod,p1);
                    587:
                    588:   if (degree(p2) > 0)
                    589:   {
                    590:     p1=element_inv(nf,leading_term(p2));
                    591:     p2=nf_pol_mul(nf,p1,p2);
                    592:     polmod=nf_pol_divres(nf,polmod,p2,NULL);
                    593:
                    594:     p1=element_inv(nf,leading_term(polmod));
                    595:     polmod=nf_pol_mul(nf,p1,polmod);
                    596:
                    597:     d=lgef(polmod); den=gun;
                    598:     for (i=2; i<d; i++)
                    599:       if (!gcmp0((GEN)polmod[i]))
                    600:        den = glcm(den,denom((GEN)polmod[i]));
                    601:     if (!gcmp1(absi(den)))
                    602:       for (i=2; i<d; i++)
                    603:        polmod[i] = lmul(den,(GEN)polmod[i]);
                    604:
                    605:     polmod=unifpol(nf,polmod,1);
                    606:   }
                    607:
                    608:   p1 = nfsqff(nf,polmod,1);
                    609:   tetpil=avma; return gerepile(av, tetpil, gen_sort(p1, 0, cmp_pol));
                    610: }
                    611:
                    612: /* Relevement de elt modulo id minimal */
                    613: static GEN
                    614: nf_bestlift(GEN id,GEN idinv,GEN den,GEN elt)
                    615: {
                    616:   return gsub(elt,gmul(id,ground(gmul(den,gmul(idinv,elt)))));
                    617: }
                    618:
                    619: /* Releve le polynome pol avec des coeff de norme t2 <= C si possible */
                    620: static GEN
                    621: nf_pol_lift(GEN id,GEN idinv,GEN den,GEN pol)
                    622: {
                    623:   long i, d = lgef(pol);
                    624:   GEN p1 = pol;
                    625:
                    626:   pol=cgetg(d,t_POL); pol[1]=p1[1];
                    627:   for (i=2; i<d; i++)
                    628:     pol[i] = (long) nf_bestlift(id,idinv,den,(GEN)p1[i]);
                    629:   return pol;
                    630: }
                    631:
                    632: #if 0
                    633: /* Evalue le polynome pol en elt */
                    634: static GEN
                    635: nf_pol_eval(GEN nf,GEN pol,GEN elt)
                    636: {
                    637:   long av=avma,tetpil,i;
                    638:   GEN p1;
                    639:
                    640:   i=lgef(pol)-1; if (i==2) return gcopy((GEN)pol[2]);
                    641:
                    642:   p1=element_mul(nf,(GEN)pol[i],elt);
                    643:   for (i--; i>=3; i--)
                    644:     p1=element_mul(nf,elt,gadd((GEN)pol[i],p1));
                    645:   tetpil=avma; return gerepile(av,tetpil,gadd(p1,(GEN)pol[2]));
                    646: }
                    647: #endif
                    648:
                    649: /* Calcule la factorisation du polynome x dans nf */
                    650: GEN
                    651: nffactor(GEN nf,GEN pol)
                    652: { GEN y,p1,p2,den,p3,p4,quot, rep = cgetg(3,t_MAT);
                    653:   long av = avma,tetpil,i,d;
                    654:
                    655:   if (DEBUGLEVEL >= 4) timer2();
                    656:
                    657:   nf=checknf(nf);
                    658:   if (typ(pol)!=t_POL) err(typeer,"nffactor");
                    659:   if (varn(pol) >= varn(nf[1]))
                    660:     err(talker,"polynomial variable must have highest priority in nffactor");
                    661:
                    662:   d=lgef(pol);
                    663:   if (d==3)
                    664:   {
                    665:     rep[1]=lgetg(1,t_COL);
                    666:     rep[2]=lgetg(1,t_COL);
                    667:     return rep;
                    668:   }
                    669:   if (d==4)
                    670:   {
                    671:     p1=cgetg(2,t_COL); rep[1]=(long)p1; p1[1]=lcopy(pol);
                    672:     p1=cgetg(2,t_COL); rep[2]=(long)p1; p1[1]=un;
                    673:     return rep;
                    674:   }
                    675:
                    676:   p1=element_inv(nf,leading_term(pol));
                    677:   pol=nf_pol_mul(nf,p1,pol);
                    678:
                    679:   p1=unifpol(nf,pol,0); den=gun;
                    680:   for (i=2; i<d; i++)
                    681:     if (! gcmp0((GEN)p1[i]))
                    682:       den = glcm(den,denom((GEN)p1[i]));
                    683:   if (! gcmp1(absi(den)))
                    684:     for (i=2; i<d; i++)
                    685:       p1[i] = lmul(den,(GEN)p1[i]);
                    686:
                    687:   if (DEBUGLEVEL>=4)
                    688:     fprintferr("On teste si le polynome est square-free\n");
                    689:
                    690:   p2=derivpol(p1);
                    691:   p3=nf_pol_subres(nf,p1,p2);
                    692:
                    693:   if (degree(p3) > 0)
                    694:   {
                    695:     p4=element_inv(nf,leading_term(p3));
                    696:     p3=nf_pol_mul(nf,p4,p3);
                    697:
                    698:     p2=nf_pol_divres(nf,p1,p3,NULL);
                    699:     p4=element_inv(nf,leading_term(p2));
                    700:     p2=nf_pol_mul(nf,p4,p2);
                    701:
                    702:     d=lgef(p2); den=gun;
                    703:     for (i=2; i<d; i++)
                    704:       if (!gcmp0((GEN)p2[i]))
                    705:        den = glcm(den,denom((GEN)p2[i]));
                    706:     if (!gcmp1(absi(den)))
                    707:       for (i=2; i<d; i++)
                    708:        p2[i] = lmul(den,(GEN)p2[i]);
                    709:
                    710:     p2=unifpol(nf,p2,1);
                    711:     tetpil = avma; y = nfsqff(nf,p2,0);
                    712:     i = nfcmbf.nfact;
                    713:
                    714:     quot=nf_pol_divres(nf,p1,p2,NULL);
                    715:     p3=(GEN)gpmalloc((i+1) * sizeof(long));
                    716:     for ( ; i>=1; i--)
                    717:     {
                    718:       GEN fact=(GEN)y[i], quo = quot, rem;
                    719:       long e = 0;
                    720:
                    721:       do
                    722:       {
                    723:        quo = nf_pol_divres(nf,quo,fact,&rem);
                    724:        e++;
                    725:       }
                    726:       while (gcmp0(rem));
                    727:       p3[i]=lstoi(e);
                    728:     }
                    729:     avma = (long)y; y = gerepile(av, tetpil, y);
                    730:     p2=cgetg(i+1, t_COL); for (; i>=1; i--) p2[i]=lstoi(p3[i]);
                    731:     free(p3);
                    732:   }
                    733:   else
                    734:   {
                    735:     tetpil=avma; y = gerepile(av,tetpil,nfsqff(nf,p1,0));
                    736:     i = nfcmbf.nfact;
                    737:     p2=cgetg(i+1, t_COL); for (; i>=1; i--) p2[i]=un;
                    738:   }
                    739:   if (DEBUGLEVEL>=4)
                    740:     fprintferr("Nombre de facteur(s) trouve(s) : %ld\n", nfcmbf.nfact);
                    741:   rep[1]=(long)y;
                    742:   rep[2]=(long)p2; return sort_factor(rep, cmp_pol);
                    743: }
                    744:
                    745: /* teste si la matrice M est suffisament orthogonale */
                    746: static long
                    747: test_mat(GEN M, GEN p, GEN C2, long k)
                    748: {
                    749:   long av = avma, i, N = lg(M);
                    750:   GEN min, prod, L2, R;
                    751:
                    752:   min = prod = gcoeff(M,1,1);
                    753:   for (i = 2; i < N; i++)
                    754:   {
                    755:     L2 = gcoeff(M,i,i); prod = mpmul(prod,L2);
                    756:     if (mpcmp(L2,min) < 0) min = L2;
                    757:   }
                    758:   R = mpmul(min, gpowgs(p, k<<1));
                    759:   i = mpcmp(mpmul(C2,prod), R); avma = av;
                    760:   return (i < 0);
                    761: }
                    762:
                    763: /* calcule la matrice correspondant a pr^e jusqu'a ce que R(pr^e) > C */
                    764: static GEN
                    765: T2_matrix_pow(GEN nf, GEN pre, GEN p, GEN C, long *kmax, long prec)
                    766: {
                    767:   long av=avma,av1,lim, k = *kmax, N = lgef((GEN)nf[1])-3;
                    768:   int tot_real = !signe(gmael(nf,2,2));
                    769:   GEN p1,p2,p3,u,C2,T2, x = (GEN)nf[1];
                    770:
                    771:   C2 = gdiv(gmul2n(C,2), absi((GEN)nf[3]));
                    772:   p1 = gmul(pre,lllintpartial(pre)); av1 = avma;
                    773:   T2 = tot_real? gmael(nf,5,4)
                    774:                : nf_get_T2((GEN) nf[7], roots(x,prec));
                    775:   p3 = qf_base_change(T2,p1,1);
                    776:
                    777:   if (N <= 6 && test_mat(p3,p,C2,k))
                    778:   {
                    779:     avma = av1; return gerepileupto(av,p1);
                    780:   }
                    781:
                    782:   av1=avma; lim = stack_lim(av1,2);
                    783:   for (;;)
                    784:   {
                    785:     if (DEBUGLEVEL>2) fprintferr("exponent: %ld\n",k);
                    786:
                    787:     for(;;)
                    788:     {
                    789:       u = tot_real? lllgramint(p3): lllgramintern(p3,100,1,prec);
                    790:       if (u) break;
                    791:
                    792:       prec=(prec<<1)-2;
                    793:       if (DEBUGLEVEL > 1) err(warnprec,"nffactor[1]",prec);
                    794:       T2 = nf_get_T2((GEN) nf[7], roots(x,prec));
                    795:       p3 = qf_base_change(T2,p1,1);
                    796:     }
                    797:     if (DEBUGLEVEL>2) msgtimer("lllgram + base change");
                    798:     p3 = qf_base_change(p3,u,1);
                    799:     if (test_mat(p3,p,C2,k))
                    800:     {
                    801:       *kmax = k;
                    802:       return gerepileupto(av,gmul(p1,u));
                    803:     }
                    804:
                    805:     /* il faut augmenter la precision en meme temps */
                    806:     p2=shifti(gceil(mulsr(k, glog(p,DEFAULTPREC))),-1);
                    807:     prec += (long)(itos(p2)*pariK1);
                    808:     if (DEBUGLEVEL > 1) err(warnprec,"nffactor[2]",prec);
                    809:     k = k<<1; p1 = idealmullll(nf,p1,p1);
                    810:     if (low_stack(lim, stack_lim(av1,2)))
                    811:     {
                    812:       if (DEBUGMEM>1) err(warnmem,"T2_matrix_pow");
                    813:       p1 = gerepileupto(av1,p1);
                    814:     }
                    815:     if (!tot_real) T2 = nf_get_T2((GEN) nf[7], roots(x,prec));
                    816:     p3 = qf_base_change(T2,p1,1);
                    817:   }
                    818: }
                    819:
                    820: /* Calcule la factorisation du polynome x qui est sans facteurs carres dans nf,
                    821:    Le polynome est a coefficients dans Z_k et son terme dominant est un entier
                    822:    rationnel, si fl=1 renvoie seulement les racines du polynome contenues
                    823:    dans le corps */
                    824: static GEN
                    825: nfsqff(GEN nf,GEN pol, long fl)
                    826: {
                    827:   long d=lgef(pol),i,k,m,n,av=avma,tetpil,newprec,prec;
                    828:   GEN p1,pr,p2,rep,k2,C,h,dk,dki,p,prh,p3,T2,polbase,fact,pk;
                    829:   GEN polmod,polred,hinv,lt,minp,den,maxp=shifti(gun,32),run;
                    830:
                    831:   dk=absi((GEN)nf[3]);
                    832:   dki=mulii(dk,(GEN)nf[4]);
                    833:   n=lgef(nf[1])-3;
                    834:
                    835:   polbase = unifpol(nf,pol,0);
                    836:   polmod  = unifpol(nf,pol,1);
                    837:   dki=mulii(dki,gnorm((GEN)polmod[d-1]));
                    838:
                    839:   prec = DEFAULTPREC;
                    840:   for (;;)
                    841:   {
                    842:     if (prec <= gprecision(nf))
                    843:       T2 = gprec_w(gmael(nf,5,3), prec);
                    844:     else
                    845:       T2 = nf_get_T2((GEN)nf[7], roots((GEN)nf[1], prec));
                    846:
                    847:     run=realun(prec);
                    848:     p1=realzero(prec);
                    849:     for (i=2; i<d; i++)
                    850:     {
                    851:       p2 = gmul(run, (GEN)polbase[i]);
                    852:       p1 = addrr(p1, qfeval(T2, p2));
                    853:       if (signe(p1) < 0) break;
                    854:     }
                    855:
                    856:     if (signe(p1) > 0) break;
                    857:
                    858:     prec = (prec<<1)-2;
                    859:     if (DEBUGLEVEL > 1) err(warnprec, "nfsqff", prec);
                    860:   }
                    861:
                    862:   if (DEBUGLEVEL>=4)
                    863:     fprintferr("La norme de ce polynome est : %Z\n", p1);
                    864:
                    865:   lt=(GEN)leading_term(polbase)[1];
                    866:   p2=mulis(sqri(lt),n);
                    867:   C=mpadd(p1,p2);
                    868:   C=mpadd(C,gsqrt(gmul(p1,p2),prec));
                    869:
                    870:   if (!fl)
                    871:     C=mpmul(C,sqri(binome(shifti(stoi(n-1),-1),(n-1)>>2)));
                    872:
                    873:   C=gmul(C,sqri(lt));
                    874:
                    875:   if (DEBUGLEVEL>=4)
                    876:     fprintferr("La borne de la norme des coeff du diviseur est : %Z\n", C);
                    877:
                    878:   k2=gmul2n(gmulgs(glog(gdivgs(gmul2n(C,2),n),DEFAULTPREC),n),-1);
                    879:   if (!fl) k2=mulrr(k2,dbltor(1.1));
                    880:
                    881:   minp=gmin(gexp(gmul2n(k2,-6),BIGDEFAULTPREC), maxp);
                    882:   minp=gceil(minp);
                    883:
                    884:   if (DEBUGLEVEL>=4)
                    885:   {
                    886:     fprintferr("borne inf. sur les nombres premiers : %Z\n", minp);
                    887:     msgtimer("Calcul des bornes");
                    888:   }
                    889:   for (;;)
                    890:   {
                    891:     pr=choose_prime(nf,dki,minp); p=(GEN)pr[1];
                    892:     prh=prime_to_ideal(nf,pr);
                    893:
                    894:     polred=gcopy(polbase);
                    895:     lt=(GEN)leading_term(polbase)[1];
                    896:     lt=mpinvmod(lt,p);
                    897:
                    898:     for (i=2; i<d; i++)
                    899:       polred[i] = nfreducemodpr_i(gmul(lt,(GEN)polbase[i]), prh)[1];
                    900:     if (!divise(discsr(polred),p)) break;
                    901:     minp = addis(p,1);
                    902:   }
                    903:
                    904:   k = itos(gceil(gdiv(k2,glog(p,BIGDEFAULTPREC))));
                    905:   rep=(GEN)simplefactmod(polred,p)[1];
                    906:
                    907:   if (DEBUGLEVEL>=4)
                    908:   {
                    909:     msgtimer("Choix de l'ideal premier");
                    910:     fprintferr("Nombre de facteurs irreductibles modulo pr = %ld\n", lg(rep)-1);
                    911:   }
                    912:   if (lg(rep)==2)
                    913:   {
                    914:     if (fl) { avma=av; return cgetg(1,t_VEC); }
                    915:     rep=cgetg(2,t_VEC); rep[1]=lcopy(polmod);
                    916:     nfcmbf.nfact=1; return gerepileupto(av, rep);
                    917:   }
                    918:
                    919:   p2=cgetr(DEFAULTPREC);
                    920:   affir(mulii(absi(dk),gpowgs(p,k)),p2);
                    921:   p2=shifti(gceil(mplog(p2)),-1);
                    922:
                    923:   newprec = MEDDEFAULTPREC + (long)(itos(p2)*pariK1);
                    924:   if (DEBUGLEVEL>=4)
                    925:     fprintferr("nouvelle precision : %ld\n",newprec);
                    926:
                    927:   prh = idealpows(nf,pr,k); m = k;
                    928:   h = T2_matrix_pow(nf,prh,p,C, &k, newprec);
                    929:   if (m != k) prh=idealpows(nf,pr,k);
                    930:
                    931:   if (DEBUGLEVEL>=4)
                    932:   {
                    933:     fprintferr("un exposant convenable est : %ld\n",(long)k);
                    934:     msgtimer("Calcul de H");
                    935:   }
                    936:
                    937:   pk = gcoeff(prh,1,1);
                    938:   lt=(GEN)leading_term(polbase)[1];
                    939:   lt=mpinvmod(lt,pk);
                    940:
                    941:   polred[1] = polbase[1];
                    942:   for (i=2; i<d; i++)
                    943:     polred[i] = nfreducemodpr_i(gmul(lt,(GEN)polbase[i]), prh)[1];
                    944:
                    945:   fact = lift_intern((GEN)factmod(polred,p)[1]);
                    946:   rep = hensel_lift_fact(polred,fact,p,pk,k);
                    947:
                    948:   if (DEBUGLEVEL >= 4) msgtimer("Calcul de la factorisation pr-adique");
                    949:
                    950:   den=ginv(det(h));
                    951:   hinv=adj(h);
                    952:   lt=(GEN)leading_term(polbase)[1];
                    953:
                    954:   if (fl)
                    955:   {
                    956:     long x_a[] = { evaltyp(t_POL)|m_evallg(4), 0,0,0 };
                    957:     GEN mlt = negi(lt), rem;
                    958:     x_a[1] = polbase[1]; setlgef(x_a, 4);
                    959:     x_a[3] = un;
                    960:     p1=cgetg(lg(rep)+1,t_VEC);
                    961:     polbase = unifpol(nf,polbase,1);
                    962:     for (m=1,i=1; i<lg(rep); i++)
                    963:     {
                    964:       p2=(GEN)rep[i]; if (lgef(p2)!=4) break;
                    965:
                    966:       p3 = algtobasis(nf, gmul(mlt,(GEN)p2[2]));
                    967:       p3 = nf_bestlift(h,hinv,den,p3);
                    968:       p3 = gdiv(p3,lt);
                    969:       x_a[2] = lneg(p3); /* check P(p3) == 0 */
                    970:       p2 = poldivres(polbase, unifpol(nf,x_a,1), &rem);
                    971:       if (!signe(rem)) { polbase = p2; p1[m++] = (long)p3; }
                    972:     }
                    973:     tetpil=avma; rep=cgetg(m,t_VEC);
                    974:     for (i=1; i<m; i++) rep[i]=(long)basistoalg(nf,(GEN)p1[i]);
                    975:     return gerepile(av,tetpil,rep);
                    976:   }
                    977:
                    978:   for (i=1; i<lg(rep); i++)
                    979:     rep[i] = (long)unifpol(nf,(GEN)rep[i],0);
                    980:
                    981:   nfcmbf.pol      = polmod;
                    982:   nfcmbf.lt       = lt;
                    983:   nfcmbf.h        = h;
                    984:   nfcmbf.hinv     = hinv;
                    985:   nfcmbf.den      = den;
                    986:   nfcmbf.fact     = rep;
                    987:   nfcmbf.res      = cgetg(lg(rep)+1,t_VEC);
                    988:   nfcmbf.nfact    = 0;
                    989:   nfcmbf.nfactmod = lg(rep)-1;
                    990:   nf_combine_factors(nf,1,NULL,d-3,1);
                    991:
                    992:   if (DEBUGLEVEL >= 4) msgtimer("Reconnaissance des facteurs");
                    993:
                    994:   i = nfcmbf.nfact;
                    995:   if (lgef(nfcmbf.pol)>3)
                    996:   {
                    997:     nfcmbf.res[++i] = (long) nf_pol_divres(nf,nfcmbf.pol,nfcmbf.lt,NULL);
                    998:     nfcmbf.nfact = i;
                    999:   }
                   1000:
                   1001:   tetpil=avma; rep=cgetg(i+1,t_VEC);
                   1002:   for (  ; i>=1; i--)
                   1003:     rep[i]=(long)unifpol(nf,(GEN)nfcmbf.res[i],1);
                   1004:   return gerepile(av,tetpil,rep);
                   1005: }
                   1006:
                   1007: static int
                   1008: nf_combine_factors(GEN nf,long fxn,GEN psf,long dlim,long hint)
                   1009: {
                   1010:   int val=0; /* assume failure */
                   1011:   GEN newf, newpsf = NULL;
                   1012:   long newd,ltop,i;
                   1013:
                   1014:   if (dlim<=0) return 0;
                   1015:   if (fxn > nfcmbf.nfactmod) return 0;
                   1016:   /* first, try deeper factors without considering the current one */
                   1017:   if (fxn != nfcmbf.nfactmod)
                   1018:   {
                   1019:     val=nf_combine_factors(nf,fxn+1,psf,dlim,hint);
                   1020:     if (val && psf) return 1;
                   1021:   }
                   1022:
                   1023:   /* second, try including the current modular factor in the product */
                   1024:   newf=(GEN)nfcmbf.fact[fxn];
                   1025:   if (!newf) return val; /* modular factor already used */
                   1026:   newd=lgef(newf)-3;
                   1027:   if (newd>dlim) return val; /* degree of new factor is too large */
                   1028:
                   1029:   if (newd%hint == 0)
                   1030:   {
                   1031:     GEN p, quot,rem;
                   1032:
                   1033:     newpsf = nf_pol_mul(nf, (psf)? psf: nfcmbf.lt, newf);
                   1034:     newpsf = nf_pol_lift(nfcmbf.h,nfcmbf.hinv,nfcmbf.den,newpsf);
                   1035:     /* try out the new combination */
                   1036:     ltop=avma;
                   1037:     quot=nf_pol_divres(nf,nfcmbf.pol,newpsf,&rem);
                   1038:     if (gcmp0(rem))  /* found a factor */
                   1039:     {
                   1040:       p = nf_pol_mul(nf,element_inv(nf,leading_term(newpsf)),newpsf);
                   1041:       nfcmbf.res[++nfcmbf.nfact] = (long) p; /* store factor */
                   1042:       nfcmbf.fact[fxn]=0;                    /* remove used modular factor */
                   1043:
                   1044:       /* fix up target */
                   1045:       p=gun; quot=unifpol(nf,quot,0);
                   1046:       for (i=2; i<lgef(quot); i++)
                   1047:        if (!gcmp0((GEN)quot[i]))
                   1048:          p = glcm(p, denom((GEN)quot[i]));
                   1049:
                   1050:       nfcmbf.pol = nf_pol_mul(nf,p,quot);
                   1051:       nfcmbf.lt  = leading_term(nfcmbf.pol);
                   1052:       return 1;
                   1053:     }
                   1054:     avma=ltop;
                   1055:   }
                   1056:
                   1057:   /* newpsf needs more; try for it */
                   1058:   if (newd==dlim) return val; /* no more room in degree limit */
                   1059:   if (fxn==nfcmbf.nfactmod) return val; /* no more modular factors to try */
                   1060:
                   1061:   if (nf_combine_factors(nf,fxn+1,newpsf,dlim-newd,hint))
                   1062:   {
                   1063:     nfcmbf.fact[fxn]=0; /* remove used modular factor */
                   1064:     return 1;
                   1065:   }
                   1066:   return val;
                   1067: }
                   1068:
                   1069: /* Calcule le polynome caracteristique de alpha sur nf ou alpha est un
                   1070:    element de l'algebre nf[X]/(T) exprime comme polynome en x */
                   1071: GEN
                   1072: rnfcharpoly(GEN nf,GEN T,GEN alpha,int v)
                   1073: {
                   1074:   long av=avma,tetpil;
                   1075:   GEN p1;
                   1076:
                   1077:   nf=checknf(nf); if (v<0) v = 0;
                   1078:   if (typ(alpha) == t_POLMOD) alpha = lift_to_pol(alpha);
                   1079:   p1 = caract2(unifpol(nf,T,1), unifpol(nf,alpha,1), v);
                   1080:   tetpil=avma; return gerepile(av,tetpil,unifpol(nf,p1,1));
                   1081: }
                   1082:
                   1083: #if 0
                   1084: /* Calcule le polynome minimal de alpha sur nf ou alpha est un
                   1085:    element de l'algebre nf[X]/(T) exprime comme polynome en x */
                   1086: GEN
                   1087: rnfminpoly(GEN nf,GEN T,GEN alpha,int n)
                   1088: {
                   1089:   long av=avma,tetpil;
                   1090:   GEN p1,p2;
                   1091:
                   1092:   nf=checknf(nf); p1=rnfcharpoly(nf,T,alpha,n);
                   1093:   tetpil=avma; p2=nf_pol_subres(nf,p1,deriv(p1,varn(T)));
                   1094:   if (lgef(p2)==3) { avma=tetpil; return p1; }
                   1095:
                   1096:   p1 = nf_pol_divres(nf,p1,p2,NULL);
                   1097:   p2 = element_inv(nf,leading_term(p1));
                   1098:   tetpil=avma; return gerepile(av,tetpil,unifpol(nf,nf_pol_mul(nf,p2,p1),1));
                   1099: }
                   1100: #endif
                   1101:
                   1102: /* relative Dedekind criterion over nf, applied to the order defined by a
                   1103:  * root of irreducible polynomial T, modulo the prime ideal pr. Returns
                   1104:  * [flag,basis,val], where basis is a pseudo-basis of the enlarged order,
                   1105:  * flag is 1 iff this order is pr-maximal, and val is the valuation in pr of
                   1106:  * the order discriminant
                   1107:  */
                   1108: GEN
                   1109: rnfdedekind(GEN nf,GEN T,GEN pr)
                   1110: {
                   1111:   long av=avma,vt,tetpil,r,d,da,n,m,i,j;
                   1112:   GEN p1,p2,p,tau,g,vecun,veczero,matid;
                   1113:   GEN prhall,res,h,k,base,Ca;
                   1114:
                   1115:   nf=checknf(nf); Ca=unifpol(nf,T,0);
                   1116:   res=cgetg(4,t_VEC);
                   1117:   if (typ(pr)==t_VEC && lg(pr)==3)
                   1118:   { prhall = (GEN)pr[2]; pr = (GEN)pr[1]; }
                   1119:   else
                   1120:     prhall=nfmodprinit(nf,pr);
                   1121:   p=(GEN)pr[1]; tau=gdiv((GEN)pr[5],p);
                   1122:   n=lgef(nf[1])-3; m=lgef(T)-3;
                   1123:
                   1124:   vecun=cgetg(n+1,t_COL); vecun[1]=un;
                   1125:   veczero=cgetg(n+1,t_COL); veczero[1]=zero;
                   1126:   for (i=2; i<=n; i++) vecun[i] = veczero[i] = zero;
                   1127:   matid=idmat(n);
                   1128:
                   1129:   p1=(GEN)nffactormod(nf,Ca,pr)[1];
                   1130:   g=lift((GEN)p1[1]); r=lg(p1);
                   1131:   for (i=2; i<r; i++)
                   1132:     g = nf_pol_mul(nf,g, lift((GEN)p1[i]));
                   1133:   h=nfmod_pol_divres(nf,prhall,Ca,g,NULL);
                   1134:   k=nf_pol_mul(nf,tau,gsub(Ca, nf_pol_mul(nf,lift(g),lift(h))));
                   1135:   p2=nfmod_pol_gcd(nf,prhall,g,h);
                   1136:   k= nfmod_pol_gcd(nf,prhall,p2,k);
                   1137:
                   1138:   d=lgef(k)-3;
                   1139:   vt = idealval(nf,discsr(T),pr) - 2*d;
                   1140:   res[3]=lstoi(vt);
                   1141:   if (!d || vt<=1) res[1]=un; else res[1]=zero;
                   1142:
                   1143:   base=cgetg(3,t_VEC);
                   1144:   p1=cgetg(m+d+1,t_MAT); base[1]=(long)p1;
                   1145:   p2=cgetg(m+d+1,t_VEC); base[2]=(long)p2;
                   1146:   for (j=1; j<=m; j++)
                   1147:   {
                   1148:     p2[j]=(long)matid;
                   1149:     p1[j]=lgetg(m+1,t_COL);
                   1150:     for (i=1; i<=m; i++)
                   1151:       coeff(p1,i,j) = (i==j)?(long)vecun:(long)veczero;
                   1152:   }
                   1153:
                   1154:   if (d)
                   1155:   {
                   1156:     GEN pal = lift(nfmod_pol_divres(nf,prhall,Ca,k,NULL));
                   1157:     GEN prinv=idealinv(nf,pr);
                   1158:     GEN nfx=unifpol(nf,polx[varn(T)],0);
                   1159:
                   1160:     for (j=m+1; j<=m+d; j++)
                   1161:     {
                   1162:       p1[j]=lgetg(m+1,t_COL);
                   1163:       da=lgef(pal)-3;
                   1164:       for (i=1; i<=da+1; i++) coeff(p1,i,j)=pal[i+1];
                   1165:       for (   ; i<=m; i++) coeff(p1,i,j)=(long)veczero;
                   1166:       p2[j]=(long)prinv;
                   1167:       nf_pol_divres(nf,nf_pol_mul(nf,pal,nfx),T,&pal);
                   1168:     }
                   1169:     base=nfhermite(nf,base);
                   1170:   }
                   1171:   res[2]=(long)base; tetpil=avma; return gerepile(av,tetpil,gcopy(res));
                   1172: }

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