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

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

1.1       noro        1: /* $Id: base2.c,v 1.87 2001/10/01 12:11:28 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: /*                       MAXIMAL ORDERS                            */
                     19: /*                                                                 */
                     20: /*******************************************************************/
                     21: #include "pari.h"
                     22:
                     23: extern GEN caractducos(GEN p, GEN x, int v);
                     24: extern GEN element_muli(GEN nf, GEN x, GEN y);
                     25: extern GEN element_mulid(GEN nf, GEN x, long i);
                     26: extern GEN eleval(GEN f,GEN h,GEN a);
                     27: extern GEN ideal_better_basis(GEN nf, GEN x, GEN M);
                     28: extern long int_elt_val(GEN nf, GEN x, GEN p, GEN bp, GEN *t, long v);
                     29: extern GEN mat_to_vecpol(GEN x, long v);
                     30: extern GEN nfidealdet1(GEN nf, GEN a, GEN b);
                     31: extern GEN nfsuppl(GEN nf, GEN x, long n, GEN prhall);
                     32: extern GEN pol_to_monic(GEN pol, GEN *lead);
                     33: extern GEN pol_to_vec(GEN x, long N);
                     34: extern GEN quicktrace(GEN x, GEN sym);
                     35: extern GEN respm(GEN f1,GEN f2,GEN pm);
                     36:
                     37: static void
                     38: allbase_check_args(GEN f, long code, GEN *y, GEN *ptw1, GEN *ptw2)
                     39: {
                     40:   GEN w;
                     41:   if (typ(f)!=t_POL) err(notpoler,"allbase");
                     42:   if (degpol(f) <= 0) err(constpoler,"allbase");
                     43:   if (DEBUGLEVEL) timer2();
                     44:   switch(code)
                     45:   {
                     46:     case 0: case 1:
                     47:       *y = ZX_disc(f);
                     48:       if (!signe(*y)) err(talker,"reducible polynomial in allbase");
                     49:       w = auxdecomp(absi(*y),1-code);
                     50:       break;
                     51:     default:
                     52:       w = (GEN)code;
                     53:       *y = factorback(w, NULL);
                     54:   }
                     55:   if (DEBUGLEVEL) msgtimer("disc. factorisation");
                     56:   *ptw1 = (GEN)w[1];
                     57:   *ptw2 = (GEN)w[2];
                     58: }
                     59:
                     60: /*******************************************************************/
                     61: /*                                                                 */
                     62: /*                            ROUND 2                              */
                     63: /*                                                                 */
                     64: /*******************************************************************/
                     65: /*  Normalized quotient and remainder ( -1/2 |y| < r = x-q*y <= 1/2 |y| ) */
                     66: static GEN
                     67: rquot(GEN x, GEN y)
                     68: {
                     69:   long av=avma,av1;
                     70:   GEN u,v,w,p;
                     71:
                     72:   u=absi(y); v=shifti(x,1); w=shifti(y,1);
                     73:   if (cmpii(u,v)>0) p=subii(v,u);
                     74:   else p=addsi(-1,addii(u,v));
                     75:   av1=avma; return gerepile(av,av1,divii(p,w));
                     76: }
                     77:
                     78: /* space needed lx + 2*ly */
                     79: static GEN
                     80: rrmdr(GEN x, GEN y)
                     81: {
                     82:   long av=avma,tetpil,k;
                     83:   GEN r,ys2;
                     84:
                     85:   if (!signe(x)) return gzero;
                     86:   r = resii(x,y); tetpil = avma;
                     87:   ys2 = shifti(y,-1);
                     88:   k = absi_cmp(r, ys2);
                     89:   if (k>0 || (k==0 && signe(r)>0))
                     90:   {
                     91:     avma = tetpil;
                     92:     if (signe(y) == signe(r)) r = subii(r,y); else r = addii(r,y);
                     93:     return gerepile(av,tetpil,r);
                     94:   }
                     95:   avma = tetpil; return r;
                     96: }
                     97:
                     98: /* companion matrix of unitary polynomial x */
                     99: static GEN
                    100: companion(GEN x) /* cf assmat */
                    101: {
                    102:   long i,j,l;
                    103:   GEN y;
                    104:
                    105:   l=degpol(x)+1; y=cgetg(l,t_MAT);
                    106:   for (j=1; j<l; j++)
                    107:   {
                    108:     y[j] = lgetg(l,t_COL);
                    109:     for (i=1; i<l-1; i++)
                    110:       coeff(y,i,j)=(i+1==j)? un: zero;
                    111:     coeff(y,i,j) = lneg((GEN)x[j+1]);
                    112:   }
                    113:   return y;
                    114: }
                    115:
                    116: /* assume x, y are square integer matrices of same dim. Multiply them */
                    117: static GEN
                    118: mulmati(GEN x, GEN y)
                    119: {
                    120:   long n = lg(x),i,j,k,av;
                    121:   GEN z = cgetg(n,t_MAT),p1,p2;
                    122:
                    123:   for (j=1; j<n; j++)
                    124:   {
                    125:     z[j] = lgetg(n,t_COL);
                    126:     for (i=1; i<n; i++)
                    127:     {
                    128:       p1=gzero; av=avma;
                    129:       for (k=1; k<n; k++)
                    130:       {
                    131:         p2=mulii(gcoeff(x,i,k),gcoeff(y,k,j));
                    132:         if (p2 != gzero) p1=addii(p1,p2);
                    133:       }
                    134:       coeff(z,i,j)=lpileupto(av,p1);
                    135:     }
                    136:   }
                    137:   return z;
                    138: }
                    139:
                    140: static GEN
                    141: powmati(GEN x, long m)
                    142: {
                    143:   long av=avma,j;
                    144:   GEN y = x;
                    145:
                    146:   j=1+bfffo(m); m<<=j; j = BITS_IN_LONG-j;
                    147:   for (; j; m<<=1,j--)
                    148:   {
                    149:     y=mulmati(y,y);
                    150:     if (m<0) y=mulmati(y,x);
                    151:   }
                    152:   return gerepileupto(av,y);
                    153: }
                    154:
                    155: static GEN
                    156: rtran(GEN v, GEN w, GEN q)
                    157: {
                    158:   long av,tetpil;
                    159:   GEN p1;
                    160:
                    161:   if (signe(q))
                    162:   {
                    163:     av=avma; p1=gneg(gmul(q,w)); tetpil=avma;
                    164:     return gerepile(av,tetpil,gadd(v,p1));
                    165:   }
                    166:   return v;
                    167: }
                    168:
                    169: /* return (v - qw) mod m (only compute entries k0,..,n)
                    170:  * v and w are expected to have entries smaller than m */
                    171: static GEN
                    172: mtran(GEN v, GEN w, GEN q, GEN m, long k0)
                    173: {
                    174:   long k,l;
                    175:   GEN p1;
                    176:
                    177:   if (signe(q))
                    178:   {
                    179:     l = lgefint(m) << 2;
                    180:     for (k=lg(v)-1; k>= k0; k--)
                    181:     {
                    182:       long av = avma; (void)new_chunk(l);
                    183:       p1 = subii((GEN)v[k], mulii(q,(GEN)w[k]));
                    184:       avma = av; v[k]=(long)rrmdr(p1, m);
                    185:     }
                    186:   }
                    187:   return v;
                    188: }
                    189:
                    190: /* entries of v and w are C small integers */
                    191: static GEN
                    192: mtran_long(GEN v, GEN w, long q, long m, long k0)
                    193: {
                    194:   long k, p1;
                    195:
                    196:   if (q)
                    197:   {
                    198:     for (k=lg(v)-1; k>= k0; k--)
                    199:     {
                    200:       p1 = v[k] - q * w[k];
                    201:       v[k] = p1 % m;
                    202:     }
                    203:   }
                    204:   return v;
                    205: }
                    206:
                    207: /* coeffs of a are C-long integers */
                    208: static void
                    209: rowred_long(GEN a, long rmod)
                    210: {
                    211:   long q,j,k,pro, c = lg(a), r = lg(a[1]);
                    212:
                    213:   for (j=1; j<r; j++)
                    214:   {
                    215:     for (k=j+1; k<c; k++)
                    216:       while (coeff(a,j,k))
                    217:       {
                    218:        q = coeff(a,j,j) / coeff(a,j,k);
                    219:        pro=(long)mtran_long((GEN)a[j],(GEN)a[k],q,rmod, j);
                    220:        a[j]=a[k]; a[k]=pro;
                    221:       }
                    222:     if (coeff(a,j,j) < 0)
                    223:       for (k=j; k<r; k++) coeff(a,k,j)=-coeff(a,k,j);
                    224:     for (k=1; k<j; k++)
                    225:     {
                    226:       q = coeff(a,j,k) / coeff(a,j,j);
                    227:       a[k]=(long)mtran_long((GEN)a[k],(GEN)a[j],q,rmod, k);
                    228:     }
                    229:   }
                    230:   /* don't update the 0s in the last columns */
                    231:   for (j=1; j<r; j++)
                    232:     for (k=1; k<r; k++) coeff(a,j,k) = lstoi(coeff(a,j,k));
                    233: }
                    234:
                    235: static void
                    236: rowred(GEN a, GEN rmod)
                    237: {
                    238:   long j,k,pro, c = lg(a), r = lg(a[1]);
                    239:   long av=avma, lim=stack_lim(av,1);
                    240:   GEN q;
                    241:
                    242:   for (j=1; j<r; j++)
                    243:   {
                    244:     for (k=j+1; k<c; k++)
                    245:       while (signe(gcoeff(a,j,k)))
                    246:       {
                    247:        q=rquot(gcoeff(a,j,j),gcoeff(a,j,k));
                    248:        pro=(long)mtran((GEN)a[j],(GEN)a[k],q,rmod, j);
                    249:        a[j]=a[k]; a[k]=pro;
                    250:       }
                    251:     if (signe(gcoeff(a,j,j)) < 0)
                    252:       for (k=j; k<r; k++) coeff(a,k,j)=lnegi(gcoeff(a,k,j));
                    253:     for (k=1; k<j; k++)
                    254:     {
                    255:       q=rquot(gcoeff(a,j,k),gcoeff(a,j,j));
                    256:       a[k]=(long)mtran((GEN)a[k],(GEN)a[j],q,rmod, k);
                    257:     }
                    258:     if (low_stack(lim, stack_lim(av,1)))
                    259:     {
                    260:       long j1,k1;
                    261:       GEN p1 = a;
                    262:       if(DEBUGMEM>1) err(warnmem,"rowred j=%ld", j);
                    263:       p1 = gerepilecopy(av,a);
                    264:       for (j1=1; j1<r; j1++)
                    265:         for (k1=1; k1<c; k1++) coeff(a,j1,k1) = coeff(p1,j1,k1);
                    266:     }
                    267:   }
                    268: }
                    269:
                    270: /* Calcule d/x  ou  d est entier et x matrice triangulaire inferieure
                    271:  * entiere dont les coeff diagonaux divisent d (resultat entier).
                    272:  */
                    273: static GEN
                    274: matinv(GEN x, GEN d, long n)
                    275: {
                    276:   long i,j,k,av,av1;
                    277:   GEN y,h;
                    278:
                    279:   y=idmat(n);
                    280:   for (i=1; i<=n; i++)
                    281:     coeff(y,i,i)=ldivii(d,gcoeff(x,i,i));
                    282:   av=avma;
                    283:   for (i=2; i<=n; i++)
                    284:     for (j=i-1; j; j--)
                    285:     {
                    286:       for (h=gzero,k=j+1; k<=i; k++)
                    287:       {
                    288:         GEN p1 = mulii(gcoeff(y,i,k),gcoeff(x,k,j));
                    289:         if (p1 != gzero) h=addii(h,p1);
                    290:       }
                    291:       setsigne(h,-signe(h)); av1=avma;
                    292:       coeff(y,i,j) = lpile(av,av1,divii(h,gcoeff(x,j,j)));
                    293:       av = avma;
                    294:     }
                    295:   return y;
                    296: }
                    297:
                    298: static GEN
                    299: ordmax(GEN *cf, GEN p, long epsilon, GEN *ptdelta)
                    300: {
                    301:   long sp,hard_case_exponent,i,n=lg(cf)-1,av=avma, av2,limit;
                    302:   GEN T,T2,Tn,m,v,delta, *w;
                    303:   const GEN pp = sqri(p);
                    304:   const long pps = (2*expi(pp)+2<BITS_IN_LONG)? pp[2]: 0;
                    305:
                    306:   if (cmpis(p,n) > 0)
                    307:   {
                    308:     hard_case_exponent = 0;
                    309:     sp = 0; /* gcc -Wall */
                    310:   }
                    311:   else
                    312:   {
                    313:     long k;
                    314:     k = sp = itos(p);
                    315:     i=1; while (k < n) { k *= sp; i++; }
                    316:     hard_case_exponent = i;
                    317:   }
                    318:   T=cgetg(n+1,t_MAT); for (i=1; i<=n; i++) T[i]=lgetg(n+1,t_COL);
                    319:   T2=cgetg(2*n+1,t_MAT); for (i=1; i<=2*n; i++) T2[i]=lgetg(n+1,t_COL);
                    320:   Tn=cgetg(n*n+1,t_MAT); for (i=1; i<=n*n; i++) Tn[i]=lgetg(n+1,t_COL);
                    321:   v = new_chunk(n+1);
                    322:   w =  (GEN*)new_chunk(n+1);
                    323:
                    324:   av2 = avma; limit = stack_lim(av2,1);
                    325:   delta=gun; m=idmat(n);
                    326:
                    327:   for(;;)
                    328:   {
                    329:     long j,k,h, av0 = avma;
                    330:     GEN t,b,jp,hh,index,p1, dd = sqri(delta), ppdd = mulii(dd,pp);
                    331:
                    332:     if (DEBUGLEVEL > 3)
                    333:       fprintferr("ROUND2: epsilon = %ld\tavma = %ld\n",epsilon,avma);
                    334:
                    335:     b=matinv(m,delta,n);
                    336:     for (i=1; i<=n; i++)
                    337:     {
                    338:       for (j=1; j<=n; j++)
                    339:         for (k=1; k<=n; k++)
                    340:         {
                    341:           p1 = j==k? gcoeff(m,i,1): gzero;
                    342:           for (h=2; h<=n; h++)
                    343:           {
                    344:            GEN p2 = mulii(gcoeff(m,i,h),gcoeff(cf[h],j,k));
                    345:             if (p2!=gzero) p1 = addii(p1,p2);
                    346:           }
                    347:           coeff(T,j,k) = (long)rrmdr(p1, ppdd);
                    348:         }
                    349:       p1 = mulmati(m, mulmati(T,b));
                    350:       for (j=1; j<=n; j++)
                    351:        for (k=1; k<=n; k++)
                    352:          coeff(p1,j,k)=(long)rrmdr(divii(gcoeff(p1,j,k),dd),pp);
                    353:       w[i] = p1;
                    354:     }
                    355:
                    356:     if (hard_case_exponent)
                    357:     {
                    358:       for (j=1; j<=n; j++)
                    359:       {
                    360:        for (i=1; i<=n; i++) coeff(T,i,j) = coeff(w[j],1,i);
                    361:        /* ici la boucle en k calcule la puissance p mod p de w[j] */
                    362:        for (k=1; k<sp; k++)
                    363:        {
                    364:          for (i=1; i<=n; i++)
                    365:          {
                    366:            p1 = gzero;
                    367:            for (h=1; h<=n; h++)
                    368:             {
                    369:               GEN p2=mulii(gcoeff(T,h,j),gcoeff(w[j],h,i));
                    370:              if (p2!=gzero) p1 = addii(p1,p2);
                    371:             }
                    372:             v[i] = lmodii(p1, p);
                    373:          }
                    374:          for (i=1; i<=n; i++) coeff(T,i,j)=v[i];
                    375:        }
                    376:       }
                    377:       t = powmati(T, hard_case_exponent);
                    378:     }
                    379:     else
                    380:     {
                    381:       for (i=1; i<=n; i++)
                    382:        for (j=1; j<=n; j++)
                    383:        {
                    384:           long av1 = avma;
                    385:           p1 = gzero;
                    386:          for (k=1; k<=n; k++)
                    387:            for (h=1; h<=n; h++)
                    388:            {
                    389:              const GEN r=modii(gcoeff(w[i],k,h),p);
                    390:              const GEN s=modii(gcoeff(w[j],h,k),p);
                    391:               const GEN p2 = mulii(r,s);
                    392:              if (p2!=gzero) p1 = addii(p1,p2);
                    393:            }
                    394:          coeff(T,i,j) = lpileupto(av1,p1);
                    395:        }
                    396:       t = T;
                    397:     }
                    398:
                    399:     if (pps)
                    400:     {
                    401:       long ps = p[2];
                    402:       for (i=1; i<=n; i++)
                    403:         for (j=1; j<=n; j++)
                    404:         {
                    405:           coeff(T2,j,i)=(i==j)? ps: 0;
                    406:           coeff(T2,j,n+i)=smodis(gcoeff(t,i,j),ps);
                    407:         }
                    408:       rowred_long(T2,pps);
                    409:     }
                    410:     else
                    411:     {
                    412:       for (i=1; i<=n; i++)
                    413:         for (j=1; j<=n; j++)
                    414:         {
                    415:           coeff(T2,j,i)=(i==j)? (long)p: zero;
                    416:           coeff(T2,j,n+i)=lmodii(gcoeff(t,i,j),p);
                    417:         }
                    418:       rowred(T2,pp);
                    419:     }
                    420:     jp=matinv(T2,p,n);
                    421:     if (pps)
                    422:     {
                    423:       for (k=1; k<=n; k++)
                    424:       {
                    425:         long av1=avma;
                    426:         t = mulmati(mulmati(jp,w[k]), T2);
                    427:         for (h=i=1; i<=n; i++)
                    428:           for (j=1; j<=n; j++)
                    429:             { coeff(Tn,k,h) = itos(divii(gcoeff(t,i,j), p)) % pps; h++; }
                    430:         avma=av1;
                    431:       }
                    432:       avma = av0;
                    433:       rowred_long(Tn,pps);
                    434:     }
                    435:     else
                    436:     {
                    437:       for (k=1; k<=n; k++)
                    438:       {
                    439:         t = mulmati(mulmati(jp,w[k]), T2);
                    440:         for (h=i=1; i<=n; i++)
                    441:           for (j=1; j<=n; j++)
                    442:             { coeff(Tn,k,h) = ldivii(gcoeff(t,i,j), p); h++; }
                    443:       }
                    444:       rowred(Tn,pp);
                    445:     }
                    446:     for (index=gun,i=1; i<=n; i++)
                    447:       index = mulii(index,gcoeff(Tn,i,i));
                    448:     if (gcmp1(index)) break;
                    449:
                    450:     m = mulmati(matinv(Tn,index,n), m);
                    451:     hh = delta = mulii(index,delta);
                    452:     for (i=1; i<=n; i++)
                    453:       for (j=1; j<=n; j++)
                    454:         hh = mppgcd(gcoeff(m,i,j),hh);
                    455:     if (!is_pm1(hh))
                    456:     {
                    457:       m = gdiv(m,hh);
                    458:       delta = divii(delta,hh);
                    459:     }
                    460:     epsilon -= 2 * ggval(index,p);
                    461:     if (epsilon < 2) break;
                    462:     if (low_stack(limit,stack_lim(av2,1)))
                    463:     {
                    464:       GEN *gptr[3]; gptr[0]=&m; gptr[1]=&delta;
                    465:       if(DEBUGMEM>1) err(warnmem,"ordmax");
                    466:       gerepilemany(av2, gptr,2);
                    467:     }
                    468:   }
                    469:   {
                    470:     GEN *gptr[2]; gptr[0]=&m; gptr[1]=&delta;
                    471:     gerepilemany(av,gptr,2);
                    472:   }
                    473:   *ptdelta=delta; return m;
                    474: }
                    475:
                    476: /* Input:
                    477:  *  x normalized integral polynomial of degree n, defining K=Q(theta).
                    478:  *
                    479:  *  code 0, 1 or (long)p if we want base, smallbase ou factoredbase (resp.).
                    480:  *  y is GEN *, which will receive the discriminant of K.
                    481:  *
                    482:  * Output
                    483:  *  1) A t_COL whose n components are rationnal polynomials (with degree
                    484:  *     0,1...n-1) : integral basis for K (putting x=theta).
                    485:  *     Rem: common denominator is in da.
                    486:  *
                    487:  *  2) discriminant of K (in *y).
                    488:  */
                    489: GEN
                    490: allbase(GEN f, long code, GEN *y)
                    491: {
                    492:   GEN w1,w2,a,pro,at,bt,b,da,db,q, *cf,*gptr[2];
                    493:   long av=avma,tetpil,n,h,j,i,k,r,s,t,v,mf;
                    494:
                    495:   allbase_check_args(f,code,y, &w1,&w2);
                    496:   v = varn(f); n = degpol(f); h = lg(w1)-1;
                    497:   cf = (GEN*)cgetg(n+1,t_VEC);
                    498:   cf[2]=companion(f);
                    499:   for (i=3; i<=n; i++) cf[i]=mulmati(cf[2],cf[i-1]);
                    500:
                    501:   a=idmat(n); da=gun;
                    502:   for (i=1; i<=h; i++)
                    503:   {
                    504:     long av1 = avma;
                    505:     mf=itos((GEN)w2[i]); if (mf==1) continue;
                    506:     if (DEBUGLEVEL) fprintferr("Treating p^k = %Z^%ld\n",w1[i],mf);
                    507:
                    508:     b=ordmax(cf,(GEN)w1[i],mf,&db);
                    509:     a=gmul(db,a); b=gmul(da,b);
                    510:     da=mulii(db,da);
                    511:     at=gtrans(a); bt=gtrans(b);
                    512:     for (r=n; r; r--)
                    513:       for (s=r; s; s--)
                    514:         while (signe(gcoeff(bt,s,r)))
                    515:         {
                    516:           q=rquot(gcoeff(at,s,s),gcoeff(bt,s,r));
                    517:           pro=rtran((GEN)at[s],(GEN)bt[r],q);
                    518:           for (t=s-1; t; t--)
                    519:           {
                    520:             q=rquot(gcoeff(at,t,s),gcoeff(at,t,t));
                    521:             pro=rtran(pro,(GEN)at[t],q);
                    522:           }
                    523:           at[s]=bt[r]; bt[r]=(long)pro;
                    524:         }
                    525:     for (j=n; j; j--)
                    526:     {
                    527:       for (k=1; k<j; k++)
                    528:       {
                    529:         while (signe(gcoeff(at,j,k)))
                    530:         {
                    531:           q=rquot(gcoeff(at,j,j),gcoeff(at,j,k));
                    532:           pro=rtran((GEN)at[j],(GEN)at[k],q);
                    533:           at[j]=at[k]; at[k]=(long)pro;
                    534:         }
                    535:       }
                    536:       if (signe(gcoeff(at,j,j))<0)
                    537:         for (k=1; k<=j; k++) coeff(at,k,j)=lnegi(gcoeff(at,k,j));
                    538:       for (k=j+1; k<=n; k++)
                    539:       {
                    540:         q=rquot(gcoeff(at,j,k),gcoeff(at,j,j));
                    541:         at[k]=(long)rtran((GEN)at[k],(GEN)at[j],q);
                    542:       }
                    543:     }
                    544:     for (j=2; j<=n; j++)
                    545:       if (egalii(gcoeff(at,j,j), gcoeff(at,j-1,j-1)))
                    546:       {
                    547:         coeff(at,1,j)=zero;
                    548:         for (k=2; k<=j; k++) coeff(at,k,j)=coeff(at,k-1,j-1);
                    549:       }
                    550:     tetpil=avma; a=gtrans(at);
                    551:     {
                    552:       GEN *gptr[2];
                    553:       da = icopy(da); gptr[0]=&a; gptr[1]=&da;
                    554:       gerepilemanysp(av1,tetpil,gptr,2);
                    555:     }
                    556:   }
                    557:   for (j=1; j<=n; j++)
                    558:     *y = divii(mulii(*y,sqri(gcoeff(a,j,j))), sqri(da));
                    559:   tetpil=avma; *y=icopy(*y);
                    560:   at=cgetg(n+1,t_VEC); v=varn(f);
                    561:   for (k=1; k<=n; k++)
                    562:   {
                    563:     q=cgetg(k+2,t_POL); at[k]=(long)q;
                    564:     q[1] = evalsigne(1) | evallgef(2+k) | evalvarn(v);
                    565:     for (j=1; j<=k; j++) q[j+1]=ldiv(gcoeff(a,k,j),da);
                    566:   }
                    567:   gptr[0]=&at; gptr[1]=y;
                    568:   gerepilemanysp(av,tetpil,gptr,2);
                    569:   return at;
                    570: }
                    571:
                    572: GEN
                    573: base2(GEN x, GEN *y)
                    574: {
                    575:   return allbase(x,0,y);
                    576: }
                    577:
                    578: GEN
                    579: discf2(GEN x)
                    580: {
                    581:   GEN y;
                    582:   long av=avma,tetpil;
                    583:
                    584:   allbase(x,0,&y); tetpil=avma;
                    585:   return gerepile(av,tetpil,icopy(y));
                    586: }
                    587:
                    588: /*******************************************************************/
                    589: /*                                                                 */
                    590: /*                            ROUND 4                              */
                    591: /*                                                                 */
                    592: /*******************************************************************/
                    593:
                    594: GEN nilord(GEN p,GEN fx,long mf,GEN gx,long flag);
                    595: GEN Decomp(GEN p,GEN f,long mf,GEN theta,GEN chi,GEN nu,long r);
                    596: static GEN dbasis(GEN p, GEN f, long mf, GEN alpha, GEN U);
                    597: static GEN maxord(GEN p,GEN f,long mf);
                    598: static GEN nbasis(GEN ibas,GEN pd);
                    599: static GEN testb2(GEN p,GEN fa,long Fa,GEN theta,GEN pmf,long Ft,GEN ns);
                    600: static GEN testc2(GEN p,GEN fa,GEN pmr,GEN pmf,GEN alph2,
                    601:                  long Ea,GEN thet2,long Et,GEN ns);
                    602:
                    603: static int
                    604: fnz(GEN x,long j)
                    605: {
                    606:   long i;
                    607:   for (i=1; i<j; i++)
                    608:     if (signe(x[i])) return 0;
                    609:   return 1;
                    610: }
                    611:
                    612: /* retourne la base, dans y le discf et dans ptw la factorisation (peut
                    613:  etre partielle) de discf */
                    614: GEN
                    615: allbase4(GEN f,long code, GEN *y, GEN *ptw)
                    616: {
                    617:   GEN w,w1,w2,a,da,b,db,bas,q,p1,*gptr[3];
                    618:   long v,n,mf,h,lfa,i,j,k,l,tetpil,av = avma;
                    619:
                    620:   allbase_check_args(f,code,y, &w1,&w2);
                    621:   v = varn(f); n = degpol(f); h = lg(w1)-1;
                    622:   a = NULL; /* gcc -Wall */
                    623:   da= NULL;
                    624:   for (i=1; i<=h; i++)
                    625:   {
                    626:     mf=itos((GEN)w2[i]); if (mf == 1) continue;
                    627:     if (DEBUGLEVEL) fprintferr("Treating p^k = %Z^%ld\n",w1[i],mf);
                    628:
                    629:     b = maxord((GEN)w1[i],f,mf); db = gun;
                    630:     for (j=1; j<=n; j++)
                    631:     {
                    632:       p1 = denom(gcoeff(b,j,j));
                    633:       if (cmpii(p1,db) > 0) db = p1;
                    634:     }
                    635:     if (db != gun)
                    636:     { /* db = denom(diag(b)), (da,db) = 1 */
                    637:       b = gmul(b,db);
                    638:       if (!da) { da=db; a=b; }
                    639:       else
                    640:       {
                    641:         j=1; while (j<=n && fnz((GEN)a[j],j) && fnz((GEN)b[j],j)) j++;
                    642:         b = gmul(da,b); a = gmul(db,a);
                    643:         k=j-1; p1=cgetg(2*n-k+1,t_MAT);
                    644:         for (j=1; j<=k; j++)
                    645:         {
                    646:           p1[j] = a[j];
                    647:           coeff(p1,j,j) = lmppgcd(gcoeff(a,j,j),gcoeff(b,j,j));
                    648:         }
                    649:         for (  ; j<=n;     j++) p1[j] = a[j];
                    650:         for (  ; j<=2*n-k; j++) p1[j] = b[j+k-n];
                    651:         da = mulii(da,db); a = hnfmodid(p1, da);
                    652:       }
                    653:     }
                    654:     if (DEBUGLEVEL>5)
                    655:       fprintferr("Result for prime %Z is:\n%Z\n",w1[i],b);
                    656:   }
                    657:   if (da)
                    658:   {
                    659:     for (j=1; j<=n; j++)
                    660:       *y = mulii(divii(*y,sqri(da)),sqri(gcoeff(a,j,j)));
                    661:     for (j=n-1; j; j--)
                    662:       if (cmpis(gcoeff(a,j,j),2) > 0)
                    663:       {
                    664:         p1=shifti(gcoeff(a,j,j),-1);
                    665:         for (k=j+1; k<=n; k++)
                    666:           if (cmpii(gcoeff(a,j,k),p1) > 0)
                    667:             for (l=1; l<=j; l++)
                    668:               coeff(a,l,k)=lsubii(gcoeff(a,l,k),gcoeff(a,l,j));
                    669:       }
                    670:   }
                    671:   lfa = 0;
                    672:   if (ptw)
                    673:   {
                    674:     for (j=1; j<=h; j++)
                    675:     {
                    676:       k=ggval(*y,(GEN)w1[j]);
                    677:       if (k) { lfa++; w1[lfa]=w1[j]; w2[lfa]=k; }
                    678:     }
                    679:   }
                    680:   tetpil=avma; *y=icopy(*y);
                    681:   bas=cgetg(n+1,t_VEC); v=varn(f);
                    682:   for (k=1; k<=n; k++)
                    683:   {
                    684:     q=cgetg(k+2,t_POL); bas[k]=(long)q;
                    685:     q[1] = evalsigne(1) | evallgef(k+2) | evalvarn(v);
                    686:     if (da)
                    687:       for (j=1; j<=k; j++) q[j+1]=ldiv(gcoeff(a,j,k),da);
                    688:     else
                    689:     {
                    690:       for (j=2; j<=k; j++) q[j]=zero;
                    691:       q[j]=un;
                    692:     }
                    693:   }
                    694:   if (ptw)
                    695:   {
                    696:     *ptw=w=cgetg(3,t_MAT);
                    697:     w[1]=lgetg(lfa+1,t_COL);
                    698:     w[2]=lgetg(lfa+1,t_COL);
                    699:     for (j=1; j<=lfa; j++)
                    700:     {
                    701:       coeff(w,j,1)=(long)icopy((GEN)w1[j]);
                    702:       coeff(w,j,2)=lstoi(w2[j]);
                    703:     }
                    704:     gptr[2]=ptw;
                    705:   }
                    706:   gptr[0]=&bas; gptr[1]=y;
                    707:   gerepilemanysp(av,tetpil,gptr, ptw?3:2);
                    708:   return bas;
                    709: }
                    710:
                    711: extern GEN merge_factor_i(GEN f, GEN g);
                    712:
                    713: static GEN
                    714: update_fact(GEN x, GEN f)
                    715: {
                    716:   GEN e,q,d = ZX_disc(x), g = cgetg(3, t_MAT), p = (GEN)f[1];
                    717:   long iq,i,k,l;
                    718:   if (typ(f)!=t_MAT || lg(f)!=3)
                    719:     err(talker,"not a factorisation in nfbasis");
                    720:   l = lg(p);
                    721:   q = cgetg(l,t_COL); g[1]=(long)q;
                    722:   e = cgetg(l,t_COL); g[2]=(long)e; iq = 1;
                    723:   for (i=1; i<l; i++)
                    724:   {
                    725:     k = pvaluation(d, (GEN)p[i], &d);
                    726:     if (k) { q[iq] = p[i]; e[iq] = lstoi(k); iq++; }
                    727:   }
                    728:   setlg(q,iq); setlg(e,iq);
                    729:   return merge_factor_i(decomp(d), g);
                    730: }
                    731:
                    732: /* if y is non-NULL, it receives the discriminant
                    733:  * return basis if (ret_basis != 0), discriminant otherwise
                    734:  */
                    735: static GEN
                    736: nfbasis00(GEN x0, long flag, GEN p, long ret_basis, GEN *y)
                    737: {
                    738:   GEN x, disc, basis, lead;
                    739:   GEN *gptr[2];
                    740:   long k, tetpil, av = avma, l = lgef(x0), smll;
                    741:
                    742:   if (typ(x0)!=t_POL) err(typeer,"nfbasis00");
                    743:   if (l<=3) err(zeropoler,"nfbasis00");
                    744:   for (k=2; k<l; k++)
                    745:     if (typ(x0[k])!=t_INT) err(talker,"polynomial not in Z[X] in nfbasis");
                    746:
                    747:   x = pol_to_monic(x0,&lead);
                    748:
                    749:   if (!p || gcmp0(p))
                    750:     smll = (flag & 1); /* small basis */
                    751:   else
                    752:   {
                    753:     if (lead) p = update_fact(x,p);
                    754:     smll = (long) p;   /* factored basis */
                    755:   }
                    756:
                    757:   if (flag & 2)
                    758:     basis = allbase(x,smll,&disc); /* round 2 */
                    759:   else
                    760:     basis = allbase4(x,smll,&disc,NULL); /* round 4 */
                    761:
                    762:   if (!ret_basis) return gerepilecopy(av,disc);
                    763:
                    764:   tetpil=avma;
                    765:   if (!lead) basis = gcopy(basis);
                    766:   else
                    767:   {
                    768:     long v = varn(x);
                    769:     GEN pol = gmul(polx[v],lead);
                    770:
                    771:     tetpil = avma; basis = gsubst(basis,v,pol);
                    772:   }
                    773:   if (!y)
                    774:     return gerepile(av,tetpil,basis);
                    775:
                    776:   *y = gcopy(disc);
                    777:   gptr[0]=&basis; gptr[1]=y;
                    778:   gerepilemanysp(av,tetpil,gptr,2);
                    779:   return basis;
                    780: }
                    781:
                    782: GEN
                    783: nfbasis(GEN x, GEN *y, long flag, GEN p)
                    784: {
                    785:   return nfbasis00(x,flag,p,1,y);
                    786: }
                    787:
                    788: GEN
                    789: nfbasis0(GEN x, long flag, GEN p)
                    790: {
                    791:   return nfbasis00(x,flag,p,1,NULL);
                    792: }
                    793:
                    794: GEN
                    795: nfdiscf0(GEN x, long flag, GEN p)
                    796: {
                    797:   return nfbasis00(x,flag,p,0,&p);
                    798: }
                    799:
                    800: GEN
                    801: base(GEN x, GEN *y)
                    802: {
                    803:   return allbase4(x,0,y,NULL);
                    804: }
                    805:
                    806: GEN
                    807: smallbase(GEN x, GEN *y)
                    808: {
                    809:   return allbase4(x,1,y,NULL);
                    810: }
                    811:
                    812: GEN
                    813: factoredbase(GEN x, GEN p, GEN *y)
                    814: {
                    815:   return allbase4(x,(long)p,y,NULL);
                    816: }
                    817:
                    818: GEN
                    819: discf(GEN x)
                    820: {
                    821:   GEN y;
                    822:   long av=avma,tetpil;
                    823:
                    824:   allbase4(x,0,&y,NULL); tetpil=avma;
                    825:   return gerepile(av,tetpil,icopy(y));
                    826: }
                    827:
                    828: GEN
                    829: smalldiscf(GEN x)
                    830: {
                    831:   GEN y;
                    832:   long av=avma,tetpil;
                    833:
                    834:   allbase4(x,1,&y,NULL); tetpil=avma;
                    835:   return gerepile(av,tetpil,icopy(y));
                    836: }
                    837:
                    838: GEN
                    839: factoreddiscf(GEN x, GEN p)
                    840: {
                    841:   GEN y;
                    842:   long av=avma,tetpil;
                    843:
                    844:   allbase4(x,(long)p,&y,NULL); tetpil=avma;
                    845:   return gerepile(av,tetpil,icopy(y));
                    846: }
                    847:
                    848: /* return U if Z[alpha] is not maximal or 2*dU < m-1; else return NULL */
                    849: static GEN
                    850: dedek(GEN f, long mf, GEN p,GEN g)
                    851: {
                    852:   GEN k,h;
                    853:   long dk;
                    854:
                    855:   if (DEBUGLEVEL>=3)
                    856:   {
                    857:     fprintferr("  entering dedek ");
                    858:     if (DEBUGLEVEL>5)
                    859:       fprintferr("with parameters p=%Z,\n  f=%Z",p,f);
                    860:     fprintferr("\n");
                    861:   }
                    862:   h = FpX_div(f,g,p);
                    863:   k = gdivexact(gadd(f, gneg_i(gmul(g,h))), p);
                    864:   k = FpX_gcd(k, FpX_gcd(g,h, p), p);
                    865:
                    866:   dk = degpol(k);
                    867:   if (DEBUGLEVEL>=3) fprintferr("  gcd has degree %ld\n", dk);
                    868:   if (2*dk >= mf-1) return FpX_div(f,k,p);
                    869:   return dk? (GEN)NULL: f;
                    870: }
                    871:
                    872: /* p-maximal order of Af; mf = v_p(Disc(f)) */
                    873: static GEN
                    874: maxord(GEN p,GEN f,long mf)
                    875: {
                    876:   long j,r, av = avma, flw = (cmpsi(degpol(f),p) < 0);
                    877:   GEN w,g,h,res;
                    878:
                    879:   if (flw)
                    880:   {
                    881:     h = NULL; r = 0; /* gcc -Wall */
                    882:     g = FpX_div(f, FpX_gcd(f,derivpol(f), p), p);
                    883:   }
                    884:   else
                    885:   {
                    886:     w=(GEN)factmod(f,p)[1]; r=lg(w)-1;
                    887:     g = h = lift_intern((GEN)w[r]); /* largest factor */
                    888:     for (j=1; j<r; j++) g = FpX_red(gmul(g, lift_intern((GEN)w[j])), p);
                    889:   }
                    890:   res = dedek(f,mf,p,g);
                    891:   if (res)
                    892:     res = dbasis(p,f,mf,polx[varn(f)],res);
                    893:   else
                    894:   {
                    895:     if (flw) { w=(GEN)factmod(f,p)[1]; r=lg(w)-1; h=lift_intern((GEN)w[r]); }
                    896:     res = (r==1)? nilord(p,f,mf,h,0): Decomp(p,f,mf,polx[varn(f)],f,h,0);
                    897:   }
                    898:   return gerepileupto(av,res);
                    899: }
                    900:
                    901: /* do a centermod on integer or rational number */
                    902: static GEN
                    903: polmodiaux(GEN x, GEN y, GEN ys2)
                    904: {
                    905:   if (typ(x)!=t_INT)
                    906:     x = mulii((GEN)x[1], mpinvmod((GEN)x[2],y));
                    907:   x = modii(x,y);
                    908:   if (cmpii(x,ys2) > 0) x = subii(x,y);
                    909:   return x;
                    910: }
                    911:
                    912: /* x polynomial with integer or rational coeff. Reduce them mod y IN PLACE */
                    913: GEN
                    914: polmodi(GEN x, GEN y)
                    915: {
                    916:   long lx=lgef(x), i;
                    917:   GEN ys2 = shifti(y,-1);
                    918:   for (i=2; i<lx; i++) x[i]=(long)polmodiaux((GEN)x[i],y,ys2);
                    919:   return normalizepol_i(x, lx);
                    920: }
                    921:
                    922: /* same but not in place */
                    923: GEN
                    924: polmodi_keep(GEN x, GEN y)
                    925: {
                    926:   long lx=lgef(x), i;
                    927:   GEN ys2 = shifti(y,-1);
                    928:   GEN z = cgetg(lx,t_POL);
                    929:   for (i=2; i<lx; i++) z[i]=(long)polmodiaux((GEN)x[i],y,ys2);
                    930:   z[1]=x[1]; return normalizepol_i(z, lx);
                    931: }
                    932:
                    933: static GEN
                    934: dbasis(GEN p, GEN f, long mf, GEN alpha, GEN U)
                    935: {
                    936:   long n=degpol(f),dU,c;
                    937:   GEN b,ha,pd,pdp;
                    938:
                    939:   if (n == 1) return gscalmat(gun, 1);
                    940:   if (DEBUGLEVEL>=3)
                    941:   {
                    942:     fprintferr("  entering Dedekind Basis ");
                    943:     if (DEBUGLEVEL>5)
                    944:     {
                    945:       fprintferr("with parameters p=%Z\n",p);
                    946:       fprintferr("  f = %Z,\n  alpha = %Z",f,alpha);
                    947:     }
                    948:     fprintferr("\n");
                    949:   }
                    950:   ha = pd = gpuigs(p,mf/2); pdp = mulii(pd,p);
                    951:   dU = typ(U)==t_POL? degpol(U): 0;
                    952:   b = cgetg(n,t_MAT); /* Z[a] + U/p Z[a] is maximal */
                    953:   /* skip first column = gscalcol(pd,n) */
                    954:   for (c=1; c<n; c++)
                    955:   {
                    956:     if (c == dU)
                    957:     {
                    958:       ha = gdiv(gmul(pd,eleval(f,U,alpha)),p);
                    959:       ha = polmodi(ha,pdp);
                    960:     }
                    961:     else
                    962:     {
                    963:       GEN p2, mod;
                    964:       ha = gmul(ha,alpha);
                    965:       p2 = content(ha); /* to cancel denominator */
                    966:       if (gcmp1(p2)) { p2 = NULL; mod = pdp; }
                    967:       else
                    968:       {
                    969:         ha = gdiv(ha,p2);
                    970:         if (typ(p2)==t_INT)
                    971:           mod = divii(pdp, mppgcd(pdp,p2));
                    972:         else
                    973:           mod = mulii(pdp, (GEN)p2[2]); /* p2 = a / p^e */
                    974:       }
                    975:       ha = FpX_res(ha, f, mod);
                    976:       if (p2) ha = gmul(ha,p2);
                    977:     }
                    978:     b[c] = (long)pol_to_vec(ha,n);
                    979:   }
                    980:   b = hnfmodid(b,pd);
                    981:   if (DEBUGLEVEL>5) fprintferr("  new order: %Z\n",b);
                    982:   return gdiv(b,pd);
                    983: }
                    984:
                    985: static GEN
                    986: get_partial_order_as_pols(GEN p, GEN f)
                    987: {
                    988:   long i,j, n = degpol(f), vf = varn(f);
                    989:   GEN b,ib,h,col;
                    990:
                    991:   b = maxord(p,f, ggval(ZX_disc(f),p));
                    992:   ib = cgetg(n+1,t_VEC);
                    993:   for (i=1; i<=n; i++)
                    994:   {
                    995:     h=cgetg(i+2,t_POL); ib[i]=(long)h; col=(GEN)b[i];
                    996:     h[1]=evalsigne(1)|evallgef(i+2)|evalvarn(vf);
                    997:     for (j=1;j<=i;j++) h[j+1]=col[j];
                    998:   }
                    999:   return ib;
                   1000: }
                   1001:
                   1002: /* if flag != 0, factorization to precision r (maximal order otherwise) */
                   1003: GEN
                   1004: Decomp(GEN p,GEN f,long mf,GEN theta,GEN chi,GEN nu,long flag)
                   1005: {
                   1006:   GEN res,pr,pk,ph,pdr,unmodp,b1,b2,b3,a1,e,f1,f2;
                   1007:
                   1008:   if (DEBUGLEVEL>2)
                   1009:   {
                   1010:     fprintferr("  entering Decomp ");
                   1011:     if (DEBUGLEVEL>5)
                   1012:     {
                   1013:       fprintferr("with parameters: p=%Z, expo=%ld\n",p,mf);
                   1014:       if (flag) fprintferr("precision = %ld\n",flag);
                   1015:       fprintferr("  f=%Z",f);
                   1016:     }
                   1017:     fprintferr("\n");
                   1018:   }
                   1019:   unmodp = gmodulsg(1,p);
                   1020:   b1=lift_intern(gmul(chi,unmodp));
                   1021:   a1=gun; b2=gun;
                   1022:   b3=lift_intern(gmul(nu,unmodp));
                   1023:   while (degpol(b3) > 0)
                   1024:   {
                   1025:     GEN p1;
                   1026:     b1 = FpX_div(b1,b3, p);
                   1027:     b2 = FpX_red(gmul(b2,b3), p);
                   1028:     b3 = FpX_extgcd(b2,b1, p, &a1,&p1); /* p1 = junk */
                   1029:     p1 = leading_term(b3);
                   1030:     if (!gcmp1(p1))
                   1031:     { /* FpX_extgcd does not return normalized gcd */
                   1032:       p1 = mpinvmod(p1,p);
                   1033:       b3 = gmul(b3,p1);
                   1034:       a1 = gmul(a1,p1);
                   1035:     }
                   1036:   }
                   1037:   pdr = respm(f,derivpol(f),gpuigs(p,mf+1));
                   1038:   e = eleval(f,FpX_red(gmul(a1,b2), p),theta);
                   1039:   e = gdiv(polmodi(gmul(pdr,e), mulii(pdr,p)),pdr);
                   1040:
                   1041:   pr = flag? gpowgs(p,flag): mulii(p,sqri(pdr));
                   1042:   pk=p; ph=mulii(pdr,pr);
                   1043:   /* E(t) - e(t) belongs to p^k Op, which is contained in p^(k-df)*Zp[xi] */
                   1044:   while (cmpii(pk,ph) < 0)
                   1045:   {
                   1046:     e = gmul(gsqr(e), gsubsg(3,gmul2n(e,1)));
                   1047:     e = gres(e,f); pk = sqri(pk);
                   1048:     e = gdiv(polmodi(gmul(pdr,e), mulii(pdr,pk)), pdr);
                   1049:   }
                   1050:   f1 = gcdpm(f,gmul(pdr,gsubsg(1,e)), ph);
                   1051:   f1 = FpX_res(f1,f, pr);
                   1052:   f2 = FpX_res(FpX_div(f,f1, pr), f, pr);
                   1053:
                   1054:   if (DEBUGLEVEL>2)
                   1055:   {
                   1056:     fprintferr("  leaving Decomp");
                   1057:     if (DEBUGLEVEL>5)
                   1058:       fprintferr(" with parameters: f1 = %Z\nf2 = %Z\ne = %Z\n", f1,f2,e);
                   1059:     fprintferr("\n");
                   1060:   }
                   1061:
                   1062:   if (flag)
                   1063:   {
                   1064:     b1=factorpadic4(f1,p,flag);
                   1065:     b2=factorpadic4(f2,p,flag); res=cgetg(3,t_MAT);
                   1066:     res[1]=lconcat((GEN)b1[1],(GEN)b2[1]);
                   1067:     res[2]=lconcat((GEN)b1[2],(GEN)b2[2]); return res;
                   1068:   }
                   1069:   else
                   1070:   {
                   1071:     GEN ib1,ib2;
                   1072:     long n1,n2,i;
                   1073:     ib1 = get_partial_order_as_pols(p,f1); n1=lg(ib1)-1;
                   1074:     ib2 = get_partial_order_as_pols(p,f2); n2=lg(ib2)-1;
                   1075:     res=cgetg(n1+n2+1,t_VEC);
                   1076:     for (i=1; i<=n1; i++)
                   1077:       res[i]=(long)polmodi(gmod(gmul(gmul(pdr,(GEN)ib1[i]),e),f), pdr);
                   1078:     e=gsubsg(1,e); ib2 -= n1;
                   1079:     for (   ; i<=n1+n2; i++)
                   1080:       res[i]=(long)polmodi(gmod(gmul(gmul(pdr,(GEN)ib2[i]),e),f), pdr);
                   1081:     return nbasis(res,pdr);
                   1082:   }
                   1083: }
                   1084:
                   1085: /* minimum extension valuation: res[0]/res[1] (both are longs) */
                   1086: static long *
                   1087: vstar(GEN p,GEN h)
                   1088: {
                   1089:   static long res[2];
                   1090:   long m,first,j,k,v,w;
                   1091:
                   1092:   m=degpol(h); first=1; k=1; v=0;
                   1093:   for (j=1; j<=m; j++)
                   1094:     if (! gcmp0((GEN)h[m-j+2]))
                   1095:     {
                   1096:       w = ggval((GEN)h[m-j+2],p);
                   1097:       if (first || w*k < v*j) { v=w; k=j; }
                   1098:       first=0;
                   1099:     }
                   1100:   m = cgcd(v,k);
                   1101:   res[0]=v/m; res[1]=k/m; return res;
                   1102: }
                   1103:
                   1104: /* reduce the element elt modulo rd, taking first care of the denominators */
                   1105: static GEN
                   1106: redelt(GEN elt, GEN rd, GEN pd)
                   1107: {
                   1108:   GEN den, nelt, nrd, relt;
                   1109:
                   1110:   den  = ggcd(denom(content(elt)), pd);
                   1111:   nelt = gmul(den, elt);
                   1112:   nrd  = gmul(den, rd);
                   1113:
                   1114:   if (typ(elt) == t_POL)
                   1115:     relt = polmodi(nelt, nrd);
                   1116:   else
                   1117:     relt = centermod(nelt, nrd);
                   1118:
                   1119:   return gdiv(relt, den);
                   1120: }
                   1121:
                   1122: /* compute the Newton sums of g(x) mod pp from its coefficients */
                   1123: GEN
                   1124: polsymmodpp(GEN g, GEN pp)
                   1125: {
                   1126:   long av1, av2, d = degpol(g), i, k;
                   1127:   GEN s , y;
                   1128:
                   1129:   y = cgetg(d + 1, t_COL);
                   1130:   y[1] = lstoi(d);
                   1131:   for (k = 1; k < d; k++)
                   1132:   {
                   1133:     av1 = avma;
                   1134:     s = centermod(gmulsg(k, polcoeff0(g,d-k,-1)), pp);
                   1135:     for (i = 1; i < k; i++)
                   1136:       s = gadd(s, gmul((GEN)y[k-i+1], polcoeff0(g,d-i,-1)));
                   1137:     av2 = avma;
                   1138:     y[k + 1] = lpile(av1, av2, centermod(gneg(s), pp));
                   1139:   }
                   1140:
                   1141:   return y;
                   1142: }
                   1143:
                   1144: /* no GC */
                   1145: static GEN
                   1146: manage_cache(GEN chi, GEN pp, GEN ns)
                   1147: {
                   1148:   long j, n = degpol(chi);
                   1149:   GEN ns2, npp = (GEN)ns[n+1];
                   1150:
                   1151:   if (gcmp(pp, npp) > 0)
                   1152:   {
                   1153:     if (DEBUGLEVEL > 4)
                   1154:       fprintferr("newtonsums: result too large to fit in cache\n");
                   1155:     return polsymmodpp(chi, pp);
                   1156:   }
                   1157:
                   1158:   if (!signe((GEN)ns[1]))
                   1159:   {
                   1160:     ns2 = polsymmodpp(chi, pp);
                   1161:     for (j = 1; j <= n; j++)
                   1162:       affii((GEN)ns2[j], (GEN)ns[j]);
                   1163:   }
                   1164:
                   1165:   return ns;
                   1166: }
                   1167:
                   1168: /* compute the Newton sums modulo pp of the characteristic
                   1169:    polynomial of a(x) mod g(x) */
                   1170: static GEN
                   1171: newtonsums(GEN a, GEN chi, GEN pp, GEN ns)
                   1172: {
                   1173:   GEN va, pa, s, ns2;
                   1174:   long j, k, n = degpol(chi), av2, lim;
                   1175:
                   1176:   ns2 = manage_cache(chi, pp, ns);
                   1177:
                   1178:   av2 = avma;
                   1179:   lim = stack_lim(av2, 1);
                   1180:
                   1181:   pa = gun;
                   1182:   va = zerovec(n);
                   1183:
                   1184:   for (j = 1; j <= n; j++)
                   1185:   {
                   1186:     pa = gmul(pa, a);
                   1187:     if (pp) pa = polmodi(pa, pp);
                   1188:     pa = gmod(pa, chi);
                   1189:     if (pp) pa = polmodi(pa, pp);
                   1190:
                   1191:     s  = gzero;
                   1192:
                   1193:     for (k = 0; k <= n-1; k++)
                   1194:       s = addii(s, mulii(polcoeff0(pa, k, -1), (GEN)ns2[k+1]));
                   1195:
                   1196:     if (pp) va[j] = (long)centermod(s, pp);
                   1197:
                   1198:     if (low_stack(lim, stack_lim(av2, 1)))
                   1199:     {
                   1200:       GEN *gptr[2];
                   1201:       gptr[0]=&pa; gptr[1]=&va;
                   1202:       if(DEBUGMEM>1) err(warnmem, "newtonsums");
                   1203:       gerepilemany(av2, gptr, 2);
                   1204:     }
                   1205:   }
                   1206:
                   1207:   return va;
                   1208: }
                   1209:
                   1210: /* compute the characteristic polynomial of a mod g
                   1211:    to a precision of pp using Newton sums */
                   1212: static GEN
                   1213: newtoncharpoly(GEN a, GEN chi, GEN pp, GEN ns)
                   1214: {
                   1215:   GEN v, c, s, t;
                   1216:   long n = degpol(chi), j, k, vn = varn(chi), av = avma, av2, lim;
                   1217:
                   1218:   v = newtonsums(a, chi, pp, ns);
                   1219:   av2 = avma;
                   1220:   lim = stack_lim(av2, 1);
                   1221:   c = cgetg(n + 2, t_VEC);
                   1222:   c[1] = un;
                   1223:   if (n%2) c[1] = lneg((GEN)c[1]);
                   1224:   for (k = 2; k <= n+1; k++) c[k] = zero;
                   1225:
                   1226:   for (k = 2; k <= n+1; k++)
                   1227:   {
                   1228:     s = gzero;
                   1229:     for (j = 1; j < k; j++)
                   1230:     {
                   1231:       t = gmul((GEN)v[j], (GEN)c[k-j]);
                   1232:       if (!(j%2)) t = gneg(t);
                   1233:       s = gadd(s, t);
                   1234:     }
                   1235:     c[k] = ldiv(s, stoi(k - 1));
                   1236:
                   1237:     if (low_stack(lim, stack_lim(av2, 1)))
                   1238:     {
                   1239:       if(DEBUGMEM>1) err(warnmem, "newtoncharpoly");
                   1240:       c = gerepilecopy(av2, c);
                   1241:     }
                   1242:   }
                   1243:
                   1244:   k = (n%2)? 1: 2;
                   1245:   for (  ; k <= n+1; k += 2)
                   1246:     c[k] = lneg((GEN)c[k]);
                   1247:
                   1248:   return gerepileupto(av, gtopoly(c, vn));
                   1249: }
                   1250:
                   1251: static GEN
                   1252: mycaract(GEN f, GEN beta, GEN p, GEN pp, GEN ns)
                   1253: {
                   1254:   GEN p1, p2, chi, chi2, npp;
                   1255:   long j, a, v = varn(f), n = degpol(f);
                   1256:
                   1257:   if (gcmp0(beta)) return zeropol(v);
                   1258:
                   1259:   p1 = content(beta);
                   1260:   if (gcmp1(p1)) p1 = NULL;
                   1261:   else beta = gdiv(beta, p1);
                   1262:
                   1263:   if (!pp)
                   1264:     chi = caractducos(f, beta, v);
                   1265:   else
                   1266:   {
                   1267:     a = 0;
                   1268:     for (j = 1; j <= n; j++) /* compute the extra precision needed */
                   1269:       a += ggval(stoi(j), p);
                   1270:     npp = mulii(pp, gpowgs(p, a));
                   1271:     if (p1) npp = gmul(npp, gpowgs(denom(p1), n));
                   1272:
                   1273:     chi = newtoncharpoly(beta, f, npp, ns);
                   1274:   }
                   1275:
                   1276:   if (p1)
                   1277:   {
                   1278:     chi2 = cgetg(n+3, t_POL);
                   1279:     chi2[1] = chi[1];
                   1280:     p2 = gun;
                   1281:     for (j = n+2; j >= 2; j--)
                   1282:     {
                   1283:       chi2[j] = lmul((GEN)chi[j], p2);
                   1284:       p2 = gmul(p2, p1);
                   1285:     }
                   1286:   }
                   1287:   else
                   1288:     chi2 = chi;
                   1289:
                   1290:   if (!pp) return chi2;
                   1291:
                   1292:   /* this can happen only if gamma is incorrect (not an integer) */
                   1293:   if (divise(denom(content(chi2)), p)) return NULL;
                   1294:
                   1295:   return redelt(chi2, pp, pp);
                   1296: }
                   1297:
                   1298: /* Factor characteristic polynomial of beta mod p */
                   1299: static GEN
                   1300: factcp(GEN p, GEN f, GEN beta, GEN pp, GEN ns)
                   1301: {
                   1302:   long av,l;
                   1303:   GEN chi,nu, b = cgetg(4,t_VEC);
                   1304:
                   1305:   chi=mycaract(f,beta,p,pp,ns);
                   1306:   av=avma; nu=(GEN)factmod(chi,p)[1]; l=lg(nu)-1;
                   1307:   nu=lift_intern((GEN)nu[1]);
                   1308:   b[1]=(long)chi;
                   1309:   b[2]=lpilecopy(av,nu);
                   1310:   b[3]=lstoi(l); return b;
                   1311: }
                   1312:
                   1313: /* return the prime element in Zp[phi] */
                   1314: static GEN
                   1315: getprime(GEN p, GEN chi, GEN phi, GEN chip, GEN nup, long *Lp, long *Ep)
                   1316: {
                   1317:   long v = varn(chi), L, E, r, s;
                   1318:   GEN chin, pip, pp, vn;
                   1319:
                   1320:   if (gegal(nup, polx[v]))
                   1321:     chin = chip;
                   1322:   else
                   1323:     chin = mycaract(chip, nup, p, NULL, NULL);
                   1324:
                   1325:   vn = vstar(p, chin);
                   1326:   L  = vn[0];
                   1327:   E  = vn[1];
                   1328:
                   1329:   cbezout(L, -E, &r, &s);
                   1330:
                   1331:   if (r <= 0)
                   1332:   {
                   1333:     long q = (-r) / E;
                   1334:     q++;
                   1335:     r += q*E;
                   1336:     s += q*L;
                   1337:   }
                   1338:
                   1339:   pip = eleval(chi, nup, phi);
                   1340:   pip = lift_intern(gpuigs(gmodulcp(pip, chi), r));
                   1341:   pp  = gpuigs(p, s);
                   1342:
                   1343:   *Lp = L;
                   1344:   *Ep = E;
                   1345:   return gdiv(pip, pp);
                   1346: }
                   1347:
                   1348: static GEN
                   1349: update_alpha(GEN p, GEN fx, GEN alph, GEN chi, GEN pmr, GEN pmf, long mf,
                   1350:             GEN ns)
                   1351: {
                   1352:   long l, v = varn(fx);
                   1353:   GEN nalph = NULL, nchi, w, nnu, pdr, npmr, rep;
                   1354:
                   1355:   affii(gzero, (GEN)ns[1]); /* kill cache */
                   1356:
                   1357:   if (!chi)
                   1358:     nchi = mycaract(fx, alph, p, pmf, ns);
                   1359:   else
                   1360:   {
                   1361:     nchi  = chi;
                   1362:     nalph = alph;
                   1363:   }
                   1364:
                   1365:   pdr = respm(nchi, derivpol(nchi), pmr);
                   1366:   for (;;)
                   1367:   {
                   1368:     if (signe(pdr)) break;
                   1369:     if (!nalph) nalph = gadd(alph, gmul(p, polx[v]));
                   1370:     /* nchi was too reduced at this point */
                   1371:     nchi = mycaract(fx, nalph, NULL, NULL, ns);
                   1372:     pdr = respm(nchi, derivpol(nchi), pmf);
                   1373:     if (signe(pdr)) break;
                   1374:     if (DEBUGLEVEL >= 6)
                   1375:       fprintferr("  non separable polynomial in update_alpha!\n");
                   1376:     /* at this point, we assume that chi is not square-free */
                   1377:     nalph = gadd(nalph, gmul(p, polx[v]));
                   1378:     w = factcp(p, fx, nalph, NULL, ns);
                   1379:     nchi = (GEN)w[1];
                   1380:     nnu  = (GEN)w[2];
                   1381:     l    = itos((GEN)w[3]);
                   1382:     if (l > 1) return Decomp(p, fx, mf, nalph, nchi, nnu, 0);
                   1383:     pdr = respm(nchi, derivpol(nchi), pmr);
                   1384:   }
                   1385:
                   1386:   if (is_pm1(pdr))
                   1387:     npmr = gun;
                   1388:   else
                   1389:   {
                   1390:     npmr  = mulii(sqri(pdr), p);
                   1391:     nchi  = polmodi(nchi, npmr);
                   1392:     if (!nalph) nalph = redelt(alph, npmr, pmf);
                   1393:     else nalph = redelt(nalph, npmr, pmf);
                   1394:   }
                   1395:
                   1396:   affii(gzero, (GEN)ns[1]); /* kill cache again (contains data for fx) */
                   1397:
                   1398:   rep = cgetg(5, t_VEC);
                   1399:   rep[1] = (long)nalph;
                   1400:   rep[2] = (long)nchi;
                   1401:   rep[3] = (long)npmr;
                   1402:   rep[4] = lmulii(p, pdr);
                   1403:
                   1404:   return rep;
                   1405: }
                   1406:
                   1407: extern GEN Fp_factor_irred(GEN P,GEN l, GEN Q);
                   1408:
                   1409: /* flag != 0 iff we're looking for the p-adic factorization,
                   1410:    in which case it is the p-adic precision we want */
                   1411: GEN
                   1412: nilord(GEN p, GEN fx, long mf, GEN gx, long flag)
                   1413: {
                   1414:   long Fa, La, Ea, oE, Fg, eq, er, v = varn(fx), i, nv, Le, Ee, N, l, vn;
                   1415:   GEN p1, alph, chi, nu, w, phi, pmf, pdr, pmr, kapp, pie, chib, ns;
                   1416:   GEN gamm, chig, nug, delt, beta, eta, chie, nue, pia, vb, opa;
                   1417:
                   1418:   if (DEBUGLEVEL >= 3)
                   1419:   {
                   1420:     if (flag)
                   1421:       fprintferr("  entering Nilord2 (factorization)");
                   1422:     else
                   1423:       fprintferr("  entering Nilord2 (basis/discriminant)");
                   1424:     if (DEBUGLEVEL >= 5)
                   1425:     {
                   1426:       fprintferr(" with parameters: p = %Z, expo = %ld\n", p, mf);
                   1427:       fprintferr("  fx = %Z, gx = %Z", fx, gx);
                   1428:     }
                   1429:     fprintferr("\n");
                   1430:   }
                   1431:
                   1432:   pmf = gpowgs(p, mf + 1);
                   1433:   pdr = respm(fx, derivpol(fx), pmf);
                   1434:   pmr = mulii(sqri(pdr), p);
                   1435:   pdr = mulii(p, pdr);
                   1436:   chi = polmodi_keep(fx, pmr);
                   1437:
                   1438:   alph = polx[v];
                   1439:   nu = gx;
                   1440:   N  = degpol(fx);
                   1441:   oE = 0;
                   1442:   opa = NULL;
                   1443:
                   1444:   /* used to cache the newton sums of chi */
                   1445:   ns = cgetg(N + 2, t_COL);
                   1446:   p1 = powgi(p, gceil(gdivsg(N, mulii(p, subis(p, 1))))); /* p^(N/(p(p-1))) */
                   1447:   p1 = mulii(p1, mulii(pmf, gpowgs(pmr, N)));
                   1448:   l  = lg(p1); /* enough in general... */
                   1449:   for (i = 1; i <= N + 1; i++) ns[i] = lgeti(l);
                   1450:   ns[N+1] = (long)p1;
                   1451:   affii(gzero, (GEN)ns[1]); /* zero means: need to be computed */
                   1452:
                   1453:   for(;;)
                   1454:   {
                   1455:     /* kappa need to be recomputed */
                   1456:     kapp = NULL;
                   1457:     Fa   = degpol(nu);
                   1458:     /* the prime element in Zp[alpha] */
                   1459:     pia  = getprime(p, chi, polx[v], chi, nu, &La, &Ea);
                   1460:     pia  = redelt(pia, pmr, pmf);
                   1461:
                   1462:     if (Ea < oE)
                   1463:     {
                   1464:       alph = gadd(alph, opa);
                   1465:       w = update_alpha(p, fx, alph, NULL, pmr, pmf, mf, ns);
                   1466:       alph = (GEN)w[1];
                   1467:       chi  = (GEN)w[2];
                   1468:       pmr  = (GEN)w[3];
                   1469:       pdr  = (GEN)w[4];
                   1470:       kapp = NULL;
                   1471:       pia  = getprime(p, chi, polx[v], chi, nu, &La, &Ea);
                   1472:       pia  = redelt(pia, pmr, pmf);
                   1473:     }
                   1474:
                   1475:     oE = Ea; opa = eleval(fx, pia, alph);
                   1476:
                   1477:     if (DEBUGLEVEL >= 5)
                   1478:       fprintferr("  Fa = %ld and Ea = %ld \n", Fa, Ea);
                   1479:
                   1480:     /* we change alpha such that nu = pia */
                   1481:     if (La > 1)
                   1482:     {
                   1483:       alph = gadd(alph, eleval(fx, pia, alph));
                   1484:
                   1485:       w = update_alpha(p, fx, alph, NULL, pmr, pmf, mf, ns);
                   1486:       alph = (GEN)w[1];
                   1487:       chi  = (GEN)w[2];
                   1488:       pmr  = (GEN)w[3];
                   1489:       pdr  = (GEN)w[4];
                   1490:     }
                   1491:
                   1492:     /* if Ea*Fa == N then O = Zp[alpha] */
                   1493:     if (Ea*Fa == N)
                   1494:     {
                   1495:       if (flag) return NULL;
                   1496:
                   1497:       alph = redelt(alph, sqri(p), pmf);
                   1498:       return dbasis(p, fx, mf, alph, p);
                   1499:     }
                   1500:
                   1501:     /* during the process beta tends to a factor of chi */
                   1502:     beta  = lift_intern(gpowgs(gmodulcp(nu, chi), Ea));
                   1503:
                   1504:     for (;;)
                   1505:     {
                   1506:       if (DEBUGLEVEL >= 5)
                   1507:        fprintferr("  beta = %Z\n", beta);
                   1508:
                   1509:       /* if pmf divides norm(beta) then it's useless */
                   1510:       p1 = gmod(gnorm(gmodulcp(beta, chi)), pmf);
                   1511:       if (signe(p1))
                   1512:       {
                   1513:        chib = NULL;
                   1514:        vn = ggval(p1, p);
                   1515:        eq = (long)(vn / N);
                   1516:        er = (long)(vn*Ea/N - eq*Ea);
                   1517:       }
                   1518:       else
                   1519:       {
                   1520:        chib = mycaract(chi, beta, NULL, NULL, ns);
                   1521:        vb = vstar(p, chib);
                   1522:        eq = (long)(vb[0] / vb[1]);
                   1523:        er = (long)(vb[0]*Ea / vb[1] - eq*Ea);
                   1524:       }
                   1525:
                   1526:       /* eq and er are such that gamma = beta.p^-eq.nu^-er is a unit */
                   1527:       if (eq) gamm = gdiv(beta, gpowgs(p, eq));
                   1528:       else gamm = beta;
                   1529:
                   1530:       if (er)
                   1531:       {
                   1532:        /* kappa = nu^-1 in Zp[alpha] */
                   1533:        if (!kapp)
                   1534:        {
                   1535:          kapp = ginvmod(nu, chi);
                   1536:          kapp = redelt(kapp, pmr, pmf);
                   1537:          kapp = gmodulcp(kapp, chi);
                   1538:        }
                   1539:        gamm = lift(gmul(gamm, gpowgs(kapp, er)));
                   1540:        gamm = redelt(gamm, p, pmf);
                   1541:       }
                   1542:
                   1543:       if (DEBUGLEVEL >= 6)
                   1544:        fprintferr("  gamma = %Z\n", gamm);
                   1545:
                   1546:       if (er || !chib)
                   1547:        chig = mycaract(chi, gamm, p, pmf, ns);
                   1548:       else
                   1549:       {
                   1550:        chig = poleval(chib, gmul(polx[v], gpowgs(p, eq)));
                   1551:        chig = gdiv(chig, gpowgs(p, N*eq));
                   1552:        chig = polmodi(chig, pmf);
                   1553:       }
                   1554:
                   1555:       if (!chig || !gcmp1(denom(content(chig))))
                   1556:       {
                   1557:        /* the valuation of beta was wrong... This also means
                   1558:           that chi_gamma has more than one factor modulo p   */
                   1559:        if (!chig) chig = mycaract(chi, gamm, p, NULL, NULL);
                   1560:
                   1561:        vb = vstar(p, chig);
                   1562:        eq = (long)(-vb[0] / vb[1]);
                   1563:        er = (long)(-vb[0]*Ea / vb[1] - eq*Ea);
                   1564:        if (eq) gamm = gmul(gamm, gpowgs(p, eq));
                   1565:        if (er)
                   1566:        {
                   1567:          gamm = gmul(gamm, gpowgs(nu, er));
                   1568:          gamm = gmod(gamm, chi);
                   1569:          gamm = redelt(gamm, p, pmr);
                   1570:        }
                   1571:        if (eq || er) chig = mycaract(chi, gamm, p, pmf, ns);
                   1572:       }
                   1573:
                   1574:       nug  = (GEN)factmod(chig, p)[1];
                   1575:       l    = lg(nug) - 1;
                   1576:       nug  = lift((GEN)nug[l]);
                   1577:
                   1578:       if (l > 1)
                   1579:       {
                   1580:        /* there are at least 2 factors mod. p => chi can be split */
                   1581:        phi  = eleval(fx, gamm, alph);
                   1582:        phi  = redelt(phi, p, pmf);
                   1583:        if (flag) mf += 3;
                   1584:         return Decomp(p, fx, mf, phi, chig, nug, flag);
                   1585:       }
                   1586:
                   1587:       Fg = degpol(nug);
                   1588:       if (Fa%Fg)
                   1589:       {
                   1590:        if (DEBUGLEVEL >= 5)
                   1591:          fprintferr("  Increasing Fa\n");
                   1592:        /* we compute a new element such F = lcm(Fa, Fg) */
                   1593:        w = testb2(p, chi, Fa, gamm, pmf, Fg, ns);
                   1594:        if (gcmp1((GEN)w[1]))
                   1595:        {
                   1596:          /* there are at least 2 factors mod. p => chi can be split */
                   1597:          phi = eleval(fx, (GEN)w[2], alph);
                   1598:          phi = redelt(phi, p, pmf);
                   1599:           if (flag) mf += 3;
                   1600:           return Decomp(p, fx, mf, phi, (GEN)w[3], (GEN)w[4], flag);
                   1601:        }
                   1602:        break;
                   1603:       }
                   1604:
                   1605:       /* we look for a root delta of nug in Fp[alpha] such that
                   1606:         vp(gamma - delta) > 0. This root can then be used to
                   1607:         improved the approximation given by beta */
                   1608:       nv = fetch_var();
                   1609:       w = Fp_factor_irred(nug, p, gsubst(nu, varn(nu), polx[nv]));
                   1610:       if (degpol(w[1]) != 1)
                   1611:         err(talker,"bug in nilord (no root). Is p a prime ?");
                   1612:
                   1613:       for (i = 1;; i++)
                   1614:       {
                   1615:        if (i >= lg(w))
                   1616:           err(talker, "bug in nilord (no suitable root), is p = %Z a prime?",
                   1617:              (long)p);
                   1618:         delt = gneg_i(gsubst(gcoeff(w, 2, i), nv, polx[v]));
                   1619:         eta  = gsub(gamm, delt);
                   1620:         if (typ(delt) == t_INT)
                   1621:         {
                   1622:           chie = poleval(chig, gadd(polx[v], delt));
                   1623:           nue  = (GEN)factmod(chie, p)[1];
                   1624:           l    = lg(nue) - 1;
                   1625:           nue  = lift((GEN)nue[l]);
                   1626:         }
                   1627:         else
                   1628:         {
                   1629:           p1   = factcp(p, chi, eta, pmf, ns);
                   1630:           chie = (GEN)p1[1];
                   1631:           nue  = (GEN)p1[2];
                   1632:           l    = itos((GEN)p1[3]);
                   1633:         }
                   1634:         if (l > 1)
                   1635:         {
                   1636:           /* there are at least 2 factors mod. p => chi can be split */
                   1637:           delete_var();
                   1638:           phi = eleval(fx, eta, alph);
                   1639:           phi = redelt(phi, p, pmf);
                   1640:           if (flag) mf += 3;
                   1641:           return Decomp(p, fx, mf, phi, chie, nue, flag);
                   1642:         }
                   1643:
                   1644:         /* if vp(eta) = vp(gamma - delta) > 0 */
                   1645:         if (gegal(nue, polx[v])) break;
                   1646:       }
                   1647:       delete_var();
                   1648:
                   1649:       if (!signe(modii((GEN)chie[2], pmr)))
                   1650:        chie = mycaract(chi, eta, p, pmf, ns);
                   1651:
                   1652:       pie = getprime(p, chi, eta, chie, nue, &Le, &Ee);
                   1653:       if (Ea%Ee)
                   1654:       {
                   1655:        if (DEBUGLEVEL >= 5)
                   1656:          fprintferr("  Increasing Ea\n");
                   1657:        pie = redelt(pie, p, pmf);
                   1658:        /* we compute a new element such E = lcm(Ea, Ee) */
                   1659:        w = testc2(p, chi, pmr, pmf, nu, Ea, pie, Ee, ns);
                   1660:        if (gcmp1((GEN)w[1]))
                   1661:        {
                   1662:          /* there are at least 2 factors mod. p => chi can be split */
                   1663:          phi = eleval(fx, (GEN)w[2], alph);
                   1664:          phi = redelt(phi, p, pmf);
                   1665:           if (flag) mf += 3;
                   1666:           return Decomp(p, fx, mf, phi, (GEN)w[3], (GEN)w[4], flag);
                   1667:        }
                   1668:        break;
                   1669:       }
                   1670:
                   1671:       if (eq) delt = gmul(delt, gpowgs(p, eq));
                   1672:       if (er) delt = gmul(delt, gpowgs(nu, er));
                   1673:       beta = gsub(beta, delt);
                   1674:     }
                   1675:
                   1676:     /* we replace alpha by a new alpha with a larger F or E */
                   1677:     alph = eleval(fx, (GEN)w[2], alph);
                   1678:     chi  = (GEN)w[3];
                   1679:     nu   = (GEN)w[4];
                   1680:
                   1681:     w = update_alpha(p, fx, alph, chi, pmr, pmf, mf, ns);
                   1682:     alph = (GEN)w[1];
                   1683:     chi  = (GEN)w[2];
                   1684:     pmr  = (GEN)w[3];
                   1685:     pdr  = (GEN)w[4];
                   1686:
                   1687:     /* that can happen if p does not divide the field discriminant! */
                   1688:     if (is_pm1(pmr))
                   1689:     {
                   1690:       if (flag)
                   1691:       {
                   1692:        p1 = lift((GEN)factmod(chi, p)[1]);
                   1693:        l  = lg(p1) - 1;
                   1694:        if (l == 1) return NULL;
                   1695:        phi = redelt(alph, p, pmf);
                   1696:        return Decomp(p, fx, ggval(pmf, p), phi, chi, (GEN)p1[l], flag);
                   1697:       }
                   1698:       else
                   1699:        return dbasis(p, fx, mf, alph, chi);
                   1700:     }
                   1701:   }
                   1702: }
                   1703:
                   1704: /* Returns [1,phi,chi,nu] if phi non-primary
                   1705:  *         [2,phi,chi,nu] with F_phi = lcm (F_alpha, F_theta)
                   1706:  *                         and E_phi = E_alpha
                   1707:  */
                   1708: static GEN
                   1709: testb2(GEN p, GEN fa, long Fa, GEN theta, GEN pmf, long Ft, GEN ns)
                   1710: {
                   1711:   long m, Dat, t, v = varn(fa);
                   1712:   GEN b, w, phi, h;
                   1713:
                   1714:   Dat = clcm(Fa, Ft) + 3;
                   1715:   b = cgetg(5, t_VEC);
                   1716:   m = p[2];
                   1717:   if (degpol(p) > 0 || m < 0) m = 0;
                   1718:
                   1719:   for (t = 1;; t++)
                   1720:   {
                   1721:     h = m? stopoly(t, m, v): scalarpol(stoi(t), v);
                   1722:     phi = gadd(theta, gmod(h, fa));
                   1723:     w = factcp(p, fa, phi, pmf, ns);
                   1724:     h = (GEN)w[3];
                   1725:     if (h[2] > 1) { b[1] = un; break; }
                   1726:     if (lgef(w[2]) == Dat) { b[1] = deux; break; }
                   1727:   }
                   1728:
                   1729:   b[2] = (long)phi;
                   1730:   b[3] = w[1];
                   1731:   b[4] = w[2];
                   1732:   return b;
                   1733: }
                   1734:
                   1735: /* Returns [1, phi, chi, nu] if phi non-primary
                   1736:  *         [2, phi, chi, nu] if E_phi = lcm (E_alpha, E_theta)
                   1737:  */
                   1738: static GEN
                   1739: testc2(GEN p, GEN fa, GEN pmr, GEN pmf, GEN alph2, long Ea, GEN thet2,
                   1740:        long Et, GEN ns)
                   1741: {
                   1742:   GEN b, c1, c2, c3, psi, phi, w, h;
                   1743:   long r, s, t, v = varn(fa);
                   1744:
                   1745:   b=cgetg(5, t_VEC);
                   1746:
                   1747:   cbezout(Ea, Et, &r, &s); t = 0;
                   1748:   while (r < 0) { r = r + Et; t++; }
                   1749:   while (s < 0) { s = s + Ea; t++; }
                   1750:
                   1751:   c1 = lift_intern(gpuigs(gmodulcp(alph2, fa), s));
                   1752:   c2 = lift_intern(gpuigs(gmodulcp(thet2, fa), r));
                   1753:   c3 = gdiv(gmod(gmul(c1, c2), fa), gpuigs(p, t));
                   1754:
                   1755:   psi = redelt(c3, pmr, pmr);
                   1756:   phi = gadd(polx[v], psi);
                   1757:
                   1758:   w = factcp(p, fa, phi, pmf, ns);
                   1759:   h = (GEN)w[3];
                   1760:   b[1] = (h[2] > 1)? un: deux;
                   1761:   b[2] = (long)phi;
                   1762:   b[3] = w[1];
                   1763:   b[4] = w[2];
                   1764:   return b;
                   1765: }
                   1766:
                   1767: /* evaluate h(a) mod f */
                   1768: GEN
                   1769: eleval(GEN f,GEN h,GEN a)
                   1770: {
                   1771:   long n,av,tetpil;
                   1772:   GEN y;
                   1773:
                   1774:   if (typ(h) != t_POL) return gcopy(h);
                   1775:   av = tetpil = avma;
                   1776:   n=lgef(h)-1; y=(GEN)h[n];
                   1777:   for (n--; n>=2; n--)
                   1778:   {
                   1779:     y = gadd(gmul(y,a),(GEN)h[n]);
                   1780:     tetpil=avma; y = gmod(y,f);
                   1781:   }
                   1782:   return gerepile(av,tetpil,y);
                   1783: }
                   1784:
                   1785: GEN addshiftw(GEN x, GEN y, long d);
                   1786:
                   1787: static GEN
                   1788: shiftpol(GEN x, long v)
                   1789: {
                   1790:   x = addshiftw(x, zeropol(v), 1);
                   1791:   setvarn(x,v); return x;
                   1792: }
                   1793:
                   1794: /* Sylvester's matrix, mod p^m (assumes f1 monic) */
                   1795: static GEN
                   1796: sylpm(GEN f1,GEN f2,GEN pm)
                   1797: {
                   1798:   long n,j,v=varn(f1);
                   1799:   GEN a,h;
                   1800:
                   1801:   n=degpol(f1); a=cgetg(n+1,t_MAT);
                   1802:   h = FpX_res(f2,f1,pm);
                   1803:   for (j=1;; j++)
                   1804:   {
                   1805:     a[j] = (long)pol_to_vec(h,n);
                   1806:     if (j == n) break;
                   1807:     h = FpX_res(shiftpol(h,v),f1,pm);
                   1808:   }
                   1809:   return hnfmodid(a,pm);
                   1810: }
                   1811:
                   1812: /* polynomial gcd mod p^m (assumes f1 monic) */
                   1813: GEN
                   1814: gcdpm(GEN f1,GEN f2,GEN pm)
                   1815: {
                   1816:   long n,c,v=varn(f1),av=avma,tetpil;
                   1817:   GEN a,col;
                   1818:
                   1819:   n=degpol(f1); a=sylpm(f1,f2,pm);
                   1820:   for (c=1; c<=n; c++)
                   1821:     if (signe(resii(gcoeff(a,c,c),pm))) break;
                   1822:   if (c > n) { avma=av; return zeropol(v); }
                   1823:
                   1824:   col = gdiv((GEN)a[c], gcoeff(a,c,c)); tetpil=avma;
                   1825:   return gerepile(av,tetpil, gtopolyrev(col,v));
                   1826: }
                   1827:
                   1828: /* reduced resultant mod p^m (assumes x monic) */
                   1829: GEN
                   1830: respm(GEN x,GEN y,GEN pm)
                   1831: {
                   1832:   long av = avma;
                   1833:   GEN p1 = sylpm(x,y,pm);
                   1834:
                   1835:   p1 = gcoeff(p1,1,1);
                   1836:   if (egalii(p1,pm)) { avma = av; return gzero; }
                   1837:   return gerepileuptoint(av, icopy(p1));
                   1838: }
                   1839:
                   1840: /* Normalized integral basis */
                   1841: static GEN
                   1842: nbasis(GEN ibas,GEN pd)
                   1843: {
                   1844:   long k, n = lg(ibas)-1;
                   1845:   GEN a = cgetg(n+1,t_MAT);
                   1846:   for (k=1; k<=n; k++) a[k] = (long)pol_to_vec((GEN)ibas[k],n);
                   1847:   return gdiv(hnfmodid(a,pd), pd);
                   1848: }
                   1849:
                   1850: /*******************************************************************/
                   1851: /*                                                                 */
                   1852: /*                   BUCHMANN-LENSTRA ALGORITHM                    */
                   1853: /*                                                                 */
                   1854: /*******************************************************************/
                   1855: static GEN lens(GEN nf,GEN p,GEN a);
                   1856: GEN element_powid_mod_p(GEN nf, long I, GEN n, GEN p);
                   1857:
                   1858: /* return a Z basis of Z_K's p-radical, modfrob = x--> x^p-x */
                   1859: static GEN
                   1860: pradical(GEN nf, GEN p, GEN *modfrob)
                   1861: {
                   1862:   long i,N = degpol(nf[1]);
                   1863:   GEN p1,m,frob,rad;
                   1864:
                   1865:   frob = cgetg(N+1,t_MAT);
                   1866:   for (i=1; i<=N; i++)
                   1867:     frob[i] = (long) element_powid_mod_p(nf,i,p, p);
                   1868:
                   1869:   /* p1 = smallest power of p st p^k >= N */
                   1870:   p1=p; while (cmpis(p1,N)<0) p1=mulii(p1,p);
                   1871:   if (p1==p) m = frob;
                   1872:   else
                   1873:   {
                   1874:     m=cgetg(N+1,t_MAT); p1 = divii(p1,p);
                   1875:     for (i=1; i<=N; i++)
                   1876:       m[i]=(long)element_pow_mod_p(nf,(GEN)frob[i],p1, p);
                   1877:   }
                   1878:   rad = FpM_ker(m, p);
                   1879:   for (i=1; i<=N; i++)
                   1880:     coeff(frob,i,i) = lsubis(gcoeff(frob,i,i), 1);
                   1881:   *modfrob = frob; return rad;
                   1882: }
                   1883:
                   1884: static GEN
                   1885: project(GEN algebre, GEN x, long k, long kbar)
                   1886: {
                   1887:   x = inverseimage(algebre,x);
                   1888:   x += k; x[0] = evaltyp(t_COL) | evallg(kbar+1);
                   1889:   return x;
                   1890: }
                   1891:
                   1892: /* Calcule le polynome minimal de alpha dans algebre (coeffs dans Z) */
                   1893: static GEN
                   1894: pol_min(GEN alpha,GEN nf,GEN algebre,long kbar,GEN p)
                   1895: {
                   1896:   long av=avma,tetpil,i,N,k;
                   1897:   GEN p1,puiss;
                   1898:
                   1899:   N = lg(nf[1])-3; puiss=cgetg(N+2,t_MAT);
                   1900:   k = N-kbar; p1=alpha;
                   1901:   puiss[1] = (long)gscalcol_i(gun,kbar);
                   1902:   for (i=2; i<=N+1; i++)
                   1903:   {
                   1904:     if (i>2) p1 = element_mul(nf,p1,alpha);
                   1905:     puiss[i] = (long) project(algebre,p1,k,kbar);
                   1906:   }
                   1907:   puiss = lift_intern(puiss);
                   1908:   p1 = (GEN)FpM_ker(puiss, p)[1]; tetpil=avma;
                   1909:   return gerepile(av,tetpil,gtopolyrev(p1,0));
                   1910: }
                   1911:
                   1912: /* Evalue le polynome pol en alpha,element de nf */
                   1913: static GEN
                   1914: eval_pol(GEN nf,GEN pol,GEN alpha,GEN algebre,GEN algebre1)
                   1915: {
                   1916:   long av=avma,tetpil,i,kbar,k, lx = lgef(pol)-1, N = degpol(nf[1]);
                   1917:   GEN res;
                   1918:
                   1919:   kbar = lg(algebre1)-1; k = N-kbar;
                   1920:   res = gscalcol_i((GEN)pol[lx], N);
                   1921:   for (i=2; i<lx; i++)
                   1922:   {
                   1923:     res = element_mul(nf,alpha,res);
                   1924:     res[1] = ladd((GEN)res[1],(GEN)pol[i]);
                   1925:   }
                   1926:   res = project(algebre,res,k,kbar); tetpil=avma;
                   1927:   return gerepile(av,tetpil,gmul(algebre1,res));
                   1928: }
                   1929:
                   1930: static GEN
                   1931: kerlens2(GEN x, GEN p)
                   1932: {
                   1933:   long i,j,k,t,nbc,nbl,av,av1;
                   1934:   GEN a,c,l,d,y,q;
                   1935:
                   1936:   av=avma; a=gmul(x,gmodulsg(1,p));
                   1937:   nbl=nbc=lg(x)-1;
                   1938:   c=new_chunk(nbl+1); for (i=1; i<=nbl; i++) c[i]=0;
                   1939:   l=new_chunk(nbc+1);
                   1940:   d=new_chunk(nbc+1);
                   1941:   k = t = 1;
                   1942:   while (t<=nbl && k<=nbc)
                   1943:   {
                   1944:     for (j=1; j<k; j++)
                   1945:       for (i=1; i<=nbl; i++)
                   1946:        if (i!=l[j])
                   1947:          coeff(a,i,k) = lsub(gmul((GEN)d[j],gcoeff(a,i,k)),
                   1948:                              gmul(gcoeff(a,l[j],k),gcoeff(a,i,j)));
                   1949:     t=1; while (t<=nbl && (c[t] || gcmp0(gcoeff(a,t,k)))) t++;
                   1950:     if (t<=nbl) { d[k]=coeff(a,t,k); c[t]=k; l[k]=t; k++; }
                   1951:   }
                   1952:   if (k>nbc) err(bugparier,"kerlens2");
                   1953:   y=cgetg(nbc+1,t_COL);
                   1954:   y[1]=(k>1)?coeff(a,l[1],k):un;
                   1955:   for (q=gun,j=2; j<k; j++)
                   1956:   {
                   1957:     q=gmul(q,(GEN)d[j-1]);
                   1958:     y[j]=lmul(gcoeff(a,l[j],k),q);
                   1959:   }
                   1960:   if (k>1) y[k]=lneg(gmul(q,(GEN)d[k-1]));
                   1961:   for (j=k+1; j<=nbc; j++) y[j]=zero;
                   1962:   av1=avma; return gerepile(av,av1,lift(y));
                   1963: }
                   1964:
                   1965: static GEN
                   1966: kerlens(GEN x, GEN pgen)
                   1967: {
                   1968:   long av = avma, i,j,k,t,nbc,nbl,p,q,*c,*l,*d,**a;
                   1969:   GEN y;
                   1970:
                   1971:   if (cmpis(pgen, MAXHALFULONG>>1) > 0)
                   1972:     return kerlens2(x,pgen);
                   1973:   /* ici p <= (MAXHALFULONG>>1) ==> long du C */
                   1974:   p=itos(pgen); nbl=nbc=lg(x)-1;
                   1975:   a=(long**)new_chunk(nbc+1);
                   1976:   for (j=1; j<=nbc; j++)
                   1977:   {
                   1978:     c=a[j]=new_chunk(nbl+1);
                   1979:     for (i=1; i<=nbl; i++) c[i]=smodis(gcoeff(x,i,j),p);
                   1980:   }
                   1981:   c=new_chunk(nbl+1); for (i=1; i<=nbl; i++) c[i]=0;
                   1982:   l=new_chunk(nbc+1);
                   1983:   d=new_chunk(nbc+1);
                   1984:   k = t = 1;
                   1985:   while (t<=nbl && k<=nbc)
                   1986:   {
                   1987:     for (j=1; j<k; j++)
                   1988:       for (i=1; i<=nbl; i++)
                   1989:        if (i!=l[j])
                   1990:           a[k][i] = (d[j]*a[k][i] - a[j][i]*a[k][l[j]]) % p;
                   1991:     t=1; while (t<=nbl && (c[t] || !a[k][t])) t++;
                   1992:     if (t<=nbl) { d[k]=a[k][t]; c[t]=k; l[k++]=t; }
                   1993:   }
                   1994:   if (k>nbc) err(bugparier,"kerlens");
                   1995:   avma=av; y=cgetg(nbc+1,t_COL);
                   1996:   t=(k>1) ? a[k][l[1]]:1;
                   1997:   y[1]=(t>0)? lstoi(t):lstoi(t+p);
                   1998:   for (q=1,j=2; j<k; j++)
                   1999:   {
                   2000:     q = (q*d[j-1]) % p;
                   2001:     t = (a[k][l[j]]*q) % p;
                   2002:     y[j] = (t>0) ? lstoi(t) : lstoi(t+p);
                   2003:   }
                   2004:   if (k>1)
                   2005:   {
                   2006:     t = (q*d[k-1]) % p;
                   2007:     y[k] = (t>0) ? lstoi(p-t) : lstoi(-t);
                   2008:   }
                   2009:   for (j=k+1; j<=nbc; j++) y[j]=zero;
                   2010:   return y;
                   2011: }
                   2012:
                   2013: /* Calcule la constante de lenstra de l'ideal p.Z_K+a.Z_K ou a est un
                   2014: vecteur sur la base d'entiers */
                   2015: static GEN
                   2016: lens(GEN nf, GEN p, GEN a)
                   2017: {
                   2018:   long av=avma,tetpil,N=degpol(nf[1]),j;
                   2019:   GEN mat=cgetg(N+1,t_MAT);
                   2020:   for (j=1; j<=N; j++) mat[j]=(long)element_mulid(nf,a,j);
                   2021:   tetpil=avma; return gerepile(av,tetpil,kerlens(mat,p));
                   2022: }
                   2023:
                   2024: extern GEN det_mod_P_n(GEN a, GEN N, GEN P);
                   2025: GEN sylvestermatrix_i(GEN x, GEN y);
                   2026:
                   2027: /* check if p^va doesnt divide norm x (or norm(x+p)) */
                   2028: #if 0
                   2029: /* compute norm mod p^whatneeded using Sylvester's matrix */
                   2030: /* looks slower than the new subresultant. Have to re-check this */
                   2031: static GEN
                   2032: prime_check_elt(GEN a, GEN pol, GEN p, GEN pf)
                   2033: {
                   2034:   GEN M,mod,x, c = denom(content(a));
                   2035:   long v = pvaluation(c, p, &x); /* x is junk */
                   2036:
                   2037:   mod = mulii(pf, gpowgs(p, degpol(pol)*v + 1));
                   2038:
                   2039:   x = FpX_red(gmul(a,c), mod);
                   2040:   M = sylvestermatrix_i(pol,x);
                   2041:   if (det_mod_P_n(M,mod,p) == gzero)
                   2042:   {
                   2043:     x[2] = ladd((GEN)x[2], mulii(p,c));
                   2044:     M = sylvestermatrix_i(pol,x);
                   2045:     if (det_mod_P_n(M,mod,p) == gzero) return NULL;
                   2046:     a[2] = ladd((GEN)a[2], p);
                   2047:   }
                   2048:   return a;
                   2049: }
                   2050: #else
                   2051: /* use subres to compute norm */
                   2052: static GEN
                   2053: prime_check_elt(GEN a, GEN pol, GEN p, GEN pf)
                   2054: {
                   2055:   GEN norme=subres(pol,a);
                   2056:   if (resii(divii(norme,pf),p) != gzero) return a;
                   2057:   /* Note: a+p can't succeed if e > 1, can we know this at this point ? */
                   2058:   a=gadd(a,p); norme=subres(pol,a);
                   2059:   if (resii(divii(norme,pf),p) != gzero) return a;
                   2060:   return NULL;
                   2061: }
                   2062: #endif
                   2063:
                   2064: #if 0
                   2065: static GEN
                   2066: prime_two_elt_loop(GEN beta, GEN pol, GEN p, GEN pf)
                   2067: {
                   2068:   long av, m = lg(beta)-1;
                   2069:   int i,j,K, *x = (int*)new_chunk(m+1);
                   2070:   GEN a;
                   2071:
                   2072:   K = 1; av = avma;
                   2073:   for(;;)
                   2074:   { /* x runs through strictly increasing sequences of length K,
                   2075:      * 1 <= x[i] <= m */
                   2076: nextK:
                   2077:     if (DEBUGLEVEL) fprintferr("K = %d\n", K);
                   2078:     for (i=1; i<=K; i++) x[i] = i;
                   2079:     for(;;)
                   2080:     {
                   2081:       if (DEBUGLEVEL > 1)
                   2082:       {
                   2083:         for (i=1; i<=K; i++) fprintferr("%d ",x[i]);
                   2084:         fprintferr("\n"); flusherr();
                   2085:       }
                   2086:       a = (GEN)beta[x[1]];
                   2087:       for (i=2; i<=K; i++) a = gadd(a, (GEN)beta[x[i]]);
                   2088:       if ((a = prime_check_elt(a,pol,p,pf))) return a;
                   2089:       avma = av;
                   2090:
                   2091:       /* start: i = K+1; */
                   2092:       do
                   2093:       {
                   2094:         if (--i == 0)
                   2095:         {
                   2096:           if (++K > m) return NULL; /* fail */
                   2097:           goto nextK;
                   2098:         }
                   2099:         x[i]++;
                   2100:       } while (x[i] > m - K + i);
                   2101:       for (j=i; j<K; j++) x[j+1] = x[j]+1;
                   2102:     }
                   2103:   }
                   2104: }
                   2105: #endif
                   2106:
                   2107: static GEN
                   2108: random_prime_two_elt_loop(GEN beta, GEN pol, GEN p, GEN pf)
                   2109: {
                   2110:   long av = avma, z,i, m = lg(beta)-1;
                   2111:   long keep = getrand();
                   2112:   int c = 0;
                   2113:   GEN a;
                   2114:
                   2115:   for(i=1; i<=m; i++)
                   2116:     if ((a = prime_check_elt((GEN)beta[i],pol,p,pf))) return a;
                   2117:   (void)setrand(1);
                   2118:   if (DEBUGLEVEL) fprintferr("prime_two_elt_loop, hard case: ");
                   2119:   for(;;avma=av)
                   2120:   {
                   2121:     if (DEBUGLEVEL) fprintferr("%d ", ++c);
                   2122:     a = gzero;
                   2123:     for (i=1; i<=m; i++)
                   2124:     {
                   2125:       z = mymyrand() >> (BITS_IN_RANDOM-5); /* in [0,15] */
                   2126:       if (z >= 9) z -= 7;
                   2127:       a = gadd(a,gmulsg(z,(GEN)beta[i]));
                   2128:     }
                   2129:     if ((a = prime_check_elt(a,pol,p,pf)))
                   2130:     {
                   2131:       if (DEBUGLEVEL) fprintferr("\n");
                   2132:       (void)setrand(keep); return a;
                   2133:     }
                   2134:   }
                   2135: }
                   2136:
                   2137: /* Input: an ideal mod p (!= Z_K)
                   2138:  * Output: a 2-elt representation [p, x] */
                   2139: static GEN
                   2140: prime_two_elt(GEN nf, GEN p, GEN ideal)
                   2141: {
                   2142:   GEN beta,a,pf, pol = (GEN)nf[1];
                   2143:   long f, N=degpol(pol), m=lg(ideal)-1;
                   2144:   ulong av;
                   2145:
                   2146:   if (!m) return gscalcol_i(p,N);
                   2147:
                   2148:   /* we want v_p(Norm(beta)) = p^f, f = N-m */
                   2149:   av = avma; f = N-m; pf = gpuigs(p,f);
                   2150:   ideal = centerlift(ideal);
                   2151:   ideal = concatsp(gscalcol(p,N), ideal);
                   2152:   ideal = ideal_better_basis(nf, ideal, p);
                   2153:   beta = gmul((GEN)nf[7], ideal);
                   2154:
                   2155: #if 0
                   2156:   a = prime_two_elt_loop(beta,pol,p,pf);
                   2157:   if (!a) err(bugparier, "prime_two_elt (failed)");
                   2158: #else
                   2159:   a = random_prime_two_elt_loop(beta,pol,p,pf);
                   2160: #endif
                   2161:
                   2162:   a = centermod(algtobasis_intern(nf,a), p);
                   2163:   if (resii(divii(subres(gmul((GEN)nf[7],a),pol),pf),p) == gzero)
                   2164:     a[1] = laddii((GEN)a[1],p);
                   2165:   return gerepilecopy(av,a);
                   2166: }
                   2167:
                   2168: static GEN
                   2169: apply_kummer(GEN nf,GEN pol,GEN e,GEN p,long N,GEN *beta)
                   2170: {
                   2171:   GEN T,p1, res = cgetg(6,t_VEC);
                   2172:   long f = degpol(pol);
                   2173:
                   2174:   res[1]=(long)p;
                   2175:   res[3]=(long)e;
                   2176:   res[4]=lstoi(f);
                   2177:   if (f == N) /* inert */
                   2178:   {
                   2179:     res[2]=(long)gscalcol_i(p,N);
                   2180:     res[5]=(long)gscalcol_i(gun,N);
                   2181:   }
                   2182:   else
                   2183:   {
                   2184:     T = (GEN) nf[1];
                   2185:     if (ggval(subres(pol,T),p) > f)
                   2186:       pol[2] = laddii((GEN)pol[2],p);
                   2187:     res[2] = (long) algtobasis_intern(nf,pol);
                   2188:
                   2189:     p1 = FpX_div(T,pol,p);
                   2190:     res[5] = (long) centermod(algtobasis_intern(nf,p1), p);
                   2191:
                   2192:     if (beta)
                   2193:       *beta = *beta? FpX_div(*beta,pol,p): p1;
                   2194:   }
                   2195:   return res;
                   2196: }
                   2197:
                   2198: /* prime ideal decomposition of p sorted by increasing residual degree */
                   2199: GEN
                   2200: primedec(GEN nf, GEN p)
                   2201: {
                   2202:   long av=avma,tetpil,i,j,k,kbar,np,c,indice,N,lp;
                   2203:   GEN ex,f,list,ip,elth,h;
                   2204:   GEN modfrob,algebre,algebre1,b,mat1,T;
                   2205:   GEN alpha,beta,p1,p2,unmodp,zmodp,idmodp;
                   2206:
                   2207:   if (DEBUGLEVEL>=3) timer2();
                   2208:   nf=checknf(nf); T=(GEN)nf[1]; N=degpol(T);
                   2209:   f=factmod(T,p); ex=(GEN)f[2];
                   2210:   f=centerlift((GEN)f[1]); np=lg(f);
                   2211:   if (DEBUGLEVEL>=6) msgtimer("factmod");
                   2212:
                   2213:   if (signe(modii((GEN)nf[4],p))) /* p doesn't divide index */
                   2214:   {
                   2215:     list=cgetg(np,t_VEC);
                   2216:     for (i=1; i<np; i++)
                   2217:       list[i]=(long)apply_kummer(nf,(GEN)f[i],(GEN)ex[i],p,N, NULL);
                   2218:     if (DEBUGLEVEL>=6) msgtimer("simple primedec");
                   2219:     p1=stoi(4); tetpil=avma;
                   2220:     return gerepile(av,tetpil,vecsort(list,p1));
                   2221:   }
                   2222:
                   2223:   p1 = (GEN)f[1];
                   2224:   for (i=2; i<np; i++)
                   2225:     p1 = FpX_red(gmul(p1, (GEN)f[i]), p);
                   2226:   p1 = FpX_red(gdiv(gadd(gmul(p1, FpX_div(T,p1,p)), gneg(T)), p), p);
                   2227:   list = cgetg(N+1,t_VEC);
                   2228:   indice=1; beta=NULL;
                   2229:   for (i=1; i<np; i++) /* e = 1 or f[i] does not divide p1 (mod p) */
                   2230:     if (is_pm1(ex[i]) || signe(FpX_res(p1,(GEN)f[i],p)))
                   2231:       list[indice++] = (long)apply_kummer(nf,(GEN)f[i],(GEN)ex[i],p,N,&beta);
                   2232:   if (DEBUGLEVEL>=3) msgtimer("unramified factors");
                   2233:
                   2234:   /* modfrob = modified Frobenius: x -> x^p - x mod p */
                   2235:   ip = pradical(nf,p,&modfrob);
                   2236:   if (DEBUGLEVEL>=3) msgtimer("pradical");
                   2237:
                   2238:   if (beta)
                   2239:   {
                   2240:     beta = algtobasis_intern(nf,beta);
                   2241:     lp=lg(ip)-1; p1=cgetg(2*lp+N+1,t_MAT);
                   2242:     for (i=1; i<=N; i++) p1[i]=(long)element_mulid(nf,beta,i);
                   2243:     for (   ; i<=N+lp; i++)
                   2244:     {
                   2245:       p2 = (GEN) ip[i-N];
                   2246:       p1[i+lp] = (long) p2;
                   2247:       p1[i] = ldiv(element_mul(nf,lift(p2),beta),p);
                   2248:     }
                   2249:     ip = FpM_image(p1, p);
                   2250:     if (lg(ip)>N) err(bugparier,"primedec (bad pradical)");
                   2251:   }
                   2252:   unmodp=gmodulsg(1,p); zmodp=gmodulsg(0,p);
                   2253:   idmodp = idmat_intern(N,unmodp,zmodp);
                   2254:   ip = gmul(ip, unmodp);
                   2255:
                   2256:   h=cgetg(N+1,t_VEC); h[1]=(long)ip;
                   2257:   for (c=1; c; c--)
                   2258:   {
                   2259:     elth=(GEN)h[c]; k=lg(elth)-1; kbar=N-k;
                   2260:     p1 = concatsp(elth,(GEN)idmodp[1]);
                   2261:     algebre = suppl_intern(p1,idmodp);
                   2262:     algebre1 = cgetg(kbar+1,t_MAT);
                   2263:     for (i=1; i<=kbar; i++) algebre1[i]=algebre[i+k];
                   2264:     b = gmul(modfrob,algebre1);
                   2265:     for (i=1;i<=kbar;i++)
                   2266:       b[i] = (long) project(algebre,(GEN) b[i],k,kbar);
                   2267:     mat1 = FpM_ker(lift_intern(b), p);
                   2268:     if (lg(mat1)>2)
                   2269:     {
                   2270:       GEN mat2 = cgetg(k+N+1,t_MAT);
                   2271:       for (i=1; i<=k; i++) mat2[i]=elth[i];
                   2272:       alpha=gmul(algebre1,(GEN)mat1[2]);
                   2273:       p1 = pol_min(alpha,nf,algebre,kbar,p);
                   2274:       p1 = (GEN)factmod(p1,p)[1];
                   2275:       for (i=1; i<lg(p1); i++)
                   2276:       {
                   2277:        beta = eval_pol(nf,(GEN)p1[i],alpha,algebre,algebre1);
                   2278:         beta = lift_intern(beta);
                   2279:        for (j=1; j<=N; j++)
                   2280:          mat2[k+j] = (long)FpV(element_mulid(nf,beta,j), p);
                   2281:        h[c] = (long) image(mat2); c++;
                   2282:       }
                   2283:     }
                   2284:     else
                   2285:     {
                   2286:       long av1; p1 = cgetg(6,t_VEC);
                   2287:       list[indice++] = (long)p1;
                   2288:       p1[1]=(long)p; p1[4]=lstoi(kbar);
                   2289:       p1[2]=(long)prime_two_elt(nf,p,elth);
                   2290:       p1[5]=(long)lens(nf,p,(GEN)p1[2]);
                   2291:       av1=avma;
                   2292:       i = int_elt_val(nf,(GEN)p1[5],p,(GEN)p1[5],NULL,N-1);
                   2293:       avma=av1;
                   2294:       p1[3]=lstoi(i+1);
                   2295:     }
                   2296:     if (DEBUGLEVEL>=3) msgtimer("h[%ld]",c);
                   2297:   }
                   2298:   setlg(list, indice); tetpil=avma;
                   2299:   return gerepile(av,tetpil,gen_sort(list,0,cmp_prime_over_p));
                   2300: }
                   2301:
                   2302: /* REDUCTION Modulo a prime ideal */
                   2303:
                   2304: /* x integral, reduce mod prh in HNF */
                   2305: GEN
                   2306: nfreducemodpr_i(GEN x, GEN prh)
                   2307: {
                   2308:   GEN p = gcoeff(prh,1,1);
                   2309:   long i,j;
                   2310:
                   2311:   x = dummycopy(x);
                   2312:   for (i=lg(x)-1; i>=2; i--)
                   2313:   {
                   2314:     GEN t = (GEN)prh[i], p1 = resii((GEN)x[i], p);
                   2315:     x[i] = (long)p1;
                   2316:     if (signe(p1) && is_pm1(t[i]))
                   2317:     {
                   2318:       for (j=1; j<i; j++)
                   2319:         x[j] = lsubii((GEN)x[j], mulii(p1, (GEN)t[j]));
                   2320:       x[i] = zero;
                   2321:     }
                   2322:   }
                   2323:   x[1] = lresii((GEN)x[1], p); return x;
                   2324: }
                   2325:
                   2326: /* for internal use */
                   2327: GEN
                   2328: nfreducemodpr(GEN nf, GEN x, GEN prhall)
                   2329: {
                   2330:   long i,v;
                   2331:   GEN p,prh,den;
                   2332:
                   2333:   for (i=lg(x)-1; i>0; i--)
                   2334:     if (typ(x[i]) == t_INTMOD) { x=lift_intern(x); break; }
                   2335:   prh=(GEN)prhall[1]; p=gcoeff(prh,1,1);
                   2336:   den=denom(x);
                   2337:   if (!gcmp1(den))
                   2338:   {
                   2339:     v=ggval(den,p);
                   2340:     if (v) x=element_mul(nf,x,element_pow(nf,(GEN)prhall[2],stoi(v)));
                   2341:     x = gmod(x,p);
                   2342:   }
                   2343:   return FpV(nfreducemodpr_i(x, prh), p);
                   2344: }
                   2345:
                   2346: /* public function */
                   2347: GEN
                   2348: nfreducemodpr2(GEN nf, GEN x, GEN prhall)
                   2349: {
                   2350:   long av = avma; checkprhall(prhall);
                   2351:   if (typ(x) != t_COL) x = algtobasis(nf,x);
                   2352:   return gerepileupto(av, nfreducemodpr(nf,x,prhall));
                   2353: }
                   2354:
                   2355: /*                        relative ROUND 2
                   2356:  *
                   2357:  * input: nf = base field K
                   2358:  *   x monic polynomial, coefficients in Z_K, degree n defining a relative
                   2359:  *   extension L=K(theta).
                   2360:  *   One MUST have varn(x) < varn(nf[1]).
                   2361:  * output: a pseudo-basis [A,I] of Z_L, where A is in M_n(K) in HNF form and
                   2362:  *   I a vector of n ideals.
                   2363:  */
                   2364:
                   2365: /* given MODULES x and y by their pseudo-bases in HNF, gives a
                   2366:  * pseudo-basis of the module generated by x and y. For internal use.
                   2367:  */
                   2368: static GEN
                   2369: rnfjoinmodules(GEN nf, GEN x, GEN y)
                   2370: {
                   2371:   long i,lx,ly;
                   2372:   GEN p1,p2,z,Hx,Hy,Ix,Iy;
                   2373:
                   2374:   if (x == NULL) return y;
                   2375:   Hx=(GEN)x[1]; lx=lg(Hx); Ix=(GEN)x[2];
                   2376:   Hy=(GEN)y[1]; ly=lg(Hy); Iy=(GEN)y[2];
                   2377:   i = lx+ly-1;
                   2378:   z = (GEN)gpmalloc(sizeof(long*)*(3+2*i));
                   2379:   *z = evaltyp(t_VEC)|evallg(3);
                   2380:   p1 =  z+3; z[1]=(long)p1; *p1 = evaltyp(t_MAT)|evallg(i);
                   2381:   p2 = p1+i; z[2]=(long)p2; *p2 = evaltyp(t_VEC)|evallg(i);
                   2382:
                   2383:   for (i=1; i<lx; i++) { p1[i]=Hx[i]; p2[i]=Ix[i]; }
                   2384:   for (   ; i<lx+ly-1; i++) { p1[i]=Hy[i-lx+1]; p2[i]=Iy[i-lx+1]; }
                   2385:   x = nfhermite(nf,z); free(z); return x;
                   2386: }
                   2387:
                   2388: /* a usage interne, pas de gestion de pile : x et y sont des vecteurs dont
                   2389:  * les coefficients sont les composantes sur nf[7]; avec reduction mod pr sauf
                   2390:  * si prhall=NULL
                   2391:  */
                   2392: static GEN
                   2393: rnfelement_mulidmod(GEN nf, GEN multab, GEN unnf, GEN x, long h, GEN prhall)
                   2394: {
                   2395:   long j,k,N;
                   2396:   GEN p1,c,v,s,znf;
                   2397:
                   2398:   if (h==1) return gcopy(x);
                   2399:   N = lg(x)-1; multab += (h-1)*N;
                   2400:   x = lift(x); v = cgetg(N+1,t_COL);
                   2401:   znf = gscalcol_i(gzero,lg(unnf)-1);
                   2402:   for (k=1; k<=N; k++)
                   2403:   {
                   2404:     s = gzero;
                   2405:     for (j=1; j<=N; j++)
                   2406:       if (!gcmp0(p1 = (GEN)x[j]) && !gcmp0(c = gcoeff(multab,k,j)))
                   2407:       {
                   2408:         if (!gegal(c,unnf)) p1 = element_mul(nf,p1,c);
                   2409:         s = gadd(s,p1);
                   2410:       }
                   2411:     if (s == gzero) s = znf;
                   2412:     else
                   2413:       if (prhall) s = nfreducemodpr(nf,s,prhall);
                   2414:     v[k] = (long)s;
                   2415:   }
                   2416:   return v;
                   2417: }
                   2418:
                   2419: /* a usage interne, pas de gestion de pile : x est un vecteur dont
                   2420:  * les coefficients sont les composantes sur nf[7]
                   2421:  */
                   2422: static GEN
                   2423: rnfelement_sqrmod(GEN nf, GEN multab, GEN unnf, GEN x, GEN prhall)
                   2424: {
                   2425:   long i,j,k,n;
                   2426:   GEN p1,c,z,s;
                   2427:
                   2428:   n=lg(x)-1; x=lift(x); z=cgetg(n+1,t_COL);
                   2429:   for (k=1; k<=n; k++)
                   2430:   {
                   2431:     if (k == 1)
                   2432:       s = element_sqr(nf,(GEN)x[1]);
                   2433:     else
                   2434:       s = gmul2n(element_mul(nf,(GEN)x[1],(GEN)x[k]), 1);
                   2435:     for (i=2; i<=n; i++)
                   2436:     {
                   2437:       c = gcoeff(multab,k,(i-1)*n+i);
                   2438:       if (!gcmp0(c))
                   2439:       {
                   2440:        p1=element_sqr(nf,(GEN)x[i]);
                   2441:        if (!gegal(c,unnf)) p1 = element_mul(nf,p1,c);
                   2442:         s = gadd(s,p1);
                   2443:       }
                   2444:       for (j=i+1; j<=n; j++)
                   2445:       {
                   2446:        c = gcoeff(multab,k,(i-1)*n+j);
                   2447:        if (!gcmp0(c))
                   2448:        {
                   2449:          p1=gmul2n(element_mul(nf,(GEN)x[i],(GEN)x[j]),1);
                   2450:          if (!gegal(c,unnf)) p1 = element_mul(nf,p1,c);
                   2451:           s = gadd(s,p1);
                   2452:        }
                   2453:       }
                   2454:     }
                   2455:     if (prhall) s = nfreducemodpr(nf,s,prhall);
                   2456:     z[k]=(long)s;
                   2457:   }
                   2458:   return z;
                   2459: }
                   2460:
                   2461: /* Compute x^n mod pr in the extension, assume n >= 0 [cf puissii()]*/
                   2462: static GEN
                   2463: rnfelementid_powmod(GEN nf, GEN multab, GEN matId, long h, GEN n, GEN prhall)
                   2464: {
                   2465:   ulong av = avma;
                   2466:   long i,k,m;
                   2467:   GEN y,p1, unrnf=(GEN)matId[1], unnf=(GEN)unrnf[1];
                   2468:
                   2469:   if (!signe(n)) return unrnf;
                   2470:   y = (GEN)matId[h]; p1 = n+2; m = *p1;
                   2471:   k = 1+bfffo(m); m<<=k; k = BITS_IN_LONG-k;
                   2472:   for (i=lgefint(n)-2;;)
                   2473:   {
                   2474:     for (; k; m<<=1,k--)
                   2475:     {
                   2476:       y = rnfelement_sqrmod(nf,multab,unnf,y,prhall);
                   2477:       if (m < 0) y = rnfelement_mulidmod(nf,multab,unnf,y,h,prhall);
                   2478:     }
                   2479:     if (--i == 0) break;
                   2480:     m = *++p1; k = BITS_IN_LONG;
                   2481:   }
                   2482:   return gerepilecopy(av, y);
                   2483: }
                   2484:
                   2485: GEN
                   2486: mymod(GEN x, GEN p)
                   2487: {
                   2488:   long i,lx, tx = typ(x);
                   2489:   GEN y,p1;
                   2490:
                   2491:   if (tx == t_INT) return resii(x,p);
                   2492:   if (tx == t_FRAC)
                   2493:   {
                   2494:     p1 = resii((GEN)x[2], p);
                   2495:     if (p1 != gzero) { cgiv(p1); return gmod(x,p); }
                   2496:     return x;
                   2497:   }
                   2498:   if (!is_matvec_t(tx))
                   2499:     err(bugparier, "mymod (missing type)");
                   2500:   lx = lg(x); y = cgetg(lx,tx);
                   2501:   for (i=1; i<lx; i++) y[i] = (long)mymod((GEN)x[i],p);
                   2502:   return y;
                   2503: }
                   2504:
                   2505: static GEN
                   2506: rnfordmax(GEN nf, GEN pol, GEN pr, GEN unnf, GEN id, GEN matId)
                   2507: {
                   2508:   long av=avma,tetpil,av1,lim,i,j,k,n,v1,v2,vpol,m,cmpt,sep;
                   2509:   GEN p,q,q1,prhall,A,Aa,Aaa,A1,I,R,p1,p2,p3,multab,multabmod,Aainv;
                   2510:   GEN pip,baseIp,baseOp,alpha,matprod,alphainv,matC,matG,vecpro,matH;
                   2511:   GEN neworder,H,Hid,alphalistinv,alphalist,prhinv;
                   2512:
                   2513:   if (DEBUGLEVEL>1) fprintferr(" treating %Z\n",pr);
                   2514:   prhall=nfmodprinit(nf,pr);
                   2515:   q=cgetg(3,t_VEC); q[1]=(long)pr;q[2]=(long)prhall;
                   2516:   p1=rnfdedekind(nf,pol,q);
                   2517:   if (gcmp1((GEN)p1[1])) return gerepilecopy(av,(GEN)p1[2]);
                   2518:
                   2519:   sep=itos((GEN)p1[3]);
                   2520:   A=gmael(p1,2,1);
                   2521:   I=gmael(p1,2,2);
                   2522:
                   2523:   n=degpol(pol); vpol=varn(pol);
                   2524:   p=(GEN)pr[1]; q=powgi(p,(GEN)pr[4]); pip=(GEN)pr[2];
                   2525:   q1=q; while (cmpis(q1,n)<0) q1=mulii(q1,q);
                   2526:
                   2527:   multab=cgetg(n*n+1,t_MAT);
                   2528:   for (j=1; j<=n*n; j++) multab[j]=lgetg(n+1,t_COL);
                   2529:   prhinv = idealinv(nf,(GEN)prhall[1]);
                   2530:   alphalistinv=cgetg(n+1,t_VEC);
                   2531:   alphalist=cgetg(n+1,t_VEC);
                   2532:   A1=cgetg(n+1,t_MAT);
                   2533:   av1=avma; lim=stack_lim(av1,1);
                   2534:   for(cmpt=1; ; cmpt++)
                   2535:   {
                   2536:     if (DEBUGLEVEL>1)
                   2537:     {
                   2538:       fprintferr("    %ld%s pass\n",cmpt,eng_ord(cmpt));
                   2539:       flusherr();
                   2540:     }
                   2541:     for (i=1; i<=n; i++)
                   2542:     {
                   2543:       if (gegal((GEN)I[i],id)) alphalist[i]=alphalistinv[i]=(long)unnf;
                   2544:       else
                   2545:       {
                   2546:        p1=ideal_two_elt(nf,(GEN)I[i]);
                   2547:        v1=gcmp0((GEN)p1[1])? EXP220
                   2548:                             : element_val(nf,(GEN)p1[1],pr);
                   2549:        v2=element_val(nf,(GEN)p1[2],pr);
                   2550:        if (v1>v2) p2=(GEN)p1[2]; else p2=(GEN)p1[1];
                   2551:        alphalist[i]=(long)p2;
                   2552:         alphalistinv[i]=(long)element_inv(nf,p2);
                   2553:       }
                   2554:     }
                   2555:     for (j=1; j<=n; j++)
                   2556:     {
                   2557:       p1=cgetg(n+1,t_COL); A1[j]=(long)p1;
                   2558:       for (i=1; i<=n; i++)
                   2559:        p1[i] = (long)element_mul(nf,gcoeff(A,i,j),(GEN)alphalist[j]);
                   2560:     }
                   2561:     Aa=basistoalg(nf,A1); Aainv=lift_intern(ginv(Aa));
                   2562:     Aaa=mat_to_vecpol(Aa,vpol);
                   2563:     for (i=1; i<=n; i++) for (j=i; j<=n; j++)
                   2564:     {
                   2565:       long tp;
                   2566:       p1 = lift_intern(gres(gmul((GEN)Aaa[i],(GEN)Aaa[j]), pol));
                   2567:       tp = typ(p1);
                   2568:       if (is_scalar_t(tp) || (tp==t_POL && varn(p1)>vpol))
                   2569:        p2 = gmul(p1, (GEN)Aainv[1]);
                   2570:       else
                   2571:         p2 = gmul(Aainv, pol_to_vec(p1, n));
                   2572:
                   2573:       p3 = algtobasis(nf,p2);
                   2574:       for (k=1; k<=n; k++)
                   2575:       {
                   2576:        coeff(multab,k,(i-1)*n+j) = p3[k];
                   2577:        coeff(multab,k,(j-1)*n+i) = p3[k];
                   2578:       }
                   2579:     }
                   2580:     R=cgetg(n+1,t_MAT); multabmod = mymod(multab,p);
                   2581:     R[1] = matId[1];
                   2582:     for (j=2; j<=n; j++)
                   2583:       R[j] = (long) rnfelementid_powmod(nf,multabmod,matId, j,q1,prhall);
                   2584:     baseIp = nfkermodpr(nf,R,prhall);
                   2585:     baseOp = lift_intern(nfsuppl(nf,baseIp,n,prhall));
                   2586:     alpha=cgetg(n+1,t_MAT);
                   2587:     for (j=1; j<lg(baseIp); j++) alpha[j]=baseOp[j];
                   2588:     for (   ; j<=n; j++)
                   2589:     {
                   2590:       p1=cgetg(n+1,t_COL); alpha[j]=(long)p1;
                   2591:       for (i=1; i<=n; i++)
                   2592:        p1[i]=(long)element_mul(nf,pip,gcoeff(baseOp,i,j));
                   2593:     }
                   2594:     matprod=cgetg(n+1,t_MAT);
                   2595:     for (j=1; j<=n; j++)
                   2596:     {
                   2597:       p1=cgetg(n+1,t_COL); matprod[j]=(long)p1;
                   2598:       for (i=1; i<=n; i++)
                   2599:       {
                   2600:         p2 = rnfelement_mulidmod(nf,multab,unnf, (GEN)alpha[i],j, NULL);
                   2601:         for (k=1; k<=n; k++)
                   2602:           p2[k] = lmul((GEN)nf[7], (GEN)p2[k]);
                   2603:         p1[i] = (long)p2;
                   2604:       }
                   2605:     }
                   2606:     alphainv = lift_intern(ginv(basistoalg(nf,alpha)));
                   2607:     matC = cgetg(n+1,t_MAT);
                   2608:     for (j=1; j<=n; j++)
                   2609:     {
                   2610:       p1=cgetg(n*n+1,t_COL); matC[j]=(long)p1;
                   2611:       for (i=1; i<=n; i++)
                   2612:       {
                   2613:        p2 = gmul(alphainv, gcoeff(matprod,i,j));
                   2614:        for (k=1; k<=n; k++)
                   2615:          p1[(i-1)*n+k]=(long)nfreducemodpr(nf,algtobasis(nf,(GEN)p2[k]),prhall);
                   2616:       }
                   2617:     }
                   2618:     matG=nfkermodpr(nf,matC,prhall); m=lg(matG)-1;
                   2619:     vecpro=cgetg(3,t_VEC);
                   2620:     p1=cgetg(n+m+1,t_MAT); vecpro[1]=(long)p1;
                   2621:     p2=cgetg(n+m+1,t_VEC); vecpro[2]=(long)p2;
                   2622:     for (j=1; j<=m; j++)
                   2623:     {
                   2624:       p1[j] = llift((GEN)matG[j]);
                   2625:       p2[j] = (long)prhinv;
                   2626:     }
                   2627:     p1 += m;
                   2628:     p2 += m;
                   2629:     for (j=1; j<=n; j++)
                   2630:     {
                   2631:       p1[j] = matId[j];
                   2632:       p2[j] = (long)idealmul(nf,(GEN)I[j],(GEN)alphalistinv[j]);
                   2633:     }
                   2634:     matH=nfhermite(nf,vecpro);
                   2635:     p1=algtobasis(nf,gmul(Aa,basistoalg(nf,(GEN)matH[1])));
                   2636:     p2=(GEN)matH[2];
                   2637:
                   2638:     tetpil=avma; neworder=cgetg(3,t_VEC);
                   2639:     H=cgetg(n+1,t_MAT); Hid=cgetg(n+1,t_VEC);
                   2640:     for (j=1; j<=n; j++)
                   2641:     {
                   2642:       p3=cgetg(n+1,t_COL); H[j]=(long)p3;
                   2643:       for (i=1; i<=n; i++)
                   2644:        p3[i]=(long)element_mul(nf,gcoeff(p1,i,j),(GEN)alphalistinv[j]);
                   2645:       Hid[j]=(long)idealmul(nf,(GEN)p2[j],(GEN)alphalist[j]);
                   2646:     }
                   2647:     if (DEBUGLEVEL>3)
                   2648:       { fprintferr(" new order:\n"); outerr(H); outerr(Hid); }
                   2649:     if (sep == 2 || gegal(I,Hid))
                   2650:     {
                   2651:       neworder[1]=(long)H; neworder[2]=(long)Hid;
                   2652:       return gerepile(av,tetpil,neworder);
                   2653:     }
                   2654:
                   2655:     A=H; I=Hid;
                   2656:     if (low_stack(lim, stack_lim(av1,1)) || (cmpt & 3) == 0)
                   2657:     {
                   2658:       GEN *gptr[2]; gptr[0]=&A; gptr[1]=&I;
                   2659:       if(DEBUGMEM>1) err(warnmem,"rnfordmax");
                   2660:       gerepilemany(av1,gptr,2);
                   2661:     }
                   2662:   }
                   2663: }
                   2664:
                   2665: static void
                   2666: check_pol(GEN x, long v)
                   2667: {
                   2668:   long i,tx, lx = lg(x);
                   2669:   if (varn(x) != v)
                   2670:     err(talker,"incorrect variable in rnf function");
                   2671:   for (i=2; i<lx; i++)
                   2672:   {
                   2673:     tx = typ(x[i]);
                   2674:     if (!is_scalar_t(tx) || tx == t_POLMOD)
                   2675:       err(talker,"incorrect polcoeff in rnf function");
                   2676:   }
                   2677: }
                   2678:
                   2679: GEN
                   2680: fix_relative_pol(GEN nf, GEN x, int chk_lead)
                   2681: {
                   2682:   GEN xnf = (typ(nf) == t_POL)? nf: (GEN)nf[1];
                   2683:   long i, vnf = varn(xnf), lx = lg(x);
                   2684:   if (typ(x) != t_POL || varn(x) >= vnf)
                   2685:     err(talker,"incorrect polynomial in rnf function");
                   2686:   x = dummycopy(x);
                   2687:   for (i=2; i<lx; i++)
                   2688:     switch(typ(x[i]))
                   2689:     {
                   2690:       case t_POL:
                   2691:         check_pol((GEN)x[i], vnf);
                   2692:         x[i] = lmodulcp((GEN)x[i], xnf); break;
                   2693:       case t_POLMOD:
                   2694:         if (!gegal(gmael(x,i,1), xnf)) err(consister,"rnf function");
                   2695:         break;
                   2696:     }
                   2697:
                   2698:   if (chk_lead && !gcmp1(leading_term(x)))
                   2699:     err(impl,"non-monic relative polynomials");
                   2700:   return x;
                   2701: }
                   2702:
                   2703: static GEN
                   2704: rnfround2all(GEN nf, GEN pol, long all)
                   2705: {
                   2706:   long av=avma,tetpil,i,j,n,N,nbidp,vpol,*ep;
                   2707:   GEN p1,p2,p3,p4,polnf,list,unnf,id,matId,I,W,pseudo,y,discpol,d,D,sym;
                   2708:
                   2709:   nf=checknf(nf); polnf=(GEN)nf[1]; vpol=varn(pol);
                   2710:   pol = fix_relative_pol(nf,pol,1);
                   2711:   N=degpol(polnf); n=degpol(pol); discpol=discsr(pol);
                   2712:   list=idealfactor(nf,discpol); ep=(long*)list[2]; list=(GEN)list[1];
                   2713:   nbidp=lg(list)-1; for(i=1;i<=nbidp;i++) ep[i]=itos((GEN)ep[i]);
                   2714:   if (DEBUGLEVEL>1)
                   2715:   {
                   2716:     fprintferr("Ideals to consider:\n");
                   2717:     for (i=1; i<=nbidp; i++)
                   2718:       if (ep[i]>1) fprintferr("%Z^%ld\n",list[i],ep[i]);
                   2719:     flusherr();
                   2720:   }
                   2721:   id=idmat(N); unnf=gscalcol_i(gun,N);
                   2722:   matId=idmat_intern(n,unnf, gscalcol_i(gzero,N));
                   2723:   pseudo = NULL;
                   2724:   for (i=1; i<=nbidp; i++)
                   2725:     if (ep[i] > 1)
                   2726:     {
                   2727:       y=rnfordmax(nf,pol,(GEN)list[i],unnf,id,matId);
                   2728:       pseudo = rnfjoinmodules(nf,pseudo,y);
                   2729:     }
                   2730:   if (!pseudo)
                   2731:   {
                   2732:     I=cgetg(n+1,t_VEC); for (i=1; i<=n; i++) I[i]=(long)id;
                   2733:     pseudo=cgetg(3,t_VEC); pseudo[1]=(long)matId; pseudo[2]=(long)I;
                   2734:   }
                   2735:   W=gmodulcp(mat_to_vecpol(basistoalg(nf,(GEN)pseudo[1]),vpol),pol);
                   2736:   p2=cgetg(n+1,t_MAT); for (j=1; j<=n; j++) p2[j]=lgetg(n+1,t_COL);
                   2737:   sym=polsym(pol,n-1);
                   2738:   for (j=1; j<=n; j++)
                   2739:     for (i=j; i<=n; i++)
                   2740:     {
                   2741:       p1 = lift_intern(gmul((GEN)W[i],(GEN)W[j]));
                   2742:       coeff(p2,j,i)=coeff(p2,i,j)=(long)quicktrace(p1,sym);
                   2743:     }
                   2744:   d = algtobasis_intern(nf,det(p2));
                   2745:
                   2746:   I=(GEN)pseudo[2];
                   2747:   i=1; while (i<=n && gegal((GEN)I[i],id)) i++;
                   2748:   if (i>n) D=id;
                   2749:   else
                   2750:   {
                   2751:     D = (GEN)I[i];
                   2752:     for (i++; i<=n; i++)
                   2753:       if (!gegal((GEN)I[i],id)) D = idealmul(nf,D,(GEN)I[i]);
                   2754:     D = idealpow(nf,D,gdeux);
                   2755:   }
                   2756:   p4=gun; p3=auxdecomp(content(d),0);
                   2757:   for (i=1; i<lg(p3[1]); i++)
                   2758:     p4 = gmul(p4, gpuigs(gcoeff(p3,i,1), itos(gcoeff(p3,i,2))>>1));
                   2759:   p4 = gsqr(p4); tetpil=avma;
                   2760:   i = all? 2: 0;
                   2761:   p1=cgetg(3 + i,t_VEC);
                   2762:   if (i) { p1[1]=lcopy((GEN)pseudo[1]); p1[2]=lcopy(I); }
                   2763:   p1[1+i] = (long)idealmul(nf,D,d);
                   2764:   p1[2+i] = ldiv(d,p4);
                   2765:   return gerepile(av,tetpil,p1);
                   2766: }
                   2767:
                   2768: GEN
                   2769: rnfpseudobasis(GEN nf, GEN pol)
                   2770: {
                   2771:   return rnfround2all(nf,pol,1);
                   2772: }
                   2773:
                   2774: GEN
                   2775: rnfdiscf(GEN nf, GEN pol)
                   2776: {
                   2777:   return rnfround2all(nf,pol,0);
                   2778: }
                   2779:
                   2780: /* given bnf as output by buchinit and a pseudo-basis of an order
                   2781:  * in HNF [A,I] (or [A,I,D,d] it does not matter), tries to simplify the
                   2782:  * HNF as much as possible. The resulting matrix will be upper triangular
                   2783:  * but the diagonal coefficients will not be equal to 1. The ideals
                   2784:  * are guaranteed to be integral and primitive.
                   2785:  */
                   2786: GEN
                   2787: rnfsimplifybasis(GEN bnf, GEN order)
                   2788: {
                   2789:   long av=avma,tetpil,j,N,n;
                   2790:   GEN p1,id,Az,Iz,nf,A,I;
                   2791:
                   2792:   bnf = checkbnf(bnf);
                   2793:   if (typ(order)!=t_VEC || lg(order)<3)
                   2794:     err(talker,"not a pseudo-basis in nfsimplifybasis");
                   2795:   A=(GEN)order[1]; I=(GEN)order[2]; n=lg(A)-1; nf=(GEN)bnf[7];
                   2796:   N=degpol(nf[1]); id=idmat(N); Iz=cgetg(n+1,t_VEC); Az=cgetg(n+1,t_MAT);
                   2797:   for (j=1; j<=n; j++)
                   2798:   {
                   2799:     if (gegal((GEN)I[j],id)) { Iz[j]=(long)id; Az[j]=A[j]; }
                   2800:     else
                   2801:     {
                   2802:       p1=content((GEN)I[j]);
                   2803:       if (!gcmp1(p1))
                   2804:       {
                   2805:        Iz[j]=(long)gdiv((GEN)I[j],p1); Az[j]=lmul((GEN)A[j],p1);
                   2806:       }
                   2807:       else Az[j]=A[j];
                   2808:       if (!gegal((GEN)Iz[j],id))
                   2809:       {
                   2810:        p1=isprincipalgen(bnf,(GEN)Iz[j]);
                   2811:        if (gcmp0((GEN)p1[1]))
                   2812:        {
                   2813:          p1=(GEN)p1[2]; Iz[j]=(long)id;
                   2814:          Az[j]=(long)element_mulvec(nf,p1,(GEN)Az[j]);
                   2815:        }
                   2816:       }
                   2817:     }
                   2818:   }
                   2819:   tetpil=avma; p1=cgetg(lg(order),t_VEC); p1[1]=lcopy(Az); p1[2]=lcopy(Iz);
                   2820:   for (j=3; j<lg(order); j++) p1[j]=lcopy((GEN)order[j]);
                   2821:   return gerepile(av,tetpil,p1);
                   2822: }
                   2823:
                   2824: GEN
                   2825: rnfdet2(GEN nf, GEN A, GEN I)
                   2826: {
                   2827:   long av,tetpil,i;
                   2828:   GEN p1;
                   2829:
                   2830:   nf=checknf(nf); av = tetpil = avma;
                   2831:   p1=idealhermite(nf,det(matbasistoalg(nf,A)));
                   2832:   for(i=1;i<lg(I);i++) { tetpil=avma; p1=idealmul(nf,p1,(GEN)I[i]); }
                   2833:   tetpil=avma; return gerepile(av,tetpil,p1);
                   2834: }
                   2835:
                   2836: GEN
                   2837: rnfdet(GEN nf, GEN order)
                   2838: {
                   2839:   if (typ(order)!=t_VEC || lg(order)<3)
                   2840:     err(talker,"not a pseudo-matrix in rnfdet");
                   2841:   return rnfdet2(nf,(GEN)order[1],(GEN)order[2]);
                   2842: }
                   2843:
                   2844: GEN
                   2845: rnfdet0(GEN nf, GEN x, GEN y)
                   2846: {
                   2847:   return y? rnfdet2(nf,x,y): rnfdet(nf,x);
                   2848: }
                   2849:
                   2850: /* given a pseudo-basis of an order in HNF [A,I] (or [A,I,D,d] it does
                   2851:  * not matter), gives an nxn matrix (not in HNF) of a pseudo-basis and
                   2852:  * an ideal vector [id,id,...,id,I] such that order=nf[7]^(n-1)xI.
                   2853:  * Since it uses the approximation theorem, can be long.
                   2854:  */
                   2855: GEN
                   2856: rnfsteinitz(GEN nf, GEN order)
                   2857: {
                   2858:   long av=avma,tetpil,i,n;
                   2859:   GEN Id,A,I,p1,a,b;
                   2860:
                   2861:   nf = checknf(nf);
                   2862:   Id = idmat(degpol(nf[1]));
                   2863:   if (typ(order)==t_POL) order=rnfpseudobasis(nf,order);
                   2864:   if (typ(order)!=t_VEC || lg(order)<3)
                   2865:     err(talker,"not a pseudo-matrix in rnfsteinitz");
                   2866:   A=dummycopy((GEN)order[1]);
                   2867:   I=dummycopy((GEN)order[2]); n=lg(A)-1;
                   2868:   if (typ(A) != t_MAT || typ(I) != t_VEC || lg(I) != n+1)
                   2869:     err(typeer,"rnfsteinitz");
                   2870:   for (i=1; i<n; i++)
                   2871:   {
                   2872:     a = (GEN)I[i];
                   2873:     if (!gegal(a,Id))
                   2874:     {
                   2875:       GEN c1 = (GEN)A[i];
                   2876:       GEN c2 = (GEN)A[i+1];
                   2877:       b = (GEN)I[i+1];
                   2878:       if (gegal(b,Id))
                   2879:       {
                   2880:         A[i]  = (long)c2;
                   2881:         A[i+1]= lneg(c1);
                   2882:        I[i]  = (long)b;
                   2883:         I[i+1]= (long)a;
                   2884:       }
                   2885:       else
                   2886:       {
                   2887:        p1 = nfidealdet1(nf,a,b);
                   2888:        A[i]  = ladd(element_mulvec(nf,(GEN)p1[1], c1),
                   2889:                     element_mulvec(nf,(GEN)p1[2], c2));
                   2890:        A[i+1]= ladd(element_mulvec(nf,(GEN)p1[3], c1),
                   2891:                     element_mulvec(nf,(GEN)p1[4], c2));
                   2892:        I[i]  =(long)Id;
                   2893:         I[i+1]=(long)idealmul(nf,a,b); p1 = content((GEN)I[i+1]);
                   2894:        if (!gcmp1(p1))
                   2895:        {
                   2896:          I[i+1] = ldiv((GEN)I[i+1],p1);
                   2897:          A[i+1] = lmul(p1,(GEN)A[i+1]);
                   2898:        }
                   2899:       }
                   2900:     }
                   2901:   }
                   2902:   tetpil=avma; p1=cgetg(lg(order),t_VEC);
                   2903:   p1[1]=lcopy(A); p1[2]=lcopy(I);
                   2904:   for (i=3; i<lg(order); i++) p1[i]=lcopy((GEN)order[i]);
                   2905:   return gerepile(av,tetpil,p1);
                   2906: }
                   2907:
                   2908: /* Given bnf as output by buchinit and either an order as output by
                   2909:  * rnfpseudobasis or a polynomial, and outputs a basis if it is free,
                   2910:  * an n+1-generating set if it is not
                   2911:  */
                   2912: GEN
                   2913: rnfbasis(GEN bnf, GEN order)
                   2914: {
                   2915:   ulong av = avma;
                   2916:   long j,N,n;
                   2917:   GEN nf,A,I,classe,p1,p2,id;
                   2918:
                   2919:   bnf = checkbnf(bnf);
                   2920:   nf=(GEN)bnf[7]; N=degpol(nf[1]); id=idmat(N);
                   2921:   if (typ(order)==t_POL) order=rnfpseudobasis(nf,order);
                   2922:   if (typ(order)!=t_VEC || lg(order)<3)
                   2923:     err(talker,"not a pseudo-matrix in rnfbasis");
                   2924:   A=(GEN)order[1]; I=(GEN)order[2]; n=lg(A)-1;
                   2925:   j=1; while (j<n && gegal((GEN)I[j],id)) j++;
                   2926:   if (j<n) order=rnfsteinitz(nf,order);
                   2927:   A=(GEN)order[1]; I=(GEN)order[2]; classe=(GEN)I[n];
                   2928:   p1=isprincipalgen(bnf,classe);
                   2929:   if (gcmp0((GEN)p1[1]))
                   2930:   {
                   2931:     p2=cgetg(n+1,t_MAT);
                   2932:     p2[n]=(long)element_mulvec(nf,(GEN)p1[2],(GEN)A[n]);
                   2933:   }
                   2934:   else
                   2935:   {
                   2936:     p1=ideal_two_elt(nf,classe);
                   2937:     p2=cgetg(n+2,t_MAT);
                   2938:     p2[n]=lmul((GEN)p1[1],(GEN)A[n]);
                   2939:     p2[n+1]=(long)element_mulvec(nf,(GEN)p1[2],(GEN)A[n]);
                   2940:   }
                   2941:   for (j=1; j<n; j++) p2[j]=A[j];
                   2942:   return gerepilecopy(av,p2);
                   2943: }
                   2944:
                   2945: /* Given bnf as output by buchinit and either an order as output by
                   2946:  * rnfpseudobasis or a polynomial, and outputs a basis (not pseudo)
                   2947:  * in Hermite Normal Form if it exists, zero if not
                   2948:  */
                   2949: GEN
                   2950: rnfhermitebasis(GEN bnf, GEN order)
                   2951: {
                   2952:   ulong av = avma;
                   2953:   long j,N,n;
                   2954:   GEN nf,A,I,p1,id;
                   2955:
                   2956:   bnf = checkbnf(bnf); nf=(GEN)bnf[7];
                   2957:   N=degpol(nf[1]); id=idmat(N);
                   2958:   if (typ(order)==t_POL)
                   2959:   {
                   2960:     order=rnfpseudobasis(nf,order);
                   2961:     A=(GEN)order[1];
                   2962:   }
                   2963:   else
                   2964:   {
                   2965:     if (typ(order)!=t_VEC || lg(order)<3)
                   2966:       err(talker,"not a pseudo-matrix in rnfbasis");
                   2967:     A=gcopy((GEN)order[1]);
                   2968:   }
                   2969:   I=(GEN)order[2]; n=lg(A)-1;
                   2970:   for (j=1; j<=n; j++)
                   2971:   {
                   2972:     if (!gegal((GEN)I[j],id))
                   2973:     {
                   2974:       p1=isprincipalgen(bnf,(GEN)I[j]);
                   2975:       if (gcmp0((GEN)p1[1]))
                   2976:        A[j]=(long)element_mulvec(nf,(GEN)p1[2],(GEN)A[j]);
                   2977:       else { avma=av; return gzero; }
                   2978:     }
                   2979:   }
                   2980:   return gerepilecopy(av,A);
                   2981: }
                   2982:
                   2983: long
                   2984: rnfisfree(GEN bnf, GEN order)
                   2985: {
                   2986:   long av=avma,n,N,j;
                   2987:   GEN nf,p1,id,I;
                   2988:
                   2989:   bnf = checkbnf(bnf);
                   2990:   if (gcmp1(gmael3(bnf,8,1,1))) return 1;
                   2991:
                   2992:   nf=(GEN)bnf[7]; N=degpol(nf[1]); id=idmat(N);
                   2993:   if (typ(order)==t_POL) order=rnfpseudobasis(nf,order);
                   2994:   if (typ(order)!=t_VEC || lg(order)<3)
                   2995:     err(talker,"not a pseudo-matrix in rnfisfree");
                   2996:
                   2997:   I=(GEN)order[2]; n=lg(I)-1;
                   2998:   j=1; while (j<=n && gegal((GEN)I[j],id)) j++;
                   2999:   if (j>n) { avma=av; return 1; }
                   3000:
                   3001:   p1=(GEN)I[j];
                   3002:   for (j++; j<=n; j++)
                   3003:     if (!gegal((GEN)I[j],id)) p1=idealmul(nf,p1,(GEN)I[j]);
                   3004:   j = gcmp0(isprincipal(bnf,p1));
                   3005:   avma=av; return j;
                   3006: }
                   3007:
                   3008: /**********************************************************************/
                   3009: /**                                                                 **/
                   3010: /**                  COMPOSITUM OF TWO NUMBER FIELDS                **/
                   3011: /**                                                                 **/
                   3012: /**********************************************************************/
                   3013: extern GEN ZY_ZXY_resultant_all(GEN A, GEN B0, long *lambda, GEN *LPRS);
                   3014: extern GEN squff2(GEN x, long klim, long hint);
                   3015: extern GEN to_polmod(GEN x, GEN mod);
                   3016:
                   3017: /* modular version. TODO: check that compositum2 is not slower */
                   3018: GEN
                   3019: polcompositum0(GEN A, GEN B, long flall)
                   3020: {
                   3021:   ulong av = avma;
                   3022:   long v,k;
                   3023:   GEN C, LPRS;
                   3024:
                   3025:   if (typ(A)!=t_POL || typ(B)!=t_POL) err(typeer,"polcompositum0");
                   3026:   if (degpol(A)<=0 || degpol(B)<=0) err(constpoler,"compositum");
                   3027:   v = varn(A);
                   3028:   if (varn(B) != v) err(talker,"not the same variable in compositum");
                   3029:   C = content(A); if (!gcmp1(C)) A = gdiv(A, C);
                   3030:   C = content(B); if (!gcmp1(C)) B = gdiv(B, C);
                   3031:   check_pol_int(A,"compositum");
                   3032:   check_pol_int(B,"compositum");
                   3033:   if (!ZX_is_squarefree(A)) err(talker,"compositum: %Z not separable", A);
                   3034:   if (!ZX_is_squarefree(B)) err(talker,"compositum: %Z not separable", B);
                   3035:
                   3036:   k = 1; C = ZY_ZXY_resultant_all(A, B, &k, flall? &LPRS: NULL);
                   3037:   C = squff2(C,0,0); /* C = Res_Y (A, B(X + kY)) guaranteed squarefree */
                   3038:   if (flall)
                   3039:   {
                   3040:     long i,l = lg(C);
                   3041:     GEN w,a,b; /* a,b,c root of A,B,C = compositum, c = b - k a */
                   3042:     for (i=1; i<l; i++)
                   3043:     { /* invmod possibly very costly */
                   3044:       a = gmul((GEN)LPRS[1], ZX_invmod((GEN)LPRS[2], (GEN)C[i]));
                   3045:       a = gneg_i(gmod(a, (GEN)C[i]));
                   3046:       b = gadd(polx[v], gmulsg(k,a));
                   3047:       w = cgetg(5,t_VEC); /* [C, a, b, n ] */
                   3048:       w[1] = C[i];
                   3049:       w[2] = (long)to_polmod(a, (GEN)w[1]);
                   3050:       w[3] = (long)to_polmod(b, (GEN)w[1]);
                   3051:       w[4] = lstoi(-k); C[i] = (long)w;
                   3052:     }
                   3053:   }
                   3054:   settyp(C, t_VEC); return gerepilecopy(av, C);
                   3055: }
                   3056:
                   3057: GEN
                   3058: compositum(GEN pol1,GEN pol2)
                   3059: {
                   3060:   return polcompositum0(pol1,pol2,0);
                   3061: }
                   3062:
                   3063: GEN
                   3064: compositum2(GEN pol1,GEN pol2)
                   3065: {
                   3066:   return polcompositum0(pol1,pol2,1);
                   3067: }
                   3068:
                   3069: extern int isrational(GEN x);
                   3070: extern GEN nfgcd(GEN P, GEN Q, GEN nf, GEN den);
                   3071:
                   3072: int
                   3073: nfissquarefree(GEN nf, GEN x)
                   3074: {
                   3075:   ulong av = avma;
                   3076:   GEN g, y = derivpol(x);
                   3077:   if (isrational(x))
                   3078:     g = modulargcd(x, y);
                   3079:   else
                   3080:     g = nfgcd(x, y, nf, NULL);
                   3081:   avma = av; return (degpol(g) == 0);
                   3082: }
                   3083:
                   3084: GEN
                   3085: rnfequation0(GEN nf, GEN B, long flall)
                   3086: {
                   3087:   ulong av = avma;
                   3088:   long v,vpol,k,lA,lB;
                   3089:   GEN cC,A,C,LPRS;
                   3090:
                   3091:   if (typ(nf)==t_POL) A=nf; else { nf=checknf(nf); A=(GEN)nf[1]; }
                   3092:   B = fix_relative_pol(nf,B,1);
                   3093:   v   = varn(A); lA = lgef(A);
                   3094:   vpol= varn(B); lB = lgef(B);
                   3095:   if (lA<=3 || lB<=3) err(constpoler,"rnfequation");
                   3096:
                   3097:   check_pol_int(A,"rnfequation");
                   3098:   B = lift_intern(B); B = gdiv(B, content(B));
                   3099:   for (k=2; k<lB; k++)
                   3100:     if (lgef(B[k]) >= lA) B[k] = lres((GEN)B[k],A);
                   3101:
                   3102:   if (!nfissquarefree(A,B))
                   3103:     err(talker,"not k separable relative equation in rnfequation");
                   3104:
                   3105:   k = 0; C = ZY_ZXY_resultant_all(A, B, &k, flall? &LPRS: NULL);
                   3106:   if (gsigne(leadingcoeff(C)) < 0) C = gneg_i(C);
                   3107:   C = primitive_part(C, &cC);
                   3108:   if (flall)
                   3109:   {
                   3110:     GEN w,a,b; /* a,b,c root of A,B,C = compositum, c = b - k a */
                   3111:     /* invmod possibly very costly */
                   3112:     a = gmul((GEN)LPRS[1], ZX_invmod((GEN)LPRS[2], C));
                   3113:     a = gneg_i(gmod(a, C));
                   3114:     b = gadd(polx[v], gmulsg(k,a));
                   3115:     w = cgetg(4,t_VEC); /* [C, a, n ] */
                   3116:     w[1] = (long)C;
                   3117:     w[2] = (long)to_polmod(a, (GEN)w[1]);
                   3118:     w[3] = lstoi(-k); C = w;
                   3119:   }
                   3120:   return gerepilecopy(av, C);
                   3121: }
                   3122:
                   3123: GEN
                   3124: rnfequation(GEN nf,GEN pol2)
                   3125: {
                   3126:   return rnfequation0(nf,pol2,0);
                   3127: }
                   3128:
                   3129: GEN
                   3130: rnfequation2(GEN nf,GEN pol2)
                   3131: {
                   3132:   return rnfequation0(nf,pol2,1);
                   3133: }
                   3134:
                   3135: static GEN
                   3136: nftau(long r1, GEN x)
                   3137: {
                   3138:   long i, ru = lg(x);
                   3139:   GEN s;
                   3140:
                   3141:   s = r1 ? (GEN)x[1] : gmul2n(greal((GEN)x[1]),1);
                   3142:   for (i=2; i<=r1; i++) s=gadd(s,(GEN)x[i]);
                   3143:   for ( ; i<ru; i++) s=gadd(s,gmul2n(greal((GEN)x[i]),1));
                   3144:   return s;
                   3145: }
                   3146:
                   3147: static GEN
                   3148: nftocomplex(GEN nf, GEN x)
                   3149: {
                   3150:   long ru,vnf,k;
                   3151:   GEN p2,p3,ronf;
                   3152:
                   3153:   p2 = (typ(x)==t_POLMOD)? (GEN)x[2]: gmul((GEN)nf[7],x);
                   3154:   vnf=varn(nf[1]);
                   3155:   ronf=(GEN)nf[6]; ru=lg(ronf); p3=cgetg(ru,t_COL);
                   3156:   for (k=1; k<ru; k++) p3[k]=lsubst(p2,vnf,(GEN)ronf[k]);
                   3157:   return p3;
                   3158: }
                   3159:
                   3160: static GEN
                   3161: rnfscal(GEN mth, GEN xth, GEN yth)
                   3162: {
                   3163:   long n,ru,i,j,kk;
                   3164:   GEN x,y,m,res,p1,p2;
                   3165:
                   3166:   n=lg(mth)-1; ru=lg(gcoeff(mth,1,1));
                   3167:   res=cgetg(ru,t_COL);
                   3168:   for (kk=1; kk<ru; kk++)
                   3169:   {
                   3170:     m=cgetg(n+1,t_MAT);
                   3171:     for (j=1; j<=n; j++)
                   3172:     {
                   3173:       p1=cgetg(n+1,t_COL); m[j]=(long)p1;
                   3174:       for (i=1; i<=n; i++) { p2=gcoeff(mth,i,j); p1[i]=p2[kk]; }
                   3175:     }
                   3176:     x=cgetg(n+1,t_VEC);
                   3177:     for (j=1; j<=n; j++) x[j]=(long)gconj((GEN)((GEN)xth[j])[kk]);
                   3178:     y=cgetg(n+1,t_COL);
                   3179:     for (j=1; j<=n; j++) y[j]=((GEN)yth[j])[kk];
                   3180:     res[kk]=(long)gmul(x,gmul(m,y));
                   3181:   }
                   3182:   return res;
                   3183: }
                   3184:
                   3185: static GEN
                   3186: rnfdiv(GEN x, GEN y)
                   3187: {
                   3188:   long i, ru = lg(x);
                   3189:   GEN z;
                   3190:
                   3191:   z=cgetg(ru,t_COL);
                   3192:   for (i=1; i<ru; i++) z[i]=(long)gdiv((GEN)x[i],(GEN)y[i]);
                   3193:   return z;
                   3194: }
                   3195:
                   3196: static GEN
                   3197: rnfmul(GEN x, GEN y)
                   3198: {
                   3199:   long i, ru = lg(x);
                   3200:   GEN z;
                   3201:
                   3202:   z=cgetg(ru,t_COL);
                   3203:   for (i=1; i<ru; i++) z[i]=(long)gmul((GEN)x[i],(GEN)y[i]);
                   3204:   return z;
                   3205: }
                   3206:
                   3207: static GEN
                   3208: rnfvecmul(GEN x, GEN v)
                   3209: {
                   3210:   long i, lx = lg(v);
                   3211:   GEN y;
                   3212:
                   3213:   y=cgetg(lx,typ(v));
                   3214:   for (i=1; i<lx; i++) y[i]=(long)rnfmul(x,(GEN)v[i]);
                   3215:   return y;
                   3216: }
                   3217:
                   3218: static GEN
                   3219: allonge(GEN v, long N)
                   3220: {
                   3221:   long r,r2,i;
                   3222:   GEN y;
                   3223:
                   3224:   r=lg(v)-1; r2=N-r;
                   3225:   y=cgetg(N+1,t_COL);
                   3226:   for (i=1; i<=r; i++) y[i]=v[i];
                   3227:   for ( ; i<=N; i++) y[i]=(long)gconj((GEN)v[i-r2]);
                   3228:   return y;
                   3229: }
                   3230:
                   3231: static GEN
                   3232: findmin(GEN nf, GEN ideal, GEN muf,long prec)
                   3233: {
                   3234:   long av=avma,N,tetpil,i;
                   3235:   GEN m,y;
                   3236:
                   3237:   m = qf_base_change(gmael(nf,5,3), ideal, 0); /* nf[5][3] = T2 */
                   3238:   m = lllgramintern(m,4,1,prec);
                   3239:   if (!m)
                   3240:   {
                   3241:     m = lllint(ideal);
                   3242:     m = qf_base_change(gmael(nf,5,3), gmul(ideal,m), 0);
                   3243:     m = lllgramintern(m,4,1,prec);
                   3244:     if (!m) err(precer,"rnflllgram");
                   3245:   }
                   3246:   ideal=gmul(ideal,m);
                   3247:   N=lg(ideal)-1; y=cgetg(N+1,t_MAT);
                   3248:   for (i=1; i<=N; i++)
                   3249:     y[i] = (long) allonge(nftocomplex(nf,(GEN)ideal[i]),N);
                   3250:   m=ground(greal(gauss(y,allonge(muf,N))));
                   3251:   tetpil=avma; return gerepile(av,tetpil,gmul(ideal,m));
                   3252: }
                   3253:
                   3254: #define swap(x,y) { long _t=x; x=y; y=_t; }
                   3255:
                   3256: /* given a base field nf (e.g main variable y), a polynomial pol with
                   3257:  * coefficients in nf    (e.g main variable x), and an order as output
                   3258:  * by rnfpseudobasis, outputs a reduced order.
                   3259:  */
                   3260: GEN
                   3261: rnflllgram(GEN nf, GEN pol, GEN order,long prec)
                   3262: {
                   3263:   long av=avma,tetpil,i,j,k,l,kk,kmax,r1,ru,lx,vnf;
                   3264:   GEN p1,p2,M,I,U,ronf,poll,unro,roorder,powreorder,mth,s,MC,MPOL,MCS;
                   3265:   GEN B,mu,Bf,temp,ideal,x,xc,xpol,muf,mufc,muno,y,z,Ikk_inv;
                   3266:
                   3267: /* Initializations and verifications */
                   3268:
                   3269:   nf=checknf(nf);
                   3270:   if (typ(order)!=t_VEC || lg(order)<3)
                   3271:     err(talker,"not a pseudo-matrix in rnflllgram");
                   3272:   M=(GEN)order[1]; I=(GEN)order[2]; lx=lg(I);
                   3273:   if (lx < 3) return gcopy(order);
                   3274:   if (lx-1 != degpol(pol)) err(consister,"rnflllgram");
                   3275:   U=idmat(lx-1); I = dummycopy(I);
                   3276:
                   3277: /* Compute the relative T2 matrix of powers of theta */
                   3278:
                   3279:   vnf=varn(nf[1]); ronf=(GEN)nf[6]; ru=lg(ronf); poll=lift(pol);
                   3280:   r1 = nf_get_r1(nf);
                   3281:   unro=cgetg(lx,t_COL); for (i=1; i<lx; i++) unro[i]=un;
                   3282:   roorder=cgetg(ru,t_VEC);
                   3283:   for (i=1; i<ru; i++)
                   3284:     roorder[i]=lroots(gsubst(poll,vnf,(GEN)ronf[i]),prec);
                   3285:   powreorder=cgetg(lx,t_MAT);
                   3286:   p1=cgetg(ru,t_COL); powreorder[1]=(long)p1;
                   3287:   for (i=1; i<ru; i++) p1[i]=(long)unro;
                   3288:   for (k=2; k<lx; k++)
                   3289:   {
                   3290:     p1=cgetg(ru,t_COL); powreorder[k]=(long)p1;
                   3291:     for (i=1; i<ru; i++)
                   3292:     {
                   3293:       p2=cgetg(lx,t_COL); p1[i]=(long)p2;
                   3294:       for (j=1; j<lx; j++)
                   3295:        p2[j] = lmul(gmael(roorder,i,j),gmael3(powreorder,k-1,i,j));
                   3296:     }
                   3297:   }
                   3298:   mth=cgetg(lx,t_MAT);
                   3299:   for (l=1; l<lx; l++)
                   3300:   {
                   3301:     p1=cgetg(lx,t_COL); mth[l]=(long)p1;
                   3302:     for (k=1; k<lx; k++)
                   3303:     {
                   3304:       p2=cgetg(ru,t_COL); p1[k]=(long)p2;
                   3305:       for (i=1; i<ru; i++)
                   3306:       {
                   3307:        s=gzero;
                   3308:        for (j=1; j<lx; j++)
                   3309:          s = gadd(s,gmul(gconj(gmael3(powreorder,k,i,j)),
                   3310:                          gmael3(powreorder,l,i,j)));
                   3311:        p2[i]=(long)s;
                   3312:       }
                   3313:     }
                   3314:   }
                   3315:
                   3316: /* Transform the matrix M into a matrix with coefficients in K and also
                   3317:    with coefficients polymod */
                   3318:
                   3319:   MC=cgetg(lx,t_MAT); MPOL=cgetg(lx,t_MAT);
                   3320:   for (j=1; j<lx; j++)
                   3321:   {
                   3322:     p1=cgetg(lx,t_COL); MC[j]=(long)p1;
                   3323:     p2=cgetg(lx,t_COL); MPOL[j]=(long)p2;
                   3324:     for (i=1; i<lx; i++)
                   3325:     {
                   3326:       p2[i]=(long)basistoalg(nf,gcoeff(M,i,j));
                   3327:       p1[i]=(long)nftocomplex(nf,(GEN)p2[i]);
                   3328:     }
                   3329:   }
                   3330:   MCS=cgetg(lx,t_MAT);
                   3331:
                   3332: /* Start LLL algorithm */
                   3333:
                   3334:   mu=cgetg(lx,t_MAT); B=cgetg(lx,t_COL);
                   3335:   for (j=1; j<lx; j++)
                   3336:   {
                   3337:     p1=cgetg(lx,t_COL); mu[j]=(long)p1; for (i=1; i<lx; i++) p1[i]=zero;
                   3338:     B[j]=zero;
                   3339:   }
                   3340:   kk=2; if (DEBUGLEVEL) fprintferr("kk = %ld ",kk);
                   3341:   kmax=1; B[1]=lreal(rnfscal(mth,(GEN)MC[1],(GEN)MC[1]));
                   3342:   MCS[1]=lcopy((GEN)MC[1]);
                   3343:   do
                   3344:   {
                   3345:     if (kk>kmax)
                   3346:     {
                   3347: /* Incremental Gram-Schmidt */
                   3348:       kmax=kk; MCS[kk]=lcopy((GEN)MC[kk]);
                   3349:       for (j=1; j<kk; j++)
                   3350:       {
                   3351:        coeff(mu,kk,j) = (long) rnfdiv(rnfscal(mth,(GEN)MCS[j],(GEN)MC[kk]),
                   3352:                                      (GEN) B[j]);
                   3353:        MCS[kk] = lsub((GEN) MCS[kk], rnfvecmul(gcoeff(mu,kk,j),(GEN)MCS[j]));
                   3354:       }
                   3355:       B[kk] = lreal(rnfscal(mth,(GEN)MCS[kk],(GEN)MCS[kk]));
                   3356:       if (gcmp0((GEN)B[kk])) err(lllger3);
                   3357:     }
                   3358:
                   3359: /* RED(k,k-1) */
                   3360:     l=kk-1; Ikk_inv=idealinv(nf, (GEN)I[kk]);
                   3361:     ideal=idealmul(nf,(GEN)I[l],Ikk_inv);
                   3362:     x=findmin(nf,ideal,gcoeff(mu,kk,l),2*prec-2);
                   3363:     if (!gcmp0(x))
                   3364:     {
                   3365:       xpol=basistoalg(nf,x); xc=nftocomplex(nf,xpol);
                   3366:       MC[kk]=lsub((GEN)MC[kk],rnfvecmul(xc,(GEN)MC[l]));
                   3367:       U[kk]=lsub((GEN)U[kk],gmul(xpol,(GEN)U[l]));
                   3368:       coeff(mu,kk,l)=lsub(gcoeff(mu,kk,l),xc);
                   3369:       for (i=1; i<l; i++)
                   3370:        coeff(mu,kk,i)=lsub(gcoeff(mu,kk,i),rnfmul(xc,gcoeff(mu,l,i)));
                   3371:     }
                   3372: /* Test LLL condition */
                   3373:     p1=nftau(r1,gadd((GEN) B[kk],
                   3374:                      gmul(gnorml2(gcoeff(mu,kk,kk-1)),(GEN)B[kk-1])));
                   3375:     p2=gdivgs(gmulsg(9,nftau(r1,(GEN)B[kk-1])),10);
                   3376:     if (gcmp(p1,p2)<=0)
                   3377:     {
                   3378: /* Execute SWAP(k) */
                   3379:       k=kk;
                   3380:       swap(MC[k-1],MC[k]);
                   3381:       swap(U[k-1],U[k]);
                   3382:       swap(I[k-1],I[k]);
                   3383:       for (j=1; j<=k-2; j++) swap(coeff(mu,k-1,j),coeff(mu,k,j));
                   3384:       muf=gcoeff(mu,k,k-1);
                   3385:       mufc=gconj(muf); muno=greal(rnfmul(muf,mufc));
                   3386:       Bf=gadd((GEN)B[k],rnfmul(muno,(GEN)B[k-1]));
                   3387:       p1=rnfdiv((GEN)B[k-1],Bf);
                   3388:       coeff(mu,k,k-1)=(long)rnfmul(mufc,p1);
                   3389:       temp=(GEN)MCS[k-1];
                   3390:       MCS[k-1]=ladd((GEN)MCS[k],rnfvecmul(muf,(GEN)MCS[k-1]));
                   3391:       MCS[k]=lsub(rnfvecmul(rnfdiv((GEN)B[k],Bf),temp),
                   3392:                  rnfvecmul(gcoeff(mu,k,k-1),(GEN)MCS[k]));
                   3393:       B[k]=(long)rnfmul((GEN)B[k],p1); B[k-1]=(long)Bf;
                   3394:       for (i=k+1; i<=kmax; i++)
                   3395:       {
                   3396:        temp=gcoeff(mu,i,k);
                   3397:        coeff(mu,i,k)=lsub(gcoeff(mu,i,k-1),rnfmul(muf,gcoeff(mu,i,k)));
                   3398:        coeff(mu,i,k-1) = ladd(temp, rnfmul(gcoeff(mu,k,k-1),gcoeff(mu,i,k)));
                   3399:       }
                   3400:       if (kk>2) { kk--; if (DEBUGLEVEL) fprintferr("%ld ",kk); }
                   3401:     }
                   3402:     else
                   3403:     {
                   3404:       for (l=kk-2; l; l--)
                   3405:       {
                   3406: /* RED(k,l) */
                   3407:        ideal=idealmul(nf,(GEN)I[l],Ikk_inv);
                   3408:        x=findmin(nf,ideal,gcoeff(mu,kk,l),2*prec-2);
                   3409:        if (!gcmp0(x))
                   3410:        {
                   3411:           xpol=basistoalg(nf,x); xc=nftocomplex(nf,xpol);
                   3412:          MC[kk]=(long)gsub((GEN)MC[kk],rnfvecmul(xc,(GEN)MC[l]));
                   3413:          U[kk]=(long)gsub((GEN)U[kk],gmul(xpol,(GEN)U[l]));
                   3414:          coeff(mu,kk,l)=lsub(gcoeff(mu,kk,l),xc);
                   3415:          for (i=1; i<l; i++)
                   3416:            coeff(mu,kk,i) = lsub(gcoeff(mu,kk,i), rnfmul(xc,gcoeff(mu,l,i)));
                   3417:        }
                   3418:       }
                   3419:       kk++; if (DEBUGLEVEL) fprintferr("%ld ",kk);
                   3420:     }
                   3421:   }
                   3422:   while (kk<lx);
                   3423:   if (DEBUGLEVEL) fprintferr("\n");
                   3424:   p1=gmul(MPOL,U); tetpil=avma;
                   3425:   y=cgetg(3,t_VEC); z=cgetg(3,t_VEC); y[1]=(long)z;
                   3426:   z[2]=lcopy(I); z[1]=(long)algtobasis(nf,p1);
                   3427:   y[2]=(long)algtobasis(nf,U);
                   3428:   return gerepile(av,tetpil,y);
                   3429: }
                   3430:
                   3431: GEN
                   3432: rnfpolred(GEN nf, GEN pol, long prec)
                   3433: {
                   3434:   ulong av = avma;
                   3435:   long i,j,k,n,N, vpol = varn(pol);
                   3436:   GEN id,id2,newid,newor,p1,p2,al,newpol,w,z;
                   3437:   GEN bnf,zk,newideals,ideals,order,neworder;
                   3438:
                   3439:   if (typ(pol)!=t_POL) err(typeer,"rnfpolred");
                   3440:   if (typ(nf)!=t_VEC) err(idealer1);
                   3441:   switch(lg(nf))
                   3442:   {
                   3443:     case 10: bnf = NULL; break;
                   3444:     case 11: bnf = nf; nf = checknf((GEN)nf[7]); break;
                   3445:     default: err(idealer1);
                   3446:       return NULL; /* not reached */
                   3447:   }
                   3448:   if (degpol(pol) <= 1)
                   3449:   {
                   3450:     w=cgetg(2,t_VEC);
                   3451:     w[1]=lpolx[vpol]; return w;
                   3452:   }
                   3453:   id=rnfpseudobasis(nf,pol); N=degpol(nf[1]);
                   3454:   if (bnf && gcmp1(gmael3(bnf,8,1,1))) /* if bnf is principal */
                   3455:   {
                   3456:     ideals=(GEN)id[2]; n=lg(ideals)-1; order=(GEN)id[1];
                   3457:     newideals=cgetg(n+1,t_VEC); neworder=cgetg(n+1,t_MAT);
                   3458:     zk=idmat(N);
                   3459:     for (j=1; j<=n; j++)
                   3460:     {
                   3461:       newideals[j]=(long)zk; p1=cgetg(n+1,t_COL); neworder[j]=(long)p1;
                   3462:       p2=(GEN)order[j];
                   3463:       al=(GEN)isprincipalgen(bnf,(GEN)ideals[j])[2];
                   3464:       for (k=1; k<=n; k++)
                   3465:        p1[k]=(long)element_mul(nf,(GEN)p2[k],al);
                   3466:     }
                   3467:     id=cgetg(3,t_VEC); id[1]=(long)neworder; id[2]=(long)newideals;
                   3468:   }
                   3469:   id2=rnflllgram(nf,pol,id,prec);
                   3470:   z=(GEN)id2[1]; newid=(GEN)z[2]; newor=(GEN)z[1];
                   3471:   n=lg(newor)-1; w=cgetg(n+1,t_VEC);
                   3472:   for (j=1; j<=n; j++)
                   3473:   {
                   3474:     p1=(GEN)newid[j]; al=gmul(gcoeff(p1,1,1),(GEN)newor[j]);
                   3475:     p1=basistoalg(nf,(GEN)al[n]);
                   3476:     for (i=n-1; i; i--)
                   3477:       p1=gadd(basistoalg(nf,(GEN)al[i]),gmul(polx[vpol],p1));
                   3478:     newpol=gtopoly(gmodulcp(gtovec(caract2(lift(pol),lift(p1),vpol)),
                   3479:                             (GEN) nf[1]), vpol);
                   3480:     p1 = ggcd(newpol, derivpol(newpol));
                   3481:     if (degpol(p1)>0)
                   3482:     {
                   3483:       newpol=gdiv(newpol,p1);
                   3484:       newpol=gdiv(newpol,leading_term(newpol));
                   3485:     }
                   3486:     w[j]=(long)newpol;
                   3487:     if (DEBUGLEVEL>=4) outerr(newpol);
                   3488:   }
                   3489:   return gerepilecopy(av,w);
                   3490: }
                   3491:
                   3492: extern GEN vecpol_to_mat(GEN v, long n);
                   3493:
                   3494: /* given a relative polynomial pol over nf, compute a pseudo-basis for the
                   3495:  * extension, then an absolute basis */
                   3496: GEN
                   3497: makebasis(GEN nf,GEN pol)
                   3498: {
                   3499:   GEN elts,ids,polabs,plg,B,bs,p1,p2,a,den,vbs,vbspro,vpro,rnf;
                   3500:   long av=avma,n,N,m,i,j, v = varn(pol);
                   3501:
                   3502:   p1 = rnfequation2(nf,pol);
                   3503:   polabs= (GEN)p1[1];
                   3504:   plg   = (GEN)p1[2];
                   3505:   a     = (GEN)p1[3];
                   3506:   rnf = cgetg(12,t_VEC);
                   3507:   for (i=2;i<=9;i++) rnf[i]=zero;
                   3508:   rnf[1] =(long)pol;
                   3509:   rnf[10]=(long)nf; p2=cgetg(4,t_VEC);
                   3510:   rnf[11]=(long)p2; p2[1]=p2[2]=zero; p2[3]=(long)a;
                   3511:   if (signe(a))
                   3512:     pol = gsubst(pol,v,gsub(polx[v],
                   3513:                             gmul(a,gmodulcp(polx[varn(nf[1])],(GEN)nf[1]))));
                   3514:   p1=rnfpseudobasis(nf,pol);
                   3515:   elts= (GEN)p1[1];
                   3516:   ids = (GEN)p1[2];
                   3517:   if (DEBUGLEVEL>1) { fprintferr("relative basis computed\n"); flusherr(); }
                   3518:   N=degpol(pol); n=degpol((GEN)nf[1]); m=n*N;
                   3519:   den = denom(content(lift(plg)));
                   3520:   vbs = cgetg(n+1,t_VEC);
                   3521:   vbs[1] = un;
                   3522:   vbs[2] = (long)plg; vbspro = gmul(den,plg);
                   3523:   for(i=3;i<=n;i++)
                   3524:     vbs[i] = ldiv(gmul((GEN)vbs[i-1],vbspro),den);
                   3525:   bs = gmul(vbs, vecpol_to_mat((GEN)nf[7],n));
                   3526:
                   3527:   vpro=cgetg(N+1,t_VEC);
                   3528:   for (i=1;i<=N;i++)
                   3529:   {
                   3530:     p1=cgetg(3,t_POLMOD);
                   3531:     p1[1]=(long)polabs;
                   3532:     p1[2]=lpuigs(polx[v],i-1); vpro[i]=(long)p1;
                   3533:   }
                   3534:   vpro=gmul(vpro,elts); B = cgetg(m+1, t_MAT);
                   3535:   for(i=1;i<=N;i++)
                   3536:     for(j=1;j<=n;j++)
                   3537:     {
                   3538:       p1 = gmul(bs, element_mul(nf,(GEN)vpro[i],gmael(ids,i,j)));
                   3539:       B[(i-1)*n+j] = (long)pol_to_vec(lift_intern(p1), m);
                   3540:     }
                   3541:   p1 = denom(B); B = gmul(B,p1);
                   3542:   B = hnfmodid(B, p1); B = gdiv(B,p1);
                   3543:   p1=cgetg(4,t_VEC);
                   3544:   p1[1]=(long)polabs;
                   3545:   p1[2]=(long)B;
                   3546:   p1[3]=(long)rnf; return gerepilecopy(av, p1);
                   3547: }

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