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

Annotation of OpenXM_contrib/pari/src/basemath/base4.c, Revision 1.1

1.1     ! maekawa     1: /*******************************************************************/
        !             2: /*                                                                 */
        !             3: /*                       BASIC NF OPERATIONS                       */
        !             4: /*                           (continued)                           */
        !             5: /*                                                                 */
        !             6: /*******************************************************************/
        !             7: /* $Id: base4.c,v 1.1.1.1 1999/09/16 13:47:22 karim Exp $ */
        !             8: #include "pari.h"
        !             9: #include "parinf.h"
        !            10:
        !            11: #define principalideal_aux(nf,x) (principalideal0((nf),(x),0))
        !            12:
        !            13: GEN element_muli(GEN nf, GEN x, GEN y);
        !            14:
        !            15: static GEN nfbezout(GEN nf, GEN a, GEN b, GEN ida, GEN idb, GEN *u, GEN *v, GEN *w, GEN *di);
        !            16:
        !            17: /*******************************************************************/
        !            18: /*                                                                 */
        !            19: /*                     IDEAL OPERATIONS                            */
        !            20: /*                                                                 */
        !            21: /*******************************************************************/
        !            22:
        !            23: /* A valid ideal is either principal (valid nf_element), or prime, or a matrix
        !            24:  * on the integer basis (preferably HNF).
        !            25:  * A prime ideal is of the form [p,a,e,f,b], where the ideal is p.Z_K+a.Z_K,
        !            26:  * p is a rational prime, a belongs to Z_K, e=e(P/p), f=f(P/p), and b
        !            27:  * Lenstra constant (p.P^(-1)= p Z_K + b Z_K).
        !            28:  *
        !            29:  * An idele is a couple[I,V] where I is a valid ideal and V a row vector
        !            30:  * with r1+r2 components (real or complex). For instance, if M=(a), V
        !            31:  * contains the complex logarithms of the first r1+r2 conjugates of a
        !            32:  * (depends on the chosen generator a). All subroutines work with either
        !            33:  * ideles or ideals (an omitted V is assumed to be 0).
        !            34:  *
        !            35:  * All the output ideals will be in HNF form.
        !            36:  */
        !            37:
        !            38: /* types and conversions */
        !            39:
        !            40: static long
        !            41: idealtyp(GEN *ideal, GEN *arch)
        !            42: {
        !            43:   GEN x = *ideal;
        !            44:   long t,lx,tx = typ(x);
        !            45:
        !            46:   if (tx==t_VEC && lg(x)==3)
        !            47:   { *arch = (GEN)x[2]; x = (GEN)x[1]; tx = typ(x); }
        !            48:   else
        !            49:     *arch = NULL;
        !            50:   switch(tx)
        !            51:   {
        !            52:     case t_MAT: lx = lg(x);
        !            53:       if (lx>2) t = id_MAT;
        !            54:       else
        !            55:       {
        !            56:         t = id_PRINCIPAL;
        !            57:         x = (lx==2)? (GEN)x[1]: gzero;
        !            58:       }
        !            59:       break;
        !            60:
        !            61:     case t_VEC: if (lg(x)!=6) err(idealer2);
        !            62:       t = id_PRIME; break;
        !            63:
        !            64:     case t_POL: case t_POLMOD: case t_COL:
        !            65:       t = id_PRINCIPAL; break;
        !            66:     default:
        !            67:       if (tx!=t_INT && !is_frac_t(tx)) err(idealer2);
        !            68:       t = id_PRINCIPAL;
        !            69:   }
        !            70:   *ideal = x; return t;
        !            71: }
        !            72:
        !            73: /* Assume ideal in HNF form */
        !            74: long
        !            75: ideal_is_zk(GEN ideal,long N)
        !            76: {
        !            77:   long i,j, lx = lg(ideal);
        !            78:
        !            79:   if (typ(ideal) != t_MAT || lx==1) return 0;
        !            80:   N++; if (lx != N || lg(ideal[1]) != N) return 0;
        !            81:   for (i=1; i<N; i++)
        !            82:   {
        !            83:     if (!gcmp1(gcoeff(ideal,i,i))) return 0;
        !            84:     for (j=i+1; j<N; j++)
        !            85:       if (!gcmp0(gcoeff(ideal,i,j))) return 0;
        !            86:   }
        !            87:   return 1;
        !            88: }
        !            89:
        !            90: static GEN
        !            91: prime_to_ideal_aux(GEN nf, GEN vp)
        !            92: {
        !            93:   GEN m,el;
        !            94:   long i, N = lgef(nf[1])-3;
        !            95:
        !            96:   m = cgetg(N+1,t_MAT); el = (GEN)vp[2];
        !            97:   for (i=1; i<=N; i++) m[i] = (long) element_mulid(nf,el,i);
        !            98:   return hnfmodid(m,(GEN)vp[1]);
        !            99: }
        !           100:
        !           101: GEN
        !           102: prime_to_ideal(GEN nf, GEN vp)
        !           103: {
        !           104:   long av=avma;
        !           105:   if (typ(vp) == t_INT) return gscalmat(vp, lgef(nf[1])-3);
        !           106:   return gerepileupto(av, prime_to_ideal_aux(nf,vp));
        !           107: }
        !           108:
        !           109: /* x = ideal in matrix form. Put it in hnf. */
        !           110: static GEN
        !           111: idealmat_to_hnf(GEN nf, GEN x)
        !           112: {
        !           113:   long rx,i,j,N;
        !           114:   GEN m,dx;
        !           115:
        !           116:   N=lgef(nf[1])-3; rx=lg(x)-1;
        !           117:   if (!rx) return gscalmat(gzero,N);
        !           118:
        !           119:   dx=denom(x); if (gcmp1(dx)) dx = NULL; else x=gmul(dx,x);
        !           120:   if (rx >= N) m = x;
        !           121:   else
        !           122:   {
        !           123:     m=cgetg(rx*N + 1,t_MAT);
        !           124:     for (i=1; i<=rx; i++)
        !           125:       for (j=1; j<=N; j++)
        !           126:         m[(i-1)*N + j] = (long) element_mulid(nf,(GEN)x[i],j);
        !           127:   }
        !           128:   x = hnfmod(m,detint(m));
        !           129:   return dx? gdiv(x,dx): x;
        !           130: }
        !           131:
        !           132: int
        !           133: ishnfall(GEN x)
        !           134: {
        !           135:   long i,j, lx = lg(x);
        !           136:   for (i=2; i<lx; i++)
        !           137:   {
        !           138:     if (gsigne(gcoeff(x,i,i)) <= 0) return 0;
        !           139:     for (j=1; j<i; j++)
        !           140:       if (!gcmp0(gcoeff(x,i,j))) return 0;
        !           141:   }
        !           142:   return (gsigne(gcoeff(x,1,1)) > 0);
        !           143: }
        !           144:
        !           145: GEN
        !           146: idealhermite_aux(GEN nf, GEN x)
        !           147: {
        !           148:   long N,tx,lx;
        !           149:   GEN z;
        !           150:
        !           151:   tx = idealtyp(&x,&z);
        !           152:   if (tx == id_PRIME) return prime_to_ideal(nf,x);
        !           153:   if (tx == id_PRINCIPAL)
        !           154:   {
        !           155:     x = principalideal(nf,x);
        !           156:     return idealmat_to_hnf(nf,x);
        !           157:   }
        !           158:   N=lgef(nf[1])-3; lx = lg(x);
        !           159:   if (lg(x[1]) != N+1) err(idealer2);
        !           160:
        !           161:   if (lx == N+1 && ishnfall(x)) return x;
        !           162:   if (lx <= N) return idealmat_to_hnf(nf,x);
        !           163:   z=denom(x); if (gcmp1(z)) z=NULL; else x = gmul(z,x);
        !           164:   x = hnfmod(x,detint(x));
        !           165:   return z? gdiv(x,z): x;
        !           166: }
        !           167:
        !           168: GEN
        !           169: idealhermite(GEN nf, GEN x)
        !           170: {
        !           171:   long av=avma;
        !           172:   GEN p1;
        !           173:   nf = checknf(nf); p1 = idealhermite_aux(nf,x);
        !           174:   if (p1==x || p1==(GEN)x[1]) return gcopy(p1);
        !           175:   return gerepileupto(av,p1);
        !           176: }
        !           177:
        !           178: static GEN
        !           179: principalideal0(GEN nf, GEN x, long copy)
        !           180: {
        !           181:   GEN z = cgetg(2,t_MAT);
        !           182:   switch(typ(x))
        !           183:   {
        !           184:     case t_INT: case t_FRAC: case t_FRACN:
        !           185:       if (copy) x = gcopy(x);
        !           186:       x = gscalcol_i(x, lgef(nf[1])-3); break;
        !           187:
        !           188:     case t_POLMOD:
        !           189:       if (!gegal((GEN)nf[1],(GEN)x[1]))
        !           190:        err(talker,"incompatible number fields in principalideal");
        !           191:       x=(GEN)x[2]; /* fall through */
        !           192:     case t_POL:
        !           193:       x = copy? algtobasis(nf,x): algtobasis_intern(nf,x);
        !           194:       break;
        !           195:
        !           196:     case t_MAT:
        !           197:       if (lg(x)!=2) err(typeer,"principalideal");
        !           198:       x = (GEN)x[1];
        !           199:     case t_COL:
        !           200:       if (lg(x)==lgef(nf[1])-2)
        !           201:       {
        !           202:         if (copy) x = gcopy(x);
        !           203:         break;
        !           204:       }
        !           205:     default: err(typeer,"principalideal");
        !           206:   }
        !           207:   z[1]=(long)x; return z;
        !           208: }
        !           209:
        !           210: GEN
        !           211: principalideal(GEN nf, GEN x)
        !           212: {
        !           213:   nf = checknf(nf); return principalideal0(nf,x,1);
        !           214: }
        !           215:
        !           216: /* for internal use */
        !           217: GEN
        !           218: get_arch(GEN nf,GEN x,long prec)
        !           219: {
        !           220:   long i,R1,RU;
        !           221:   GEN v,p1,p2;
        !           222:
        !           223:   R1=itos(gmael(nf,2,1)); RU = R1+itos(gmael(nf,2,2));
        !           224:   if (typ(x)!=t_COL) x = algtobasis_intern(nf,x);
        !           225:   if (isnfscalar(x)) /* rational number */
        !           226:   {
        !           227:     v = cgetg(RU+1,t_VEC);
        !           228:     p1=glog((GEN)x[1],prec); if (RU!=R1) p2=gmul2n(p1,1);
        !           229:     for (i=1; i<=R1; i++) v[i]=(long)p1;
        !           230:     for (   ; i<=RU; i++) v[i]=(long)p2;
        !           231:   }
        !           232:   else
        !           233:   {
        !           234:     x = gmul(gmael(nf,5,1),x); v = cgetg(RU+1,t_VEC);
        !           235:     for (i=1; i<=R1; i++) v[i] = llog((GEN)x[i],prec);
        !           236:     for (   ; i<=RU; i++) v[i] = lmul2n(glog((GEN)x[i],prec),1);
        !           237:   }
        !           238:   return v;
        !           239: }
        !           240:
        !           241: GEN
        !           242: get_arch_real(GEN nf,GEN x,GEN *emb,long prec)
        !           243: {
        !           244:   long i,R1,RU;
        !           245:   GEN v,p1,p2;
        !           246:
        !           247:   R1=itos(gmael(nf,2,1)); RU = R1+itos(gmael(nf,2,2));
        !           248:   if (typ(x)!=t_COL) x = algtobasis_intern(nf,x);
        !           249:   if (isnfscalar(x)) /* rational number */
        !           250:   {
        !           251:     GEN u = (GEN)x[1];
        !           252:     v = cgetg(RU+1,t_COL);
        !           253:     i = signe(u);
        !           254:     if (!i) err(talker,"0 in get_arch_real");
        !           255:     p1= (i > 0)? glog(u,prec): gzero;
        !           256:     if (RU != R1) p2 = gmul2n(p1,1);
        !           257:     for (i=1; i<=R1; i++) v[i]=(long)p1;
        !           258:     for (   ; i<=RU; i++) v[i]=(long)p2;
        !           259:   }
        !           260:   else
        !           261:   {
        !           262:     x = gmul(gmael(nf,5,1),x); v = cgetg(RU+1,t_COL);
        !           263:     for (i=1; i<=R1; i++) v[i] = llog(gabs((GEN)x[i],prec),prec);
        !           264:     for (   ; i<=RU; i++) v[i] = llog(gnorm((GEN)x[i]),prec);
        !           265:   }
        !           266:   *emb = x; return v;
        !           267: }
        !           268:
        !           269: GEN
        !           270: principalidele(GEN nf, GEN x, long prec)
        !           271: {
        !           272:   GEN p1,y = cgetg(3,t_VEC);
        !           273:   long av;
        !           274:
        !           275:   nf = checknf(nf);
        !           276:   p1 = principalideal0(nf,x,1);
        !           277:   y[1] = (long)p1;
        !           278:   av =avma; p1 = get_arch(nf,(GEN)p1[1],prec);
        !           279:   y[2] = lpileupto(av,p1); return y;
        !           280: }
        !           281:
        !           282: /* GP functions */
        !           283:
        !           284: GEN
        !           285: ideal_two_elt0(GEN nf, GEN x, GEN a)
        !           286: {
        !           287:   if (!a) return ideal_two_elt(nf,x);
        !           288:   return ideal_two_elt2(nf,x,a);
        !           289: }
        !           290:
        !           291: GEN
        !           292: idealpow0(GEN nf, GEN x, GEN n, long flag, long prec)
        !           293: {
        !           294:   if (flag) return idealpowred(nf,x,n,prec);
        !           295:   return idealpow(nf,x,n);
        !           296: }
        !           297:
        !           298: GEN
        !           299: idealmul0(GEN nf, GEN x, GEN y, long flag, long prec)
        !           300: {
        !           301:   if (flag) return idealmulred(nf,x,y,prec);
        !           302:   return idealmul(nf,x,y);
        !           303: }
        !           304:
        !           305: GEN
        !           306: idealpowred(GEN nf, GEN x, GEN n, long prec)
        !           307: {
        !           308:   long av=avma, tetpil;
        !           309:   x = idealpow(nf,x,n); tetpil=avma;
        !           310:   return gerepile(av,tetpil, ideallllred(nf,x,NULL,prec));
        !           311: }
        !           312:
        !           313: GEN
        !           314: idealmulred(GEN nf, GEN x, GEN y, long prec)
        !           315: {
        !           316:   long av=avma,tetpil;
        !           317:   x = idealmul(nf,x,y); tetpil=avma;
        !           318:   return gerepile(av,tetpil,ideallllred(nf,x,NULL,prec));
        !           319: }
        !           320:
        !           321: GEN
        !           322: idealinv0(GEN nf, GEN ix, long flag)
        !           323: {
        !           324:   switch(flag)
        !           325:   {
        !           326:     case 0: return idealinv(nf,ix);
        !           327:     case 1: return oldidealinv(nf,ix);
        !           328:     default: err(flagerr,"idealinv");
        !           329:   }
        !           330:   return NULL; /* not reached */
        !           331: }
        !           332:
        !           333: GEN
        !           334: idealdiv0(GEN nf, GEN x, GEN y, long flag)
        !           335: {
        !           336:   switch(flag)
        !           337:   {
        !           338:     case 0: return idealdiv(nf,x,y);
        !           339:     case 1: return idealdivexact(nf,x,y);
        !           340:     default: err(flagerr,"idealdiv");
        !           341:   }
        !           342:   return NULL; /* not reached */
        !           343: }
        !           344:
        !           345: GEN
        !           346: idealaddtoone0(GEN nf, GEN arg1, GEN arg2)
        !           347: {
        !           348:   if (!arg2) return idealaddmultoone(nf,arg1);
        !           349:   return idealaddtoone(nf,arg1,arg2);
        !           350: }
        !           351:
        !           352: static GEN
        !           353: two_to_hnf(GEN nf, GEN a, GEN b)
        !           354: {
        !           355:   a = principalideal_aux(nf,a);
        !           356:   b = principalideal_aux(nf,b);
        !           357:   a = concatsp(a,b);
        !           358:   if (lgef(nf[1])==5) /* quadratic field: a has to be turned into idealmat */
        !           359:     a = idealmul(nf,idmat(2),a);
        !           360:   return idealmat_to_hnf(nf, a);
        !           361: }
        !           362:
        !           363: GEN
        !           364: idealhnf0(GEN nf, GEN a, GEN b)
        !           365: {
        !           366:   long av;
        !           367:   if (!b) return idealhermite(nf,a);
        !           368:
        !           369:   /* HNF of aZ_K+bZ_K */
        !           370:   av = avma; nf=checknf(nf);
        !           371:   return gerepileupto(av, two_to_hnf(nf,a,b));
        !           372: }
        !           373:
        !           374: GEN
        !           375: idealhermite2(GEN nf, GEN a, GEN b)
        !           376: {
        !           377:   return idealhnf0(nf,a,b);
        !           378: }
        !           379:
        !           380: static GEN
        !           381: check_elt(GEN a, GEN pol, GEN pnorm, GEN idz)
        !           382: {
        !           383:   GEN x,norme, p2,p1;
        !           384:
        !           385:   if (!signe(a)) return NULL;
        !           386:   p1 = content(a);
        !           387:   if (gcmp1(p1)) { x=a; p1=NULL; }
        !           388:   else { x=gdiv(a,p1); p2=gpowgs(p1, lgef(pol)-3); }
        !           389:
        !           390:   norme = resultantducos(pol,x); if (p1) norme = gmul(norme,p2);
        !           391:   if (gcmp1(mppgcd(divii(norme,pnorm),pnorm))) return a;
        !           392:
        !           393:   if (p1)
        !           394:   {
        !           395:     idz=gdiv(idz,p1);
        !           396:     if (typ(idz) == t_FRAC) /* should be exceedingly rare */
        !           397:     {
        !           398:       x = gmul(x,(GEN)idz[2]);
        !           399:       p2 = gdiv(p2, gpowgs((GEN)idz[2], lgef(pol)-3));
        !           400:       idz = (GEN)idz[1];
        !           401:     }
        !           402:   }
        !           403:   x = gadd(x,idz);
        !           404:
        !           405:   norme = resultantducos(pol,x); if (p1) norme = gmul(norme,p2);
        !           406:   if (gcmp1(mppgcd(divii(norme,pnorm),pnorm))) return a;
        !           407:   return NULL;
        !           408: }
        !           409:
        !           410: static void
        !           411: setprec(GEN x, long prec)
        !           412: {
        !           413:   long i,j, n=lg(x);
        !           414:   for (i=1;i<n;i++)
        !           415:   {
        !           416:     GEN p2,p1 = (GEN)x[i];
        !           417:     for (j=1;j<n;j++)
        !           418:     {
        !           419:       p2 = (GEN)p1[j];
        !           420:       if (typ(p2) == t_REAL) setlg(p2, prec);
        !           421:     }
        !           422:   }
        !           423: }
        !           424:
        !           425: /* find a basis of x whose elements have small norm
        !           426:  * M a bound for the size of coeffs of x */
        !           427: GEN
        !           428: ideal_better_basis(GEN nf, GEN x, GEN M)
        !           429: {
        !           430:   GEN a,b;
        !           431:   long nfprec = (long)nfnewprec(nf,0);
        !           432:   long prec = DEFAULTPREC + (expi(M) >> TWOPOTBITS_IN_LONG);
        !           433:
        !           434:   if (typ(nf[5]) != t_VEC) return x;
        !           435:   if ((prec<<1) < nfprec) prec = (prec+nfprec) >> 1;
        !           436:   a = qf_base_change(gmael(nf,5,3),x,1);
        !           437:   setprec(a,prec);
        !           438:   b = lllgramintern(a,4,1,prec);
        !           439:   if (!b)
        !           440:   {
        !           441:     if (DEBUGLEVEL)
        !           442:       err(warner, "precision too low in ideal_better_basis (1)");
        !           443:     if (nfprec > prec)
        !           444:     {
        !           445:       setprec(a,nfprec);
        !           446:       b = lllgramintern(a,4,1,nfprec);
        !           447:     }
        !           448:   }
        !           449:   if (!b)
        !           450:   {
        !           451:     if (DEBUGLEVEL)
        !           452:       err(warner, "precision too low in ideal_better_basis (2)");
        !           453:     b = lllint(x); /* better than nothing */
        !           454:   }
        !           455:   return gmul(x, b);
        !           456: }
        !           457:
        !           458: static GEN
        !           459: mat_ideal_two_elt(GEN nf, GEN x)
        !           460: {
        !           461:   GEN y,a,beta,pnorm,con,idz, pol = (GEN)nf[1];
        !           462:   long av,tetpil,i,z, N = lgef(pol)-3;
        !           463:
        !           464:   y=cgetg(3,t_VEC); av=avma;
        !           465:   if (lg(x[1])!=N+1) err(typeer,"ideal_two_elt");
        !           466:   if (N == 2)
        !           467:   {
        !           468:     y[1] = lcopy(gcoeff(x,1,1));
        !           469:     y[2] = lcopy((GEN)x[2]); return y;
        !           470:   }
        !           471:
        !           472:   con=content(x); if (!gcmp1(con)) x = gdiv(x,con);
        !           473:   if (lg(x) != N+1) x = idealhermite_aux(nf,x);
        !           474:   idz=gcoeff(x,1,1);
        !           475:   if (gcmp1(idz))
        !           476:   {
        !           477:     y[1]=lpileupto(av,gcopy(con));
        !           478:     y[2]=(long)gscalcol(con,N); return y;
        !           479:   }
        !           480:   pnorm = dethnf(x);
        !           481:   beta = gmul((GEN)nf[7], x);
        !           482:   for (i=2; i<=N; i++)
        !           483:   {
        !           484:     a = check_elt((GEN)beta[i], pol, pnorm, idz);
        !           485:     if (a) break;
        !           486:   }
        !           487:   if (i>N)
        !           488:   {
        !           489:     x = ideal_better_basis(nf,x,pnorm);
        !           490:     beta = gmul((GEN)nf[7], x);
        !           491:     for (i=1; i<=N; i++)
        !           492:     {
        !           493:       a = check_elt((GEN)beta[i], pol, pnorm, idz);
        !           494:       if (a) break;
        !           495:     }
        !           496:   }
        !           497:   if (i>N)
        !           498:   {
        !           499:     long c=0, av1=avma;
        !           500:
        !           501:     if (DEBUGLEVEL>3) fprintferr("ideal_two_elt, hard case: ");
        !           502:     for(;;)
        !           503:     {
        !           504:       if (DEBUGLEVEL>3) fprintferr("%d ", ++c);
        !           505:       a = gzero;
        !           506:       for (i=1; i<=N; i++)
        !           507:       {
        !           508:         z = mymyrand() >> (BITS_IN_RANDOM-5); /* in [0,15] */
        !           509:         if (z >= 9) z -= 7;
        !           510:         a = gadd(a,gmulsg(z,(GEN)beta[i]));
        !           511:       }
        !           512:       a = check_elt(a, pol, pnorm, idz);
        !           513:       if (a) break;
        !           514:       avma=av1;
        !           515:     }
        !           516:     if (DEBUGLEVEL>3) fprintferr("\n");
        !           517:   }
        !           518:   a = centermod(algtobasis_intern(nf,a), idz);
        !           519:   tetpil=avma; y[1]=lmul(idz,con); y[2]=lmul(a,con);
        !           520:   gerepilemanyvec(av,tetpil,y+1,2); return y;
        !           521: }
        !           522:
        !           523: /* Etant donne un ideal ix, ressort un vecteur [a,alpha] a deux composantes
        !           524:  * tel que a soit rationnel et ix=aZ_K+alpha Z_K, alpha etant un vecteur
        !           525:  * colonne sur la base d'entiers. On peut avoir a=0 ou alpha=0, mais on ne
        !           526:  * cherche pas a determiner si ix est principal.
        !           527:  */
        !           528: GEN
        !           529: ideal_two_elt(GEN nf, GEN x)
        !           530: {
        !           531:   GEN z;
        !           532:   long N, tx = idealtyp(&x,&z);
        !           533:
        !           534:   nf=checknf(nf);
        !           535:   if (tx==id_MAT) return mat_ideal_two_elt(nf,x);
        !           536:
        !           537:   N=lgef(nf[1])-3; z=cgetg(3,t_VEC);
        !           538:   if (tx == id_PRINCIPAL)
        !           539:   {
        !           540:     switch(typ(x))
        !           541:     {
        !           542:       case t_INT: case t_FRAC: case t_FRACN:
        !           543:         z[1]=lcopy(x);
        !           544:        z[2]=(long)zerocol(N); return z;
        !           545:
        !           546:       case t_POLMOD:
        !           547:         if (!gegal((GEN)nf[1],(GEN)x[1]))
        !           548:          err(talker,"incompatible number fields in ideal_two_elt");
        !           549:        x=(GEN)x[2]; /* fall through */
        !           550:       case t_POL:
        !           551:         z[1]=zero; z[2]=(long)algtobasis(nf,x); return z;
        !           552:       case t_COL:
        !           553:         if (lg(x)==N+1) { z[1]=zero; z[2]=lcopy(x); return z; }
        !           554:     }
        !           555:   }
        !           556:   else if (tx == id_PRIME)
        !           557:   {
        !           558:     z[1]=lcopy((GEN)x[1]);
        !           559:     z[2]=lcopy((GEN)x[2]); return z;
        !           560:   }
        !           561:   err(typeer,"ideal_two_elt");
        !           562:   return NULL; /* not reached */
        !           563: }
        !           564:
        !           565: /* factorization */
        !           566:
        !           567: GEN
        !           568: idealfactor(GEN nf, GEN x)
        !           569: {
        !           570:   long av,tx, tetpil,i,j,k,lf,lff,N,ls,v,vd;
        !           571:   GEN d,f,f1,f2,ff,ff1,ff2,y1,y2,y,p1,p2,denx;
        !           572:
        !           573:   tx = idealtyp(&x,&y);
        !           574:   if (tx == id_PRIME)
        !           575:   {
        !           576:     y=cgetg(3,t_MAT);
        !           577:     y[1]=lgetg(2,t_COL); mael(y,1,1)=lcopy(x);
        !           578:     y[2]=lgetg(2,t_COL); mael(y,2,1)=un; return y;
        !           579:   }
        !           580:   nf=checknf(nf); av=avma;
        !           581:   if (tx == id_PRINCIPAL) x = principalideal_aux(nf,x);
        !           582:
        !           583:   N=lgef(nf[1])-3; if (lg(x) != N+1) x = idealmat_to_hnf(nf,x);
        !           584:   if (lg(x)==1) err(talker,"zero ideal in idealfactor");
        !           585:   denx=denom(x);
        !           586:   if (gcmp1(denx)) lff=1;
        !           587:   else
        !           588:   {
        !           589:     ff=factor(denx); ff1=(GEN)ff[1]; ff2=(GEN)ff[2];
        !           590:     lff=lg(ff1); x=gmul(denx,x);
        !           591:   }
        !           592:   for (d=gun,i=1; i<=N; i++) d=mulii(d,gcoeff(x,i,i));
        !           593:   f=factor(absi(d)); f1=(GEN)f[1]; f2=(GEN)f[2]; lf=lg(f1);
        !           594:   y1=cgetg((lf+lff-2)*N+1,t_COL); y2=new_chunk((lf+lff-2)*N+1);
        !           595:   k=0;
        !           596:   for (i=1; i<lf; i++)
        !           597:   {
        !           598:     p1=primedec(nf,(GEN)f1[i]); ls=itos((GEN)f2[i]);
        !           599:     vd=ggval(denx,(GEN)f1[i]);
        !           600:     for (j=1; j<lg(p1); j++)
        !           601:     {
        !           602:       p2=(GEN)p1[j];
        !           603:       if (ls)
        !           604:       {
        !           605:        v = idealval(nf,x,p2);
        !           606:        ls -= v*itos((GEN)p2[4]);
        !           607:         v -= vd*itos((GEN)p2[3]);
        !           608:       }
        !           609:       else v = - vd*itos((GEN)p2[3]);
        !           610:       if (v) { y1[++k]=(long)p2; y2[k]=v; }
        !           611:     }
        !           612:   }
        !           613:   for (i=1; i<lff; i++)
        !           614:     if (!divise(d,(GEN)ff1[i]))
        !           615:     {
        !           616:       p1=primedec(nf,(GEN)ff1[i]);
        !           617:       for (j=1; j<lg(p1); j++)
        !           618:       {
        !           619:        p2=(GEN)p1[j]; y1[++k]=(long)p2;
        !           620:        y2[k] = -itos((GEN)ff2[i])*itos((GEN)p2[3]);
        !           621:       }
        !           622:     }
        !           623:   tetpil=avma; y=cgetg(3,t_MAT);
        !           624:   p1=cgetg(k+1,t_COL); y[1]=(long)p1;
        !           625:   p2=cgetg(k+1,t_COL); y[2]=(long)p2;
        !           626:   for (i=1; i<=k; i++) { p1[i]=lcopy((GEN)y1[i]); p2[i]=lstoi(y2[i]); }
        !           627:   return gerepile(av,tetpil,y);
        !           628: }
        !           629:
        !           630: /* vp prime ideal in primedec format. Return valuation(ix) at vp */
        !           631: long
        !           632: idealval(GEN nf, GEN ix, GEN vp)
        !           633: {
        !           634:   long N,v,vd,w,av=avma,av1,lim,i,j,k, tx = typ(ix);
        !           635:   GEN mul,mat,a,x,y,r,bp,p,denx;
        !           636:
        !           637:   nf=checknf(nf); checkprimeid(vp);
        !           638:   if (is_extscalar_t(tx) || tx==t_COL) return element_val(nf,ix,vp);
        !           639:   p=(GEN)vp[1]; N=lgef(nf[1])-3;
        !           640:   tx = idealtyp(&ix,&a);
        !           641:   denx=denom(ix); if (!gcmp1(denx)) ix=gmul(denx,ix);
        !           642:   if (tx != id_MAT)
        !           643:     ix = idealhermite_aux(nf,ix);
        !           644:   else
        !           645:   {
        !           646:     checkid(ix,N);
        !           647:     if (lg(ix) != N+1) ix=idealmat_to_hnf(nf,ix);
        !           648:   }
        !           649:   v = ggval(dethnf_i(ix), p);
        !           650:   vd = ggval(denx,p) * itos((GEN)vp[3]); /* v_p * e */
        !           651:   if (!v) return -vd;
        !           652:
        !           653:   mul = cgetg(N+1,t_MAT); bp=(GEN)vp[5];
        !           654:   mat = cgetg(N+1,t_MAT);
        !           655:   for (j=1; j<=N; j++)
        !           656:   {
        !           657:     mul[j] = (long)element_mulid(nf,bp,j);
        !           658:     x = (GEN)ix[j];
        !           659:     y = cgetg(N+1, t_COL); mat[j] = (long)y;
        !           660:     for (i=1; i<=N; i++)
        !           661:     { /* compute (x.b)_i, ix in HNF ==> x[j+1..N] = 0 */
        !           662:       a = mulii((GEN)x[1], gcoeff(mul,i,1));
        !           663:       for (k=2; k<=j; k++) a = addii(a, mulii((GEN)x[k], gcoeff(mul,i,k)));
        !           664:       /* is it divisible by p ? */
        !           665:       y[i] = ldvmdii(a,p,&r);
        !           666:       if (signe(r)) { avma=av; return -vd; }
        !           667:     }
        !           668:   }
        !           669:   av1 = avma; lim=stack_lim(av1,3);
        !           670:   y = cgetg(N+1,t_COL);
        !           671:   for (w=1; w<v; w++)
        !           672:     for (j=1; j<=N; j++)
        !           673:     {
        !           674:       x = (GEN)mat[j];
        !           675:       for (i=1; i<=N; i++)
        !           676:       { /* compute (x.b)_i */
        !           677:         a = mulii((GEN)x[1], gcoeff(mul,i,1));
        !           678:         for (k=2; k<=N; k++) a = addii(a, mulii((GEN)x[k], gcoeff(mul,i,k)));
        !           679:         /* is it divisible by p ? */
        !           680:         y[i] = ldvmdii(a,p,&r);
        !           681:         if (signe(r)) { avma=av; return w - vd; }
        !           682:       }
        !           683:       r=x; mat[j]=(long)y; y=r;
        !           684:       if (low_stack(lim,stack_lim(av1,3)))
        !           685:       {
        !           686:         GEN *gptr[2]; gptr[0]=&y; gptr[1]=&mat;
        !           687:        if(DEBUGMEM>1) err(warnmem,"idealval");
        !           688:         gerepilemany(av1,gptr,2);
        !           689:       }
        !           690:     }
        !           691:   avma=av; return w - vd;
        !           692: }
        !           693:
        !           694: /* gcd and generalized Bezout */
        !           695:
        !           696: GEN
        !           697: idealadd(GEN nf, GEN x, GEN y)
        !           698: {
        !           699:   long av=avma,N,tx,ty;
        !           700:   GEN z,p1,dx,dy,dz;
        !           701:
        !           702:   tx = idealtyp(&x,&z);
        !           703:   ty = idealtyp(&y,&z);
        !           704:   nf=checknf(nf); N=lgef(nf[1])-3;
        !           705:   z = cgetg(N+1, t_MAT);
        !           706:   if (tx != id_MAT || lg(x)!=N+1) x = idealhermite_aux(nf,x);
        !           707:   if (ty != id_MAT || lg(y)!=N+1) y = idealhermite_aux(nf,y);
        !           708:   if (lg(x) == 1) return gerepileupto(av,y);
        !           709:   if (lg(y) == 1) return gerepileupto(av,x); /* check for 0 ideal */
        !           710:   dx=denom(x);
        !           711:   dy=denom(y); dz=mulii(dx,dy);
        !           712:   if (gcmp1(dz)) dz = NULL; else { x=gmul(x,dz); y=gmul(y,dz); }
        !           713:   p1=mppgcd(detint(x),detint(y));
        !           714:   if (gcmp1(p1))
        !           715:   {
        !           716:     long i,j;
        !           717:     if (!dz) { avma=av; return idmat(N); }
        !           718:     avma = (long)dz; dz = gerepileupto((long)z, ginv(dz));
        !           719:     for (i=1; i<=N; i++)
        !           720:     {
        !           721:       z[i]=lgetg(N+1,t_COL);
        !           722:       for (j=1; j<=N; j++)
        !           723:         coeff(z,j,i) = (i==j)? (long)dz: zero;
        !           724:     }
        !           725:     return z;
        !           726:   }
        !           727:   z=hnfmod(concatsp(x,y),p1); if (dz) z=gdiv(z,dz);
        !           728:   return gerepileupto(av,z);
        !           729: }
        !           730:
        !           731: static GEN
        !           732: get_p1(GEN nf, GEN x, GEN y,long fl)
        !           733: {
        !           734:   GEN u,v,v1,v2,v3,v4;
        !           735:   long i,j,N;
        !           736:
        !           737:   switch(fl)
        !           738:   {
        !           739:     case 1:
        !           740:       v1 = gcoeff(x,1,1);
        !           741:       v2 = gcoeff(y,1,1);
        !           742:       if (typ(v1)!=t_INT || typ(v2)!=t_INT)
        !           743:         err(talker,"ideals don't sum to Z_K in idealaddtoone");
        !           744:       if (gcmp1(bezout(v1,v2,&u,&v)))
        !           745:         return gmul(u,(GEN)x[1]);
        !           746:     default:
        !           747:       v=hnfperm(concatsp(x,y));
        !           748:       v1=(GEN)v[1]; v2=(GEN)v[2]; v3=(GEN)v[3];
        !           749:       j=0; N = lgef(nf[1])-3;
        !           750:       for (i=1; i<=N; i++)
        !           751:       {
        !           752:         if (!gcmp1(gcoeff(v1,i,i)))
        !           753:           err(talker,"ideals don't sum to Z_K in idealaddtoone");
        !           754:         if (gcmp1((GEN)v3[i])) j=i;
        !           755:       }
        !           756:       v4=(GEN)v2[N+j]; setlg(v4,N+1);
        !           757:       return gmul(x,v4);
        !           758:   }
        !           759: }
        !           760:
        !           761: GEN
        !           762: idealaddtoone_i(GEN nf, GEN x, GEN y)
        !           763: {
        !           764:   long t, fl = 1;
        !           765:   GEN p1,xh,yh;
        !           766:
        !           767:   if (DEBUGLEVEL>4)
        !           768:   {
        !           769:     fprintferr(" entering idealaddtoone:\n");
        !           770:     fprintferr(" x = %Z\n",x);
        !           771:     fprintferr(" y = %Z\n",y);
        !           772:   }
        !           773:   t = idealtyp(&x,&p1);
        !           774:   if (t != id_MAT || lg(x) != lg(x[1])) xh = idealhermite_aux(nf,x);
        !           775:   else
        !           776:     { xh=x; fl = isnfscalar((GEN)x[1]); }
        !           777:   t = idealtyp(&y,&p1);
        !           778:   if (t != id_MAT || lg(y) != lg(y[1])) yh = idealhermite_aux(nf,y);
        !           779:   else
        !           780:     { yh=y; if (fl) fl = isnfscalar((GEN)y[1]); }
        !           781:
        !           782:   p1 = get_p1(nf,xh,yh,fl);
        !           783:   p1 = element_reduce(nf,p1, idealmullll(nf,x,y));
        !           784:   if (DEBUGLEVEL>4 && !gcmp0(p1))
        !           785:     fprintferr(" leaving idealaddtoone: %Z\n",p1);
        !           786:   return p1;
        !           787: }
        !           788:
        !           789: /* ideal should be an idele (not mandatory). For internal use. */
        !           790: GEN
        !           791: ideleaddone_aux(GEN nf,GEN x,GEN ideal)
        !           792: {
        !           793:   long i,nba,R1;
        !           794:   GEN p1,p2,p3,arch;
        !           795:
        !           796:   idealtyp(&ideal,&arch);
        !           797:   if (!arch) return idealaddtoone_i(nf,x,ideal);
        !           798:
        !           799:   R1=itos(gmael(nf,2,1));
        !           800:   if (typ(arch)!=t_VEC && lg(arch)!=R1+1)
        !           801:     err(talker,"incorrect idele in idealaddtoone");
        !           802:   for (nba=0,i=1; i<lg(arch); i++)
        !           803:     if (signe(arch[i])) nba++;
        !           804:   if (!nba) return idealaddtoone_i(nf,x,ideal);
        !           805:
        !           806:   p3 = idealaddtoone_i(nf,x,ideal);
        !           807:   if (gcmp0(p3)) p3=(GEN)idealhermite_aux(nf,x)[1];
        !           808:   p1=idealmullll(nf,x,ideal);
        !           809:
        !           810:   p2=zarchstar(nf,p1,arch,nba);
        !           811:   p1=lift_intern(gmul((GEN)p2[3],zsigne(nf,p3,arch)));
        !           812:   p2=(GEN)p2[2]; nba=0;
        !           813:   for (i=1; i<lg(p1); i++)
        !           814:     if (signe(p1[i])) { nba=1; p3=element_mul(nf,p3,(GEN)p2[i]); }
        !           815:   if (gcmp0(p3)) return gcopy((GEN)x[1]); /* can happen if ideal = Z_K */
        !           816:   return nba? p3: gcopy(p3);
        !           817: }
        !           818:
        !           819: static GEN
        !           820: unnf_minus_x(GEN x)
        !           821: {
        !           822:   long i, N = lg(x);
        !           823:   GEN y = cgetg(N,t_COL);
        !           824:
        !           825:   y[1] = lsub(gun,(GEN)x[1]);
        !           826:   for (i=2;i<N; i++) y[i] = lneg((GEN)x[i]);
        !           827:   return y;
        !           828: }
        !           829:
        !           830: static GEN
        !           831: addone(GEN f(GEN,GEN,GEN), GEN nf, GEN x, GEN y)
        !           832: {
        !           833:   GEN z = cgetg(3,t_VEC);
        !           834:   long av=avma;
        !           835:
        !           836:   nf=checknf(nf); x = gerepileupto(av, f(nf,x,y));
        !           837:   z[1]=(long)x; z[2]=(long)unnf_minus_x(x); return z;
        !           838: }
        !           839:
        !           840: GEN
        !           841: idealaddtoone(GEN nf, GEN x, GEN y)
        !           842: {
        !           843:   return addone(idealaddtoone_i,nf,x,y);
        !           844: }
        !           845:
        !           846: GEN
        !           847: ideleaddone(GEN nf,GEN x,GEN idele)
        !           848: {
        !           849:   return addone(ideleaddone_aux,nf,x,idele);
        !           850: }
        !           851:
        !           852: GEN
        !           853: nfmodprinit(GEN nf, GEN pr)
        !           854: {
        !           855:   long av;
        !           856:   GEN p,e,p1,prhall;
        !           857:
        !           858:   nf = checknf(nf); checkprimeid(pr);
        !           859:   prhall = cgetg(3,t_VEC);
        !           860:   prhall[1] = (long) prime_to_ideal(nf,pr);
        !           861:
        !           862:   av = avma; p = (GEN)pr[1]; e = (GEN)pr[3];
        !           863:   p1 = cgetg(2,t_MAT);
        !           864:   p1[1] = ldiv(element_pow(nf,(GEN)pr[5],e), gpuigs(p,itos(e)-1));
        !           865:   p1 = hnfmodid(idealhermite_aux(nf,p1), p);
        !           866:   p1 = idealaddtoone_i(nf,pr,p1);
        !           867:
        !           868:   /* p1 = 1 mod pr, p1 = 0 mod q^{e_q} for all other primes q | p */
        !           869:   prhall[2] = lpileupto(av, unnf_minus_x(p1)); return prhall;
        !           870: }
        !           871:
        !           872: /* given an element x in Z_K and an integral ideal y with x, y coprime,
        !           873:    outputs an element inverse of x modulo y */
        !           874: GEN
        !           875: element_invmodideal(GEN nf, GEN x, GEN y)
        !           876: {
        !           877:   long av=avma,N,i, fl = 1;
        !           878:   GEN v,p1,xh,yh;
        !           879:
        !           880:   nf=checknf(nf); N=lgef(nf[1])-3;
        !           881:   if (ideal_is_zk(y,N)) return zerocol(N);
        !           882:   if (DEBUGLEVEL>4)
        !           883:   {
        !           884:     fprintferr(" entree dans element_invmodideal() :\n");
        !           885:     fprintferr(" x = "); outerr(x);
        !           886:     fprintferr(" y = "); outerr(y);
        !           887:   }
        !           888:   i = lg(y);
        !           889:   if (typ(y)!=t_MAT || i==1 || i != lg(y[1])) yh=idealhermite_aux(nf,y);
        !           890:   else
        !           891:     { yh=y; fl = isnfscalar((GEN)y[1]); }
        !           892:   switch (typ(x))
        !           893:   {
        !           894:     case t_POL: case t_POLMOD: case t_COL:
        !           895:       xh = idealhermite_aux(nf,x); break;
        !           896:     default: err(typeer,"element_invmodideal");
        !           897:   }
        !           898:   p1 = get_p1(nf,xh,yh,fl);
        !           899:   p1 = element_div(nf,p1,x);
        !           900:   v = gerepileupto(av, nfreducemodideal(nf,p1,y));
        !           901:   if (DEBUGLEVEL>2)
        !           902:     { fprintferr(" sortie de element_invmodideal : v = "); outerr(v); }
        !           903:   return v;
        !           904: }
        !           905:
        !           906: GEN
        !           907: idealaddmultoone(GEN nf, GEN list)
        !           908: {
        !           909:   long av=avma,tetpil,N,i,i1,j,k;
        !           910:   GEN z,v,v1,v2,v3,p1;
        !           911:
        !           912:   nf=checknf(nf); N=lgef(nf[1])-3;
        !           913:   if (DEBUGLEVEL>4)
        !           914:   {
        !           915:     fprintferr(" entree dans idealaddmultoone() :\n");
        !           916:     fprintferr(" list = "); outerr(list);
        !           917:   }
        !           918:   if (typ(list)!=t_VEC && typ(list)!=t_COL)
        !           919:     err(talker,"not a list in idealaddmultoone");
        !           920:   k=lg(list); z=cgetg(1,t_MAT); list = dummycopy(list);
        !           921:   if (k==1) err(talker,"ideals don't sum to Z_K in idealaddmultoone");
        !           922:   for (i=1; i<k; i++)
        !           923:   {
        !           924:     p1=(GEN)list[i];
        !           925:     if (typ(p1)!=t_MAT || lg(p1)!=lg(p1[1]))
        !           926:       list[i] = (long)idealhermite_aux(nf,p1);
        !           927:     z = concatsp(z,(GEN)list[i]);
        !           928:   }
        !           929:   v=hnfperm(z); v1=(GEN)v[1]; v2=(GEN)v[2]; v3=(GEN)v[3]; j=0;
        !           930:   for (i=1; i<=N; i++)
        !           931:   {
        !           932:     if (!gcmp1(gcoeff(v1,i,i)))
        !           933:       err(talker,"ideals don't sum to Z_K in idealaddmultoone");
        !           934:     if (gcmp1((GEN)v3[i])) j=i;
        !           935:   }
        !           936:
        !           937:   v=(GEN)v2[(k-2)*N+j]; z=cgetg(k,t_VEC);
        !           938:   for (i=1; i<k; i++)
        !           939:   {
        !           940:     p1=cgetg(N+1,t_COL); z[i]=(long)p1;
        !           941:     for (i1=1; i1<=N; i1++) p1[i1]=v[(i-1)*N+i1];
        !           942:   }
        !           943:   tetpil=avma; v=cgetg(k,typ(list));
        !           944:   for (i=1; i<k; i++) v[i]=lmul((GEN)list[i],(GEN)z[i]);
        !           945:   if (DEBUGLEVEL>2)
        !           946:     { fprintferr(" sortie de idealaddmultoone v = "); outerr(v); }
        !           947:   return gerepile(av,tetpil,v);
        !           948: }
        !           949:
        !           950: /* multiplication */
        !           951:
        !           952: /* x integral ideal (without archimedean component) in HNF form
        !           953:  * [a,alpha,n] corresponds to the ideal aZ_K+alpha Z_K of norm n (a is a
        !           954:  * rational integer). Multiply them
        !           955:  */
        !           956: static GEN
        !           957: idealmulspec(GEN nf, GEN x, GEN a, GEN alpha, GEN n)
        !           958: {
        !           959:   long i, N=lg(x)-1;
        !           960:   GEN m;
        !           961:
        !           962:   if (isnfscalar(alpha))
        !           963:     return gmul(mppgcd(a,(GEN)alpha[1]),x);
        !           964:   m = cgetg((N<<1)+1,t_MAT);
        !           965:   for (i=1; i<=N; i++) n = mulii(n,gcoeff(x,i,i));
        !           966:   for (i=1; i<=N; i++) m[i]=(long)element_muli(nf,alpha,(GEN)x[i]);
        !           967:   for (i=1; i<=N; i++) m[i+N]=lmul(a,(GEN)x[i]);
        !           968:   return hnfmod(m,n);
        !           969: }
        !           970:
        !           971: /* x ideal (matrix form,maximal rank), vp prime ideal (primedec). Output the
        !           972:  * product. Can be used for arbitrary vp of the form [p,a,e,f,b], IF vp
        !           973:  * =pZ_K+aZ_K, p is an integer, and norm(vp) = p^f; e and b are not used. For
        !           974:  * internal use.
        !           975:  */
        !           976: GEN
        !           977: idealmulprime(GEN nf, GEN x, GEN vp)
        !           978: {
        !           979:   GEN dx, denx = denom(x);
        !           980:
        !           981:   if (gcmp1(denx)) denx = NULL; else x=gmul(denx,x);
        !           982:   dx = powgi((GEN)vp[1], (GEN)vp[4]);
        !           983:   x = idealmulspec(nf,x, (GEN)vp[1], (GEN)vp[2], dx);
        !           984:   return denx? gdiv(x,denx): x;
        !           985: }
        !           986:
        !           987: /* Assume ix and iy are integral in HNF form (or ideles of the same form).
        !           988:  * Ideal in iy can be of the form [a,b,N], with iy = (a,b) and N = norm y
        !           989:  * For internal use. */
        !           990: GEN
        !           991: idealmulh(GEN nf, GEN ix, GEN iy)
        !           992: {
        !           993:   long N,i, f = 0;
        !           994:   GEN res,x,y,dy;
        !           995:
        !           996:   if (typ(ix)==t_VEC) {f=1;  x=(GEN)ix[1];} else x=ix;
        !           997:   if (typ(iy)==t_VEC && lg(iy)==3) {f+=2; y=(GEN)iy[1];} else y=iy;
        !           998:   if (f) res = cgetg(3,t_VEC);
        !           999:
        !          1000:   if (typ(y)==t_VEC)
        !          1001:     y = idealmulspec(nf,x,(GEN)y[1],(GEN)y[2],(GEN)y[3]);
        !          1002:   else
        !          1003:   {
        !          1004:
        !          1005:     N=lg(x)-1; dy=gcoeff(y,1,1);
        !          1006:     for (i=2; i<=N; i++) dy=mulii(dy,gcoeff(y,i,i));
        !          1007:     y = ideal_two_elt(nf,y);
        !          1008:     y = idealmulspec(nf,x,(GEN)y[1],(GEN)y[2],dy);
        !          1009:   }
        !          1010:
        !          1011:   if (!f) return y;
        !          1012:   res[1]=(long)y;
        !          1013:   if (f==3) y = gadd((GEN)ix[2],(GEN)iy[2]);
        !          1014:   else
        !          1015:   {
        !          1016:     y = (f==2)? (GEN)iy[2]: (GEN)ix[2];
        !          1017:     y = gcopy(y);
        !          1018:   }
        !          1019:   res[2]=(long)y; return res;
        !          1020: }
        !          1021:
        !          1022: /* x and y are ideals in matrix form */
        !          1023: static GEN
        !          1024: idealmat_mul(GEN nf, GEN x, GEN y)
        !          1025: {
        !          1026:   long i,j, rx=lg(x)-1, ry=lg(y)-1;
        !          1027:   GEN dx,dy,m;
        !          1028:
        !          1029:   dx=denom(x); if (!gcmp1(dx)) x=gmul(dx,x);
        !          1030:   dy=denom(y); if (!gcmp1(dy)) y=gmul(dy,y);
        !          1031:   dx = mulii(dx,dy);
        !          1032:   if (rx<=2 || ry<=2)
        !          1033:   {
        !          1034:     m=cgetg(rx*ry+1,t_MAT);
        !          1035:     for (i=1; i<=rx; i++)
        !          1036:       for (j=1; j<=ry; j++)
        !          1037:         m[(i-1)*ry+j]=(long)element_muli(nf,(GEN)x[i],(GEN)y[j]);
        !          1038:     y=hnfmod(m, detint(m));
        !          1039:   }
        !          1040:   else
        !          1041:   {
        !          1042:     x=idealmat_to_hnf(nf,x);
        !          1043:     y=idealmat_to_hnf(nf,y); y=idealmulh(nf,x,y);
        !          1044:   }
        !          1045:   return gcmp1(dx)? y: gdiv(y,dx);
        !          1046: }
        !          1047:
        !          1048: /* y is principal */
        !          1049: static GEN
        !          1050: add_arch(GEN nf, GEN ax, GEN y)
        !          1051: {
        !          1052:   long tetpil, av=avma, prec=precision(ax);
        !          1053:
        !          1054:   y = get_arch(nf,y,prec); tetpil=avma;
        !          1055:   return gerepile(av,tetpil,gadd(ax,y));
        !          1056: }
        !          1057:
        !          1058: /* output the ideal product ix.iy (don't reduce) */
        !          1059: GEN
        !          1060: idealmul(GEN nf, GEN x, GEN y)
        !          1061: {
        !          1062:   long tx,ty,av,f;
        !          1063:   GEN res,ax,ay,p1;
        !          1064:
        !          1065:   tx = idealtyp(&x,&ax);
        !          1066:   ty = idealtyp(&y,&ay);
        !          1067:   if (tx>ty) {
        !          1068:     res=ax; ax=ay; ay=res;
        !          1069:     res=x; x=y; y=res;
        !          1070:     f=tx; tx=ty; ty=f;
        !          1071:   }
        !          1072:   f = (ax||ay); if (f) res = cgetg(3,t_VEC); /* product is an idele */
        !          1073:   nf=checknf(nf); av=avma;
        !          1074:   switch(tx)
        !          1075:   {
        !          1076:     case id_PRINCIPAL:
        !          1077:       switch(ty)
        !          1078:       {
        !          1079:         case id_PRINCIPAL:
        !          1080:           p1 = idealhermite_aux(nf, element_mul(nf,x,y));
        !          1081:           break;
        !          1082:         case id_PRIME:
        !          1083:           p1 = gmul((GEN)y[1],x);
        !          1084:           p1 = two_to_hnf(nf,p1, element_mul(nf,(GEN)y[2],x));
        !          1085:           break;
        !          1086:         default: /* id_MAT */
        !          1087:           p1 = idealmat_mul(nf,y, principalideal_aux(nf,x));
        !          1088:       }break;
        !          1089:
        !          1090:     case id_PRIME:
        !          1091:       p1 = (ty==id_PRIME)? prime_to_ideal_aux(nf,y)
        !          1092:                          : idealmat_to_hnf(nf,y);
        !          1093:       p1 = idealmulprime(nf,p1,x); break;
        !          1094:
        !          1095:     default: /* id_MAT */
        !          1096:       p1 = idealmat_mul(nf,x,y);
        !          1097:   }
        !          1098:   p1 = gerepileupto(av,p1);
        !          1099:   if (!f) return p1;
        !          1100:
        !          1101:   if (ax && ay) ax = gadd(ax,ay);
        !          1102:   else
        !          1103:   {
        !          1104:     if (ax)
        !          1105:       ax = (ty==id_PRINCIPAL)? add_arch(nf,ax,y): gcopy(ax);
        !          1106:     else
        !          1107:       ax = (tx==id_PRINCIPAL)? add_arch(nf,ay,x): gcopy(ay);
        !          1108:   }
        !          1109:   res[1]=(long)p1; res[2]=(long)ax; return res;
        !          1110: }
        !          1111:
        !          1112: /* different of nf */
        !          1113: GEN
        !          1114: differente(GEN nf, GEN premiers)
        !          1115: {
        !          1116:   long av=avma,i,j,vi,ei,v,nb_p,vpc;
        !          1117:   GEN ideal,diff,liste_id,p1,pcon,pr,pol,a,alpha;
        !          1118:
        !          1119:   pol=(GEN)nf[1];
        !          1120:   if (DEBUGLEVEL>1) fprintferr("Computing different\n");
        !          1121:   if (gcmp1((GEN)nf[4]))
        !          1122:   {
        !          1123:     p1 = derivpol(pol);
        !          1124:     return gerepileupto(av,idealhermite_aux(nf,p1));
        !          1125:   }
        !          1126:
        !          1127:   ideal = gmul((GEN)nf[3],ginv(gmael(nf,5,4)));
        !          1128:   pcon = content(ideal);
        !          1129:   if (!gcmp1(pcon)) ideal=gdiv(ideal,pcon);
        !          1130:
        !          1131:   ideal=hnfmodid(ideal,divii((GEN)nf[3],pcon));
        !          1132:   if (DEBUGLEVEL>1) msgtimer("hnf(D*delta^-1)");
        !          1133:
        !          1134:   if (!premiers)
        !          1135:   {
        !          1136:     premiers=factor(absi((GEN)nf[3]));
        !          1137:     if (DEBUGLEVEL>1) msgtimer("factor(D)");
        !          1138:   }
        !          1139:   diff=idmat(lgef(nf[1])-3); nb_p=lg(premiers[1]);
        !          1140:
        !          1141:   for (i=1; i<nb_p; i++)
        !          1142:   {
        !          1143:     pr=gcoeff(premiers,i,1); liste_id = primedec(nf,pr);
        !          1144:     vi=itos(gcoeff(premiers,i,2)); vpc=ggval(pcon,pr);
        !          1145:     for (j=1; j<lg(liste_id); j++)
        !          1146:     {
        !          1147:       p1=(GEN)liste_id[j]; ei=itos((GEN)p1[3]);
        !          1148:       if (ei>1)
        !          1149:       {
        !          1150:        if (DEBUGLEVEL>1) fprintferr("treating %Z\n",p1);
        !          1151:        if (signe(ressi(ei,pr)))
        !          1152:           v = ei-1;
        !          1153:        else
        !          1154:          v = ei*(vi-vpc)-idealval(nf,ideal,p1);
        !          1155:         a = gpuigs(pr, 1+(v-1)/ei);
        !          1156:         alpha = element_pow(nf,(GEN)p1[2],stoi(v));
        !          1157:         v *= itos((GEN)p1[4]);
        !          1158:        diff = idealmulspec(nf,diff,a,alpha,gpuigs(pr,v));
        !          1159:       }
        !          1160:     }
        !          1161:   }
        !          1162:   return gerepileupto(av,diff);
        !          1163: }
        !          1164:
        !          1165: /* norm of an ideal */
        !          1166: GEN
        !          1167: idealnorm(GEN nf, GEN x)
        !          1168: {
        !          1169:   long av = avma,tetpil;
        !          1170:   GEN y;
        !          1171:
        !          1172:   nf = checknf(nf);
        !          1173:   switch(idealtyp(&x,&y))
        !          1174:   {
        !          1175:     case id_PRIME:
        !          1176:       return powgi((GEN)x[1],(GEN)x[4]);
        !          1177:     case id_PRINCIPAL:
        !          1178:       x = gnorm(basistoalg(nf,x)); break;
        !          1179:     default:
        !          1180:       if (lg(x) != lgef(nf[1])-2) x = idealhermite_aux(nf,x);
        !          1181:       x = det(x);
        !          1182:   }
        !          1183:   tetpil=avma; return gerepile(av,tetpil,gabs(x,0));
        !          1184: }
        !          1185:
        !          1186: /* inverse */
        !          1187:
        !          1188: /* P.M & M.H. */
        !          1189: static GEN
        !          1190: hnfideal_inv(GEN nf, GEN x)
        !          1191: {
        !          1192:   long N = lgef(nf[1])-3;
        !          1193:   GEN denx = denom(x), detx,dual,p1;
        !          1194:
        !          1195:   if (gcmp1(denx)) denx = NULL; else x = gmul(x,denx);
        !          1196:   detx = dethnf(x);
        !          1197:   if (gcmp0(detx)) err(talker, "cannot invert zero ideal");
        !          1198:   x = idealmulh(nf,x, gmael(nf,5,7));
        !          1199:   dual = gauss(x, gmul(detx, gmael(nf,5,6)));
        !          1200:   dual = gdiv(gtrans(dual), detx);
        !          1201:
        !          1202:  /* nf[5][4] is a dense symmetric matrix.  We computed
        !          1203:   * nf[5][6] = fieldd * ginv(nf[5][4]) in initalg.
        !          1204:   * x is upper triangular (HNF), and easily inverted.
        !          1205:   * The factor fieldd cancels while solving the linear equations.
        !          1206:   */
        !          1207:   p1 = denom(dual); dual = gmul(dual, p1);
        !          1208:   dual = hnfmod(dual, gdiv(gpowgs(p1,N),detx));
        !          1209:   if (denx) p1 = gdiv(p1,denx);
        !          1210:   return gdiv(dual,p1);
        !          1211: }
        !          1212:
        !          1213: /* Calcule le dual de mat_id pour la forme trace */
        !          1214: GEN
        !          1215: oldidealinv(GEN nf, GEN x)
        !          1216: {
        !          1217:   GEN res,dual,di,ax;
        !          1218:   long av,tetpil, tx = idealtyp(&x,&ax);
        !          1219:
        !          1220:   if (tx!=id_MAT) return idealinv(nf,x);
        !          1221:   if (ax) res = cgetg(3,t_VEC);
        !          1222:   nf=checknf(nf); av=avma;
        !          1223:   if (lg(x)!=lgef(nf[1])) x = idealmat_to_hnf(nf,x);
        !          1224:
        !          1225:   dual = ginv(gmul(gtrans(x), gmael(nf,5,4)));
        !          1226:   di=denom(dual); dual=gmul(di,dual);
        !          1227:   dual = idealmat_mul(nf,gmael(nf,5,5), dual);
        !          1228:   tetpil=avma; dual = gerepile(av,tetpil,gdiv(dual,di));
        !          1229:   if (!ax) return dual;
        !          1230:   res[1]=(long)dual; res[2]=lneg(ax); return res;
        !          1231: }
        !          1232:
        !          1233: /* Calcule le dual de mat_id pour la forme trace */
        !          1234: GEN
        !          1235: idealinv(GEN nf, GEN x)
        !          1236: {
        !          1237:   GEN res,ax,p1;
        !          1238:   long av=avma, tx = idealtyp(&x,&ax);
        !          1239:
        !          1240:   if (ax) res = cgetg(3,t_VEC);
        !          1241:   nf=checknf(nf); av=avma;
        !          1242:   switch (tx)
        !          1243:   {
        !          1244:     case id_MAT:
        !          1245:       if (lg(x) != lg(x[1])) x = idealmat_to_hnf(nf,x);
        !          1246:       x = hnfideal_inv(nf,x); break;
        !          1247:     case id_PRINCIPAL: tx = typ(x);
        !          1248:       if (is_const_t(tx)) x = ginv(x);
        !          1249:       else
        !          1250:       {
        !          1251:         switch(tx)
        !          1252:         {
        !          1253:           case t_COL: x = gmul((GEN)nf[7],x); break;
        !          1254:           case t_POLMOD: x = (GEN)x[2]; break;
        !          1255:         }
        !          1256:         x = ginvmod(x,(GEN)nf[1]);
        !          1257:       }
        !          1258:       x = idealhermite_aux(nf,x); break;
        !          1259:     case id_PRIME:
        !          1260:       p1=cgetg(6,t_VEC); p1[1]=x[1]; p1[2]=x[5];
        !          1261:       p1[3]=p1[5]=zero; p1[4]=lsubsi(lgef(nf[1])-3, (GEN)x[4]);
        !          1262:       x = gdiv(prime_to_ideal_aux(nf,p1), (GEN)x[1]);
        !          1263:   }
        !          1264:   x = gerepileupto(av,x); if (!ax) return x;
        !          1265:   res[1]=(long)x; res[2]=lneg(ax); return res;
        !          1266: }
        !          1267:
        !          1268: static GEN
        !          1269: idealpowprime(GEN nf, GEN vp, GEN n)
        !          1270: {
        !          1271:   GEN n1, x = dummycopy(vp);
        !          1272:   long s = signe(n);
        !          1273:
        !          1274:   if (s < 0) n=negi(n);
        !          1275:   n1 = gceil(gdiv(n,(GEN)x[3]));
        !          1276:   x[1]=(long)powgi((GEN)x[1],n1);
        !          1277:   if (s < 0)
        !          1278:     x[2]=ldiv(element_pow(nf,(GEN)x[5],n), powgi((GEN)vp[1],subii(n,n1)));
        !          1279:   else
        !          1280:     x[2]=(long)element_pow(nf,(GEN)x[2],n);
        !          1281:   x = prime_to_ideal_aux(nf,x);
        !          1282:   if (s<0) x = gdiv(x, powgi((GEN)vp[1],n1));
        !          1283:   return x;
        !          1284: }
        !          1285:
        !          1286: /* raise the ideal x to the power n (in Z) */
        !          1287: GEN
        !          1288: idealpow(GEN nf, GEN x, GEN n)
        !          1289: {
        !          1290:   long tx,N,av,s,i;
        !          1291:   GEN res,ax,m,denx,denz,dx,n1,a,alpha;
        !          1292:
        !          1293:   if (typ(n) != t_INT) err(talker,"non-integral exponent in idealpow");
        !          1294:   tx = idealtyp(&x,&ax);
        !          1295:   if (ax) res = cgetg(3,t_VEC);
        !          1296:   nf = checknf(nf);
        !          1297:   av=avma; N=lgef(nf[1])-3; s=signe(n);
        !          1298:   if (!s) x = idmat(N);
        !          1299:   else
        !          1300:     switch(tx)
        !          1301:     {
        !          1302:       case id_PRINCIPAL: tx = typ(x);
        !          1303:         if (!is_const_t(tx))
        !          1304:           switch(tx)
        !          1305:           {
        !          1306:             case t_COL: x = gmul((GEN)nf[7],x);
        !          1307:             case t_POL: x = gmodulcp(x,(GEN)nf[1]);
        !          1308:           }
        !          1309:         x = gpui(x,n,0);
        !          1310:         x = idealhermite_aux(nf,x); break;
        !          1311:       case id_PRIME:
        !          1312:         x = idealpowprime(nf,x,n); break;
        !          1313:       default:
        !          1314:         n1 = (s<0)? negi(n): n;
        !          1315:
        !          1316:         denx=denom(x); if (gcmp1(denx)) denx=NULL; else x = gmul(x,denx);
        !          1317:         a=ideal_two_elt(nf,x); alpha=(GEN)a[2]; a=(GEN)a[1];
        !          1318:         dx=gcoeff(x,1,1); for (i=2; i<=N; i++) dx=mulii(dx,gcoeff(x,i,i));
        !          1319:
        !          1320:         m = cgetg(N+1,t_MAT); a = gpui(a,n1,0);
        !          1321:         alpha = element_pow(nf,alpha,n1);
        !          1322:         for (i=1; i<=N; i++) m[i]=(long)element_mulid(nf,alpha,i);
        !          1323:         m = concatsp(m, gscalmat(a,N));
        !          1324:         x = hnfmod(m, gpui(dx,n1,0));
        !          1325:         if (s<0) x = hnfideal_inv(nf,x);
        !          1326:         if (denx) { denz=gpui(denx,negi(n),0); x=gmul(denz,x); }
        !          1327:     }
        !          1328:   x = gerepileupto(av, x);
        !          1329:   if (!ax) return x;
        !          1330:   res[1]=(long)x; res[2]=lmul(n,ax); return res;
        !          1331: }
        !          1332:
        !          1333: /* Return ideal^e in number field nf. e is a C integer. */
        !          1334: GEN
        !          1335: idealpows(GEN nf, GEN ideal, long e)
        !          1336: {
        !          1337:   long court[] = {evaltyp(t_INT) | m_evallg(3),0,0};
        !          1338:   affsi(e,court); return idealpow(nf,ideal,court);
        !          1339: }
        !          1340:
        !          1341: /* compute vp^n (vp prime, n integer), reducing along the way if n is big */
        !          1342: GEN
        !          1343: idealpowred_prime(GEN nf, GEN vp, GEN n, long prec)
        !          1344: {
        !          1345:   long av=avma,tetpil,i,m,RU, s = signe(n);
        !          1346:   GEN x = cgetg(3,t_VEC);
        !          1347:   ulong j;
        !          1348:
        !          1349:   RU = itos(gmael(nf,2,1)) + itos(gmael(nf,2,2));
        !          1350:   x[2] =(long)zerocol(RU); settyp(x[2],t_VEC);
        !          1351:   if (absi_cmp(n,stoi(16)) < 0)
        !          1352:   {
        !          1353:     x[1] = s? (long)idealpowprime(nf,vp,n):
        !          1354:               (long)idmat(lgef(nf[1])-3);
        !          1355:     tetpil=avma;
        !          1356:     return gerepile(av,tetpil,ideallllred(nf,x,NULL,prec));
        !          1357:   }
        !          1358:
        !          1359:   i = lgefint(n)-1; m=n[i]; j=HIGHBIT;
        !          1360:   while ((m&j)==0) j>>=1;
        !          1361:   x[1] = (long)prime_to_ideal_aux(nf,vp);
        !          1362:   for (j>>=1; j; j>>=1)
        !          1363:   {
        !          1364:     x = idealmul(nf,x,x);
        !          1365:     if (m&j) x[1] = (long)idealmulprime(nf,(GEN)x[1],vp);
        !          1366:     x = ideallllred(nf,x,NULL,prec);
        !          1367:   }
        !          1368:   for (i--; i>=2; i--)
        !          1369:     for (m=n[i],j=HIGHBIT; j; j>>=1)
        !          1370:     {
        !          1371:       x = idealmul(nf,x,x);
        !          1372:       if (m&j) x[1] = (long)idealmulprime(nf,(GEN)x[1],vp);
        !          1373:       x = ideallllred(nf,x,NULL,prec);
        !          1374:     }
        !          1375:   if (s < 0) x = idealinv(nf,x);
        !          1376:   return gerepileupto(av,x);
        !          1377: }
        !          1378:
        !          1379: long
        !          1380: isideal(GEN nf,GEN x)
        !          1381: {
        !          1382:   long N,av,i,j,k,tx=typ(x),lx;
        !          1383:   GEN p1,minv;
        !          1384:
        !          1385:   nf=checknf(nf); lx=lg(x);
        !          1386:   if (tx==t_VEC && lx==3) { x=(GEN)x[1]; tx=typ(x); lx=lg(x); }
        !          1387:   if (is_scalar_t(tx))
        !          1388:     return (tx==t_INT || tx==t_FRAC || tx==t_FRACN || tx==t_POL ||
        !          1389:                      (tx==t_POLMOD && gegal((GEN)nf[1],(GEN)x[1])));
        !          1390:   if (typ(x)==t_VEC) return (lx==6);
        !          1391:   if (typ(x)!=t_MAT) return 0;
        !          1392:   if (lx == 1) return 1;
        !          1393:   N=lgef(nf[1])-2; if (lg(x[1]) != N) return 0;
        !          1394:
        !          1395:   av=avma;
        !          1396:   if (lx != N) x = idealmat_to_hnf(nf,x);
        !          1397:   x = gdiv(x,content(x)); minv=ginv(x);
        !          1398:
        !          1399:   for (i=1; i<N; i++)
        !          1400:     for (j=1; j<N; j++)
        !          1401:     {
        !          1402:       p1=gmul(minv, element_mulid(nf,(GEN)x[i],j));
        !          1403:       for (k=1; k<N; k++)
        !          1404:        if (typ(p1[k])!=t_INT) { avma=av; return 0; }
        !          1405:     }
        !          1406:   avma=av; return 1;
        !          1407: }
        !          1408:
        !          1409: GEN
        !          1410: idealdiv(GEN nf, GEN x, GEN y)
        !          1411: {
        !          1412:   long av=avma,tetpil;
        !          1413:   GEN z=idealinv(nf,y);
        !          1414:
        !          1415:   tetpil=avma; return gerepile(av,tetpil,idealmul(nf,x,z));
        !          1416: }
        !          1417:
        !          1418: GEN
        !          1419: idealdivexact(GEN nf, GEN x, GEN y)
        !          1420: /*  This routine computes the quotient x/y of two ideals in the number field
        !          1421:  *  nf. It assumes that the quotient is an integral ideal.
        !          1422:  *
        !          1423:  *  The idea is to find an ideal z dividing y
        !          1424:  *  such that gcd(N(x)/N(z), N(z)) = 1. Then
        !          1425:  *
        !          1426:  *    x + (N(x)/N(z))    x
        !          1427:  *    --------------- = -----
        !          1428:  *    y + (N(y)/N(z))    y
        !          1429:  *
        !          1430:  *  When x and y are integral ideals, this identity can be checked by looking
        !          1431:  *  at the exponent of a prime ideal p on both sides of the equation.
        !          1432:  *
        !          1433:  *  Specifically, if a prime ideal p divides N(z), then it divides neither
        !          1434:  *  N(x)/N(z) nor N(y)/N(z) (since N(x)/N(z) is the product of the integers
        !          1435:  *  N(x/y) and N(y/z)).  Both the numerator and the denominator on the left
        !          1436:  *  will be coprime to p.  So will x/y, since x/y is assumed integral and its
        !          1437:  *  norm N(x/y) is coprime to p
        !          1438:  *
        !          1439:  *  If instead p does not divide N(z), then the power of p dividing N(x)/N(z)
        !          1440:  *  is the same as the power of p dividing N(x), which is at least as large
        !          1441:  *  as the power of p dividing x.  Likewise for N(y)/N(z).  So the power of p
        !          1442:  *  dividing the left side equals the power of dividing the right side.
        !          1443:  *
        !          1444:  *             Peter Montgomery
        !          1445:  *             July, 1994.
        !          1446:  */
        !          1447: {
        !          1448:   long av = avma, tetpil,N;
        !          1449:   GEN x1,y1,detx1,dety1,detq,gcancel,gtemp, cy = content(y);
        !          1450:
        !          1451:   nf=checknf(nf); N=lgef(nf[1])-3;
        !          1452:   if (gcmp0(cy)) err(talker, "cannot invert zero ideal");
        !          1453:
        !          1454:   x1 = gdiv(x,cy); detx1 = idealnorm(nf,x1);
        !          1455:   if (gcmp0(detx1)) { avma = av; return gcopy(x); } /* numerator is zero */
        !          1456:
        !          1457:   y1 = gdiv(y,cy); dety1 = idealnorm(nf,y1);
        !          1458:   detq = gdiv(detx1,dety1);
        !          1459:   if (!gcmp1(denom(x1)) || typ(detq) != t_INT)
        !          1460:     err(talker, "quotient not integral in idealdivexact");
        !          1461:   gcancel = dety1;
        !          1462:  /* Find a norm gcancel such that
        !          1463:   * (1) gcancel divides dety1;
        !          1464:   * (2) gcd(detx1/gcancel, gcancel) = 1.
        !          1465:   */
        !          1466:   do
        !          1467:   {
        !          1468:     gtemp = ggcd(gcancel, gdiv(detx1,gcancel));
        !          1469:     gcancel = gdiv(gcancel,gtemp);
        !          1470:   }
        !          1471:   while (!gcmp1(gtemp));
        !          1472:  /*                    x1 + (detx1/gcancel)
        !          1473:   * Replace x1/y1 by:  --------------------
        !          1474:   *                    y1 + (dety1/gcancel)
        !          1475:   */
        !          1476:
        !          1477:   x1 = idealadd(nf, x1, gscalmat(gdiv(detx1, gcancel), N));
        !          1478:   /* y1 reduced to unit ideal ? */
        !          1479:   if (gegal(gcancel,dety1)) return gerepileupto(av, x1);
        !          1480:
        !          1481:   y1 = idealadd(nf,y1, gscalmat(gdiv(dety1,gcancel), N));
        !          1482:   y1 = hnfideal_inv(nf,y1); tetpil = avma;
        !          1483:   return gerepile(av, tetpil, idealmat_mul(nf,x1,y1));
        !          1484: }
        !          1485:
        !          1486: GEN
        !          1487: idealintersect(GEN nf, GEN x, GEN y)
        !          1488: {
        !          1489:   long av=avma,lz,i,N;
        !          1490:   GEN z,dx,dy;
        !          1491:
        !          1492:   nf=checknf(nf); N=lgef(nf[1])-3;
        !          1493:   if (idealtyp(&x,&z)!=t_MAT || lg(x)!=N+1) x=idealhermite_aux(nf,x);
        !          1494:   if (idealtyp(&y,&z)!=t_MAT || lg(y)!=N+1) y=idealhermite_aux(nf,y);
        !          1495:   dx=denom(x); if (!gcmp1(dx)) y=gmul(y,dx);
        !          1496:   dy=denom(y); if (!gcmp1(dy)) x=gmul(x,dy);
        !          1497:   dx = mulii(dx,dy);
        !          1498:   z=kerint(concatsp(x,y)); lz=lg(z);
        !          1499:   for (i=1; i<lz; i++) setlg(z[i], N+1);
        !          1500:   z=gmul(x,z); z = hnfmod(z,detint(z));
        !          1501:   if (!gcmp1(dx)) z = gdiv(z,dx);
        !          1502:   return gerepileupto(av,z);
        !          1503: }
        !          1504:
        !          1505: static GEN
        !          1506: computet2twist(GEN nf, GEN vdir)
        !          1507: {
        !          1508:   long j, ru = lg(nf[6]);
        !          1509:   GEN p1,MC, mat = (GEN)nf[5];
        !          1510:
        !          1511:   if (!vdir) return (GEN)mat[3];
        !          1512:   MC=(GEN)mat[2]; p1=cgetg(ru,t_MAT);
        !          1513:   for (j=1; j<ru; j++)
        !          1514:   {
        !          1515:     GEN v = (GEN)vdir[j];
        !          1516:     if (gcmp0(v))
        !          1517:       p1[j]=MC[j];
        !          1518:     else if (typ(v) == t_INT)
        !          1519:       p1[j]=lmul2n((GEN)MC[j],itos(v)<<1);
        !          1520:     else
        !          1521:       p1[j]=lmul((GEN)MC[j],gpui(stoi(4),v,0));
        !          1522:   }
        !          1523:   return mulmat_real(p1,(GEN)mat[1]);
        !          1524: }
        !          1525:
        !          1526: GEN
        !          1527: ideallllredall(GEN nf, GEN x, GEN vdir, long prec, long precint)
        !          1528: {
        !          1529:   long tx,N,av,tetpil,i,j;
        !          1530:   GEN iax,ix,res,ax,p1,p2,y,alpha,beta,pol;
        !          1531:
        !          1532:   nf=checknf(nf);
        !          1533:   if (vdir)
        !          1534:   {
        !          1535:     if (gcmp0(vdir)) vdir = NULL;
        !          1536:     else if (typ(vdir)!=t_VEC || lg(vdir) != lg(nf[6])) err(idealer5);
        !          1537:   }
        !          1538:   pol = (GEN)nf[1]; N=lgef(pol)-3;
        !          1539:   tx = idealtyp(&x,&ax); ix=x; iax=ax;
        !          1540:   if (ax) res = cgetg(3,t_VEC);
        !          1541:   av = avma;
        !          1542:   if (tx == id_PRINCIPAL)
        !          1543:   {
        !          1544:     if (ax)
        !          1545:     {
        !          1546:       res = cgetg(3,t_VEC);
        !          1547:       ax = get_arch(nf,x,prec); av=avma;
        !          1548:     }
        !          1549:     x = idealhermite_aux(nf,x);
        !          1550:   }
        !          1551:   else if (tx == id_PRIME)
        !          1552:     x = prime_to_ideal_aux(nf,x);
        !          1553:   else if (lg(x) != N+1) /* id_MAT */
        !          1554:     x = idealhermite_aux(nf,x);
        !          1555:
        !          1556:   if (DEBUGLEVEL>=6) msgtimer("entering idealllred");
        !          1557:   p1=content(x); if (!gcmp1(p1)) x=gdiv(x,p1);
        !          1558:
        !          1559:   for (i=1; ; i++)
        !          1560:   {
        !          1561:     p1=computet2twist(nf,vdir);
        !          1562:     if (DEBUGLEVEL>=6) msgtimer("twisted T2");
        !          1563:     y = qf_base_change(p1,x,1);
        !          1564:     j = 1 + (gexpo(y)>>TWOPOTBITS_IN_LONG);
        !          1565:     if (j<0) j=0;
        !          1566:     p1 = lllgramintern(y,100,1,j+precint);
        !          1567:     if (p1) break;
        !          1568:
        !          1569:     if (i == MAXITERPOL) err(accurer,"ideallllredall");
        !          1570:     precint=(precint<<1)-2; prec=max(prec,precint);
        !          1571:     if (DEBUGLEVEL) err(warnprec,"ideallllredall",precint);
        !          1572:     nf=nfnewprec(nf,(j>>1)+precint);
        !          1573:   }
        !          1574:   y = gmul(x,(GEN)p1[1]);
        !          1575:   if (DEBUGLEVEL>=6) msgtimer("lllgram");
        !          1576:
        !          1577:   i=2; while (i<=N && gcmp0((GEN)y[i])) i++;
        !          1578:   if (i>N)
        !          1579:   {
        !          1580:     if (x!=ix) x = gerepileupto(av,x); else { avma=av; x = gcopy(x); }
        !          1581:     if (!ax) return x;
        !          1582:     if (ax==iax) ax = gcopy(ax);
        !          1583:     res[1]=(long)x; res[2]=(long)ax; return res;
        !          1584:   }
        !          1585:   alpha = gmul((GEN)nf[7], y);
        !          1586:   /* beta = norm(alpha) / alpha */
        !          1587:   beta = gmul(subres(pol,alpha), ginvmod(alpha,pol));
        !          1588:   beta = algtobasis_intern(nf,beta);
        !          1589:   if (DEBUGLEVEL>=6) msgtimer("alpha/beta");
        !          1590:
        !          1591:   p2 = cgetg(N+1,t_MAT);
        !          1592:   for (i=1; i<=N; i++)
        !          1593:     p2[i] = (long)element_muli(nf,beta,(GEN)x[i]);
        !          1594:   p1=content(p2); if (!gcmp1(p1)) p2=gdiv(p2,p1);
        !          1595:   if (DEBUGLEVEL>=6) msgtimer("new ideal");
        !          1596:   if (ax) y = gclone(gneg_i(get_arch(nf,y,prec)));
        !          1597:
        !          1598:   p1 = detint(p2); tetpil = avma;
        !          1599:   p2 = gerepile(av,tetpil,hnfmod(p2,p1));
        !          1600:   if (DEBUGLEVEL>=6) msgtimer("final hnf");
        !          1601:   if (!ax) return p2;
        !          1602:   res[1]=(long)p2; res[2]=ladd(ax,y);
        !          1603:   gunclone(y); return res;
        !          1604: }
        !          1605:
        !          1606: GEN
        !          1607: ideallllred(GEN nf, GEN ix, GEN vdir, long prec)
        !          1608: {
        !          1609:   return ideallllredall(nf,ix,vdir,prec,prec);
        !          1610: }
        !          1611:
        !          1612: GEN
        !          1613: minideal(GEN nf, GEN x, GEN vdir, long prec)
        !          1614: {
        !          1615:   long N,av=avma,tetpil,j,RU,tx;
        !          1616:   GEN p1,p2,p3,y;
        !          1617:
        !          1618:   if (!gcmp0(vdir) && typ(vdir)!=t_VEC) err(idealer5);
        !          1619:   nf=checknf(nf); N=lgef(nf[1])-3;
        !          1620:   tx = idealtyp(&x,&y); if (tx!=id_MAT) x = idealhermite_aux(nf,x);
        !          1621:   RU = N - itos(gmael(nf,2,2)); p1=(GEN)nf[5];
        !          1622:   if (gcmp0(vdir)) p1=(GEN)p1[3];
        !          1623:   else
        !          1624:   {
        !          1625:     p3=(GEN)p1[2]; p2=cgetg(RU+1,t_MAT);
        !          1626:     for (j=1; j<=RU; j++)
        !          1627:       p2[j] = lmul2n((GEN)p3[j], itos((GEN)vdir[j])<<1);
        !          1628:     p1=greal(gmul(p2,(GEN)p1[1]));
        !          1629:   }
        !          1630:   y = gmul(x,(GEN)lllgram(qf_base_change(p1,x,0),prec)[1]);
        !          1631:   tetpil = avma; return gerepile(av,tetpil,principalidele(nf,y,prec));
        !          1632: }
        !          1633: static GEN
        !          1634: appr_reduce(GEN s, GEN y, long N)
        !          1635: {
        !          1636:   GEN p1,u,z = cgetg(N+2,t_MAT);
        !          1637:   long i;
        !          1638:
        !          1639:   s=gmod(s,gcoeff(y,1,1)); y=gmul(y,lllint(y));
        !          1640:   for (i=1; i<=N; i++) z[i]=y[i]; z[N+1]=(long)s;
        !          1641:   u=(GEN)ker(z)[1]; p1 = denom(u);
        !          1642:   if (!gcmp1(p1)) u=gmul(u,p1);
        !          1643:   p1=(GEN)u[N+1]; setlg(u,N+1);
        !          1644:   for (i=1; i<=N; i++) u[i]=lround(gdiv((GEN)u[i],p1));
        !          1645:   return gadd(s, gmul(y,u));
        !          1646: }
        !          1647:
        !          1648: /* Given a fractional ideal x (if fl=0) or a prime ideal factorization
        !          1649:  * with possibly zero or negative exponents (if fl=1), gives a b such that
        !          1650:  * v_p(b)=v_p(x) for all prime ideals p dividing x (or in the factorization)
        !          1651:  * and v_p(b)>=0 for all other p, using the (standard) proof given in GTM 138.
        !          1652:  * Certainly not the most efficient, but sure.
        !          1653:  */
        !          1654: GEN
        !          1655: idealappr0(GEN nf, GEN x, long fl)
        !          1656: {
        !          1657:   long av=avma,tetpil,i,j,k,l,N,r,r2;
        !          1658:   GEN fact,fact2,list,ep,ep1,ep2,y,z,v,p1,p2,p3,p4,s,pr,alpha,beta,den;
        !          1659:
        !          1660:   if (DEBUGLEVEL>4)
        !          1661:   {
        !          1662:     fprintferr(" entree dans idealappr0() :\n");
        !          1663:     fprintferr(" x = "); outerr(x);
        !          1664:   }
        !          1665:   if (fl)
        !          1666:   {
        !          1667:     nf=checknf(nf); N=lgef(nf[1])-3;
        !          1668:     if (typ(x)!=t_MAT || lg(x)!=3)
        !          1669:       err(talker,"not a prime ideal factorization in idealappr0");
        !          1670:     fact=x; list=(GEN)fact[1]; ep=(GEN)fact[2]; r=lg(list);
        !          1671:     if (r==1) return gscalcol_i(gun,N);
        !          1672:     for (i=1; i<r; i++)
        !          1673:       if (signe(ep[i])<0)
        !          1674:       {
        !          1675:        ep1=cgetg(r,t_COL);
        !          1676:        for (i=1; i<r; i++)
        !          1677:           ep1[i] = (signe(ep[i])>=0)? zero: lnegi((GEN)ep[i]);
        !          1678:        fact[2]=(long)ep1; beta=idealappr0(nf,fact,1);
        !          1679:        fact2=idealfactor(nf,beta);
        !          1680:        p1=(GEN)fact2[1]; r2=lg(p1);
        !          1681:         ep2=(GEN)fact2[2]; l=r+r2-1;
        !          1682:         z=cgetg(l,t_VEC); for (i=1; i<r; i++) z[i]=list[i];
        !          1683:        ep1=cgetg(l,t_VEC);
        !          1684:        for (i=1; i<r; i++)
        !          1685:           ep1[i] = (signe(ep[i])<=0)? zero: licopy((GEN)ep[i]);
        !          1686:        j=r-1;
        !          1687:        for (i=1; i<r2; i++)
        !          1688:        {
        !          1689:          p3=(GEN)p1[i]; k=1;
        !          1690:          while (k<r &&
        !          1691:             (    !gegal((GEN)p3[1],gmael(list,k,1))
        !          1692:              || !element_val(nf,(GEN)p3[2],(GEN)list[k]) )) k++;
        !          1693:          if (k==r) { j++; z[j]=(long)p3; ep1[j]=ep2[i]; }
        !          1694:        }
        !          1695:         fact=cgetg(3,t_MAT);
        !          1696:         fact[1]=(long)z; setlg(z,j+1);
        !          1697:         fact[2]=(long)ep1; setlg(ep1,j+1);
        !          1698:        alpha=idealappr0(nf,fact,1); tetpil=avma;
        !          1699:        if (DEBUGLEVEL>2)
        !          1700:        {
        !          1701:          fprintferr(" alpha = "); outerr(alpha);
        !          1702:          fprintferr(" beta = "); outerr(beta);
        !          1703:        }
        !          1704:        return gerepile(av,tetpil,element_div(nf,alpha,beta));
        !          1705:       }
        !          1706:     y=idmat(N);
        !          1707:     for (i=1; i<r; i++)
        !          1708:     {
        !          1709:       pr=(GEN)list[i];
        !          1710:       if (signe(ep[i]))
        !          1711:       {
        !          1712:         p4=addsi(1,(GEN)ep[i]); p1=powgi((GEN)pr[1],p4);
        !          1713:        if (cmpis((GEN)pr[4],N))
        !          1714:        {
        !          1715:          p2=cgetg(3,t_MAT);
        !          1716:           p2[1]=(long)gscalcol_i(p1, N);
        !          1717:          p2[2]=(long)element_pow(nf,(GEN)pr[2],p4);
        !          1718:           y=idealmat_mul(nf,y,p2);
        !          1719:        }
        !          1720:        else y=gmul(p1,y);
        !          1721:       }
        !          1722:       else y=idealmulprime(nf,y,pr);
        !          1723:     }
        !          1724:   }
        !          1725:   else
        !          1726:   {
        !          1727:     den=denom(x); if (gcmp1(den)) den=NULL; else x=gmul(den,x);
        !          1728:     x=idealhermite_aux(nf,x); N=lgef(nf[1])-3;
        !          1729:     fact=idealfactor(nf,x);
        !          1730:     list=(GEN)fact[1]; ep=(GEN)fact[2]; r=lg(list);
        !          1731:     if (r==1) { avma=av; return gscalcol_i(gun,N); }
        !          1732:     if (den)
        !          1733:     {
        !          1734:       fact2=idealfactor(nf,den);
        !          1735:       p1=(GEN)fact2[1]; r2=lg(p1);
        !          1736:       l=r+r2-1;
        !          1737:       z=cgetg(l,t_COL);   for (i=1; i<r; i++) z[i]=list[i];
        !          1738:       ep1=cgetg(l,t_COL); for (i=1; i<r; i++) ep1[i]=ep[i];
        !          1739:       j=r-1;
        !          1740:       for (i=1; i<r2; i++)
        !          1741:       {
        !          1742:        p3=(GEN)p1[i]; k=1;
        !          1743:        while (k<r && !gegal((GEN)list[k],p3)) k++;
        !          1744:        if (k==r){ j++; z[j]=(long)p3; ep1[j]=zero; }
        !          1745:       }
        !          1746:       fact=cgetg(3,t_MAT);
        !          1747:       fact[1]=(long)z; setlg(z,j+1);
        !          1748:       fact[2]=(long)ep1; setlg(ep1,j+1);
        !          1749:       alpha=idealappr0(nf,fact,1);
        !          1750:       if (DEBUGLEVEL>2) { fprintferr(" alpha = "); outerr(alpha); }
        !          1751:       tetpil=avma; return gerepile(av,tetpil,gdiv(alpha,den));
        !          1752:     }
        !          1753:     y=x; for (i=1; i<r; i++) y=idealmulprime(nf,y,(GEN)list[i]);
        !          1754:   }
        !          1755:
        !          1756:   z=cgetg(r,t_VEC);
        !          1757:   for (i=1; i<r; i++)
        !          1758:   {
        !          1759:     pr=(GEN)list[i]; p4=addsi(1, (GEN)ep[i]); p1=powgi((GEN)pr[1],p4);
        !          1760:     if (cmpis((GEN)pr[4],N))
        !          1761:     {
        !          1762:       p2=cgetg(3,t_MAT);
        !          1763:       p2[1]=(long)gscalcol_i(p1,N);
        !          1764:       p2[2]=(long)element_pow(nf,(GEN)pr[5],p4);
        !          1765:       z[i]=ldiv(idealmat_mul(nf,y,p2),p1);
        !          1766:     }
        !          1767:     else z[i]=ldiv(y,p1);
        !          1768:   }
        !          1769:   v=idealaddmultoone(nf,z);
        !          1770:   s=cgetg(N+1,t_COL); for (i=1; i<=N; i++) s[i]=zero;
        !          1771:   for (i=1; i<r; i++)
        !          1772:   {
        !          1773:     pr=(GEN)list[i];
        !          1774:     if (signe(ep[i]))
        !          1775:       s=gadd(s,element_mul(nf,(GEN)v[i],element_pow(nf,(GEN)pr[2],(GEN)ep[i])));
        !          1776:     else s=gadd(s,(GEN)v[i]);
        !          1777:   }
        !          1778:   p3 = appr_reduce(s,y,N);
        !          1779:   if (DEBUGLEVEL>2)
        !          1780:     { fprintferr(" sortie de idealappr0 p3 = "); outerr(p3); }
        !          1781:   return gerepileupto(av,p3);
        !          1782: }
        !          1783:
        !          1784: /* Given a prime ideal factorization x with possibly zero or negative exponents,
        !          1785:  * and a vector y of elements of nf, gives a b such that
        !          1786:  * v_p(b-y_p)>=v_p(x) for all prime ideals p in the ideal factorization
        !          1787:  * and v_p(b)>=0 for all other p, using the (standard) proof given in GTM 138.
        !          1788:  * Certainly not the most efficient, but sure.
        !          1789:  */
        !          1790: GEN
        !          1791: idealchinese(GEN nf, GEN x, GEN y)
        !          1792: {
        !          1793:   long ty=typ(y),av=avma,i,j,k,l,N,r,r2;
        !          1794:   GEN fact,fact2,list,ep,ep1,ep2,z,t,v,p1,p2,p3,p4,s,pr,den;
        !          1795:
        !          1796:   if (DEBUGLEVEL>4)
        !          1797:   {
        !          1798:     fprintferr(" entree dans idealchinese() :\n");
        !          1799:     fprintferr(" x = "); outerr(x);
        !          1800:     fprintferr(" y = "); outerr(y);
        !          1801:   }
        !          1802:   nf=checknf(nf); N=lgef(nf[1])-3;
        !          1803:   if (typ(x)!=t_MAT ||(lg(x)!=3))
        !          1804:     err(talker,"not a prime ideal factorization in idealchinese");
        !          1805:   fact=x; list=(GEN)fact[1]; ep=(GEN)fact[2]; r=lg(list);
        !          1806:   if (!is_vec_t(ty) || lg(y)!=r)
        !          1807:     err(talker,"not a suitable vector of elements in idealchinese");
        !          1808:   if (r==1) return gscalcol_i(gun,N);
        !          1809:
        !          1810:   den=denom(y);
        !          1811:   if (!gcmp1(den))
        !          1812:   {
        !          1813:     fact2=idealfactor(nf,den);
        !          1814:     p1=(GEN)fact2[1]; r2=lg(p1);
        !          1815:     ep2=(GEN)fact2[2]; l=r+r2-1;
        !          1816:     z=cgetg(l,t_VEC); for (i=1; i<r; i++) z[i]=list[i];
        !          1817:     ep1=cgetg(l,t_VEC); for (i=1; i<r; i++) ep1[i]=ep[i];
        !          1818:     j=r-1;
        !          1819:     for (i=1; i<r2; i++)
        !          1820:     {
        !          1821:       p3=(GEN)p1[i]; k=1;
        !          1822:       while (k<r && !gegal((GEN)list[k],p3)) k++;
        !          1823:       if (k==r) { j++; z[j]=(long)p3; ep1[j]=ep2[i]; }
        !          1824:       else ep1[k]=ladd((GEN)ep1[k],(GEN)ep2[i]);
        !          1825:     }
        !          1826:     r=j+1; setlg(z,r); setlg(ep1,r); list=z; ep=ep1;
        !          1827:   }
        !          1828:   for (i=1; i<r; i++)
        !          1829:     if (signe(ep[i])<0) ep[i] = zero;
        !          1830:   t=idmat(N);
        !          1831:   for (i=1; i<r; i++)
        !          1832:   {
        !          1833:     pr=(GEN)list[i]; p4=(GEN)ep[i];
        !          1834:     if (signe(p4))
        !          1835:     {
        !          1836:       if (cmpis((GEN)pr[4],N))
        !          1837:       {
        !          1838:        p2=cgetg(3,t_MAT);
        !          1839:         p2[1]=(long)gscalcol_i(gpui((GEN)pr[1],p4,0), N);
        !          1840:        p2[2]=(long)element_pow(nf,(GEN)pr[2],p4);
        !          1841:         t=idealmat_mul(nf,t,p2);
        !          1842:       }
        !          1843:       else t=gmul(gpui((GEN)pr[1],p4,0),t);
        !          1844:     }
        !          1845:   }
        !          1846:   z=cgetg(r,t_VEC);
        !          1847:   for (i=1; i<r; i++)
        !          1848:   {
        !          1849:     pr=(GEN)list[i]; p4=(GEN)ep[i];
        !          1850:     if (cmpis((GEN)pr[4],N))
        !          1851:     {
        !          1852:       p2=cgetg(3,t_MAT); p1=gpui((GEN)pr[1],p4,0);
        !          1853:       p2[1]=(long)gscalcol_i(p1,N);
        !          1854:       p2[2]=(long)element_pow(nf,(GEN)pr[5],p4);
        !          1855:       z[i]=ldiv(idealmat_mul(nf,t,p2),p1);
        !          1856:     }
        !          1857:     else z[i]=ldiv(t,gpui((GEN)pr[1],p4,0));
        !          1858:   }
        !          1859:   v=idealaddmultoone(nf,z);
        !          1860:   s=cgetg(N+1,t_COL); for (i=1; i<=N; i++) s[i]=zero;
        !          1861:   for (i=1; i<r; i++)
        !          1862:     s = gadd(s,element_mul(nf,(GEN)v[i],(GEN)y[i]));
        !          1863:
        !          1864:   p3 = appr_reduce(s,t,N);
        !          1865:   if (DEBUGLEVEL>2)
        !          1866:     { fprintferr(" sortie de idealchinese() : p3 = "); outerr(p3); }
        !          1867:   return gerepileupto(av,p3);
        !          1868: }
        !          1869:
        !          1870: GEN
        !          1871: idealappr(GEN nf, GEN x) { return idealappr0(nf,x,0); }
        !          1872:
        !          1873: GEN
        !          1874: idealapprfact(GEN nf, GEN x) { return idealappr0(nf,x,1); }
        !          1875:
        !          1876: /* Given an integral ideal x and a in x, gives a b such that
        !          1877:  * x=aZ_K+bZ_K using a different algorithm than ideal_two_elt
        !          1878:  */
        !          1879: GEN
        !          1880: ideal_two_elt2(GEN nf, GEN x, GEN a)
        !          1881: {
        !          1882:   long ta=typ(a), av=avma,tetpil,i,r;
        !          1883:   GEN con,ep,b,list,fact;
        !          1884:
        !          1885:   nf = checknf(nf);
        !          1886:   if (!is_extscalar_t(ta) && typ(a)!=t_COL)
        !          1887:     err(typeer,"ideal_two_elt2");
        !          1888:   x = idealhermite_aux(nf,x);
        !          1889:   if (gcmp0(x))
        !          1890:   {
        !          1891:     if (!gcmp0(a)) err(talker,"element not in ideal in ideal_two_elt2");
        !          1892:     avma=av; return gcopy(a);
        !          1893:   }
        !          1894:   con = content(x);
        !          1895:   if (gcmp1(con)) con = NULL; else { x = gdiv(x,con); a = gdiv(a,con); }
        !          1896:   a = principalideal(nf,a);
        !          1897:   if (!gcmp1(denom(gauss(x,a))))
        !          1898:     err(talker,"element does not belong to ideal in ideal_two_elt2");
        !          1899:
        !          1900:   fact=idealfactor(nf,a); list=(GEN)fact[1];
        !          1901:   r=lg(list); ep = (GEN)fact[2];
        !          1902:   for (i=1; i<r; i++) ep[i]=lstoi(idealval(nf,x,(GEN)list[i]));
        !          1903:   b = centermod(idealappr0(nf,fact,1), gcoeff(x,1,1));
        !          1904:   tetpil=avma; b = con? gmul(b,con): gcopy(b);
        !          1905:   return gerepile(av,tetpil,b);
        !          1906: }
        !          1907:
        !          1908: /* Given 2 integral ideals x and y in a number field nf gives a beta
        !          1909:  * belonging to nf such that beta.x is an integral ideal coprime to y
        !          1910:  */
        !          1911: GEN
        !          1912: idealcoprime(GEN nf, GEN x, GEN y)
        !          1913: {
        !          1914:   long av=avma,tetpil,i,r;
        !          1915:   GEN fact,list,p2,ep;
        !          1916:
        !          1917:   if (DEBUGLEVEL>4)
        !          1918:   {
        !          1919:     fprintferr(" entree dans idealcoprime() :\n");
        !          1920:     fprintferr(" x = "); outerr(x);
        !          1921:     fprintferr(" y = "); outerr(y);
        !          1922:   }
        !          1923:   fact=idealfactor(nf,y); list=(GEN)fact[1];
        !          1924:   r=lg(list); ep = (GEN)fact[2];
        !          1925:   for (i=1; i<r; i++) ep[i]=lstoi(-idealval(nf,x,(GEN)list[i]));
        !          1926:   tetpil=avma; p2=idealappr0(nf,fact,1);
        !          1927:   if (DEBUGLEVEL>4)
        !          1928:     { fprintferr(" sortie de idealcoprime() : p2 = "); outerr(p2); }
        !          1929:   return gerepile(av,tetpil,p2);
        !          1930: }
        !          1931:
        !          1932: /* returns the first index i<=n such that x=v[i] if it exits, 0 otherwise */
        !          1933: long
        !          1934: isinvector(GEN v, GEN x, long n)
        !          1935: {
        !          1936:   long i;
        !          1937:
        !          1938:   for (i=1; i<=n; i++)
        !          1939:     if (gegal((GEN)v[i],x)) return i;
        !          1940:   return 0;
        !          1941: }
        !          1942:
        !          1943: /* Given an integral ideal x and three algebraic integers a, b and c in a
        !          1944:  * number field nf gives a beta belonging to nf such that beta.x^(-1) is an
        !          1945:  * integral ideal coprime to abc.Z_k
        !          1946:  */
        !          1947: static GEN
        !          1948: idealcoprimeinvabc(GEN nf, GEN x, GEN a, GEN b, GEN c)
        !          1949: {
        !          1950:   long av=avma,tetpil,i,j,r,ra,rb,rc;
        !          1951:   GEN facta,factb,factc,fact,factall,p1,p2,ep;
        !          1952:
        !          1953:   if (DEBUGLEVEL>4)
        !          1954:   {
        !          1955:     fprintferr(" entree dans idealcoprimeinvabc() :\n");
        !          1956:     fprintferr(" x = "); outerr(x); fprintferr(" a = "); outerr(a);
        !          1957:     fprintferr(" b = "); outerr(b); fprintferr(" c = "); outerr(c);
        !          1958:     flusherr();
        !          1959:   }
        !          1960:   facta=(GEN)idealfactor(nf,a)[1]; factb=(GEN)idealfactor(nf,b)[1];
        !          1961:   factc=(GEN)idealfactor(nf,c)[1]; ra=lg(facta); rb=lg(factb); rc=lg(factc);
        !          1962:   factall=cgetg(ra+rb+rc-2,t_COL);
        !          1963:   for (i=1; i<ra; i++) factall[i]=facta[i]; j=ra-1;
        !          1964:   for (i=1; i<rb; i++)
        !          1965:     if (!isinvector(factall,(GEN)factb[i],j)) factall[++j]=factb[i];
        !          1966:   for (i=1; i<rc; i++)
        !          1967:     if (!isinvector(factall,(GEN)factc[i],j)) factall[++j]=factc[i];
        !          1968:   r=j+1; fact=cgetg(3,t_MAT); p1=cgetg(r,t_COL); ep=cgetg(r,t_COL);
        !          1969:   for (i=1; i<r; i++) p1[i]=factall[i];
        !          1970:   for (i=1; i<r; i++) ep[i]=lstoi(idealval(nf,x,(GEN)p1[i]));
        !          1971:   fact[1]=(long)p1; fact[2]=(long)ep; tetpil=avma; p2=idealappr0(nf,fact,1);
        !          1972:   if (DEBUGLEVEL>2)
        !          1973:     { fprintferr(" sortie de idealcoprimeinvabc() : p2 = "); outerr(p2); }
        !          1974:   return gerepile(av,tetpil,p2);
        !          1975: }
        !          1976:
        !          1977: /* Solve the equation ((b+aX).Z_k/((a,b).J),M)=Z_k. */
        !          1978: static GEN
        !          1979: findX(GEN nf, GEN a, GEN b, GEN J, GEN M)
        !          1980: {
        !          1981:   long N,i,k,r,v;
        !          1982:   GEN p1,p2,abJ,fact,list,ve,ep,int0,int1,int2,pr;
        !          1983:
        !          1984:   if (DEBUGLEVEL>4)
        !          1985:   {
        !          1986:     fprintferr(" entree dans findX() :\n");
        !          1987:     fprintferr(" a = "); outerr(a); fprintferr(" b = "); outerr(b);
        !          1988:     fprintferr(" J = "); outerr(J); fprintferr(" M = "); outerr(M);
        !          1989:   }
        !          1990:   N=lgef(nf[1])-3;
        !          1991:   p1=cgetg(3,t_MAT); p1[1]=(long)a; p1[2]=(long)b;
        !          1992:   if (N==2) p1=idealmul(nf,p1,idmat(2));
        !          1993:   abJ=idealmul(nf,p1,J);
        !          1994:   fact=idealfactor(nf,M); list=(GEN)fact[1]; r=lg(list);
        !          1995:   ve=cgetg(r,t_VEC); ep=cgetg(r,t_VEC);
        !          1996:   int0=cgetg(N+1,t_COL); int1=cgetg(N+1,t_COL); int2=cgetg(N+1,t_COL);
        !          1997:   for (i=2; i<=N; i++) int0[i]=int1[i]=int2[i]=zero;
        !          1998:   int0[1]=zero; int1[1]=un; int2[1]=deux;
        !          1999:   for (i=1; i<r; i++)
        !          2000:   {
        !          2001:     pr=(GEN)list[i]; v=element_val(nf,a,pr);
        !          2002:     if (v)
        !          2003:     {
        !          2004:       ep[i]=un;
        !          2005:       ve[i] = (element_val(nf,b,pr)<=v)? (long)int0: (long)int1;
        !          2006:     }
        !          2007:     else
        !          2008:     {
        !          2009:       v=idealval(nf,abJ,pr);
        !          2010:       p1=element_div(nf,idealaddtoone_i(nf,a,pr),a);
        !          2011:       ep[i]=lstoi(v+1); k=1;
        !          2012:       while (k<=v)
        !          2013:       {
        !          2014:        p1=element_mul(nf,p1,gsub(int2,element_mul(nf,a,p1)));
        !          2015:        k<<=1;
        !          2016:       }
        !          2017:       p1=element_mul(nf,p1,gsub(element_pow(nf,(GEN)pr[2],stoi(v)),b));
        !          2018:       ve[i]=lmod(p1,gpuigs((GEN)pr[1],v+1));
        !          2019:     }
        !          2020:   }
        !          2021:   fact[2]=(long)ep; p2=idealchinese(nf,fact,ve);
        !          2022:   if (DEBUGLEVEL>2) { fprintferr(" sortie de findX() : p2 = "); outerr(p2); }
        !          2023:   return p2;
        !          2024: }
        !          2025:
        !          2026: /* A usage interne. Given a, b, c, d in nf, gives an algebraic integer y in
        !          2027:  * nf such that [c,d]-y.[a,b] is "small"
        !          2028:  */
        !          2029: static GEN
        !          2030: nfreducemat(GEN nf, GEN a, GEN b, GEN c, GEN d)
        !          2031: {
        !          2032:   long av=avma,tetpil,i,i1,i2,j,j1,j2,k,N;
        !          2033:   GEN p1,p2,X,M,y,mult,s;
        !          2034:
        !          2035:   mult=(GEN)nf[9]; N=lgef(nf[1])-3; X=cgetg(N+1,t_COL);
        !          2036:   for (j=1; j<=N; j++)
        !          2037:   {
        !          2038:     s=gzero;
        !          2039:     for (i=1; i<=N; i++) for (k=1; k<=N; k++)
        !          2040:     {
        !          2041:       p1=gcoeff(mult,k,j+(i-1)*N);
        !          2042:       if (!gcmp0(p1))
        !          2043:        s=gadd(s,gmul(p1,gadd(gmul((GEN)a[i],(GEN)c[k]),
        !          2044:                              gmul((GEN)b[i],(GEN)d[k]))));
        !          2045:     }
        !          2046:     X[j]=(long)s;
        !          2047:   }
        !          2048:   M=cgetg(N+1,t_MAT);
        !          2049:   for (j2=1; j2<=N; j2++)
        !          2050:   {
        !          2051:     p1=cgetg(N+1,t_COL); M[j2]=(long)p1;
        !          2052:     for (j1=1; j1<=N; j1++)
        !          2053:     {
        !          2054:       s=gzero;
        !          2055:       for (i1=1; i1<=N; i1++)
        !          2056:        for (i2=1; i2<=N; i2++)
        !          2057:         for (k=1; k<=N; k++)
        !          2058:        {
        !          2059:          p2=gmul(gcoeff(mult,k,j1+(i1-1)*N),gcoeff(mult,k,j2+(i2-1)*N));
        !          2060:          if (!gcmp0(p2))
        !          2061:             s=gadd(s,gmul(p2,gadd(gmul((GEN)a[i1],(GEN)a[i2]),
        !          2062:                                   gmul((GEN)b[i1],(GEN)b[i2]))));
        !          2063:        }
        !          2064:       p1[j1]=(long)s;
        !          2065:     }
        !          2066:   }
        !          2067:   y=gauss(M,X); tetpil=avma;
        !          2068:   return gerepile(av,tetpil,ground(y));
        !          2069: }
        !          2070:
        !          2071: /* Given 3 algebraic integers a,b,c in a number field nf given by their
        !          2072:  * components on the integral basis, gives a three-component vector [d,e,U]
        !          2073:  * whose first two components are algebraic integers d,e and the third a
        !          2074:  * unimodular 3x3-matrix U such that [a,b,c]*U=[0,d,e]
        !          2075:  */
        !          2076: GEN
        !          2077: threetotwo2(GEN nf, GEN a, GEN b, GEN c)
        !          2078: {
        !          2079:   long av=avma,tetpil,i,N;
        !          2080:   GEN y,p1,p2,p3,M,X,Y,J,e,b1,c1,u,v,U,int0,Z,pk;
        !          2081:
        !          2082:   if (DEBUGLEVEL>2)
        !          2083:   {
        !          2084:     fprintferr(" On entre dans threetotwo2() : \n");
        !          2085:     fprintferr(" a = "); outerr(a);
        !          2086:     fprintferr(" b = "); outerr(b);
        !          2087:     fprintferr(" c = "); outerr(c);
        !          2088:   }
        !          2089:   if (gcmp0(a))
        !          2090:   {
        !          2091:     y=cgetg(4,t_VEC); y[1]=lcopy(b); y[2]=lcopy(c); y[3]=(long)idmat(3);
        !          2092:     return y;
        !          2093:   }
        !          2094:   if (gcmp0(b))
        !          2095:   {
        !          2096:     y=cgetg(4,t_VEC); y[1]=lcopy(a); y[2]=lcopy(c);
        !          2097:     e = idmat(3); i=e[1]; e[1]=e[2]; e[2]=i;
        !          2098:     y[3]=(long)e; return y;
        !          2099:   }
        !          2100:   if (gcmp0(c))
        !          2101:   {
        !          2102:     y=cgetg(4,t_VEC); y[1]=lcopy(a); y[2]=lcopy(b);
        !          2103:     e = idmat(3); i=e[1]; e[1]=e[3]; e[3]=e[2]; e[2]=i;
        !          2104:     y[3]=(long)e; return y;
        !          2105:   }
        !          2106:
        !          2107:   N=lgef(nf[1])-3;
        !          2108:   p1=cgetg(4,t_MAT); p1[1]=(long)a; p1[2]=(long)b;
        !          2109:   p1[3]=(long)c; p1=idealhermite_aux(nf,p1);
        !          2110:   if (DEBUGLEVEL>2)
        !          2111:     { fprintferr(" ideal a.Z_k+b.Z_k+c.Z_k = "); outerr(p1); }
        !          2112:   J=idealdiv(nf,e=idealcoprimeinvabc(nf,p1,a,b,c),p1);
        !          2113:   if (DEBUGLEVEL>2)
        !          2114:     { fprintferr(" ideal J = "); outerr(J); fprintferr(" e = "); outerr(e); }
        !          2115:   p1=cgetg(3,t_MAT); p1[1]=(long)a; p1[2]=(long)b; M=idealmul(nf,p1,J);
        !          2116:   if (DEBUGLEVEL>2)
        !          2117:     { fprintferr(" ideal M=(a.Z_k+b.Z_k).J = "); outerr(M); }
        !          2118:   X=findX(nf,a,b,J,M);
        !          2119:   if (DEBUGLEVEL>2){ fprintferr(" X = "); outerr(X); }
        !          2120:   p1=gadd(b,element_mul(nf,a,X));
        !          2121:   p2=cgetg(3,t_MAT); p2[1]=(long)element_mul(nf,a,p1);
        !          2122:   p2[2]=(long)element_mul(nf,c,p1);
        !          2123:   if (N==2) p2=idealhermite_aux(nf,p2);
        !          2124:   p3=cgetg(3,t_MAT); p3[1]=(long)a; p3[2]=(long)b;
        !          2125:   p3=idealhermite_aux(nf,p3);
        !          2126:   if (DEBUGLEVEL>2)
        !          2127:     { fprintferr(" ideal a.Z_k+b.Z_k = "); outerr(p3); }
        !          2128:   Y=findX(nf,a,c,J,idealdiv(nf,p2,p3));
        !          2129:   if (DEBUGLEVEL>2) { fprintferr(" Y = "); outerr(Y); }
        !          2130:   b1=element_div(nf,p1,e);
        !          2131:   if (DEBUGLEVEL>2) { fprintferr(" b1 = "); outerr(b1); }
        !          2132:   p2=gadd(c,element_mul(nf,a,Y));
        !          2133:   c1=element_div(nf,p2,e);
        !          2134:   if (DEBUGLEVEL>2) { fprintferr(" c1 = "); outerr(c1); }
        !          2135:   p1=idealhermite_aux(nf,b1);
        !          2136:   p2=idealhermite_aux(nf,c1);
        !          2137:   p3=idealaddtoone(nf,p1,p2);
        !          2138:   u=element_div(nf,(GEN)p3[1],b1); v=element_div(nf,(GEN)p3[2],c1);
        !          2139:   if (DEBUGLEVEL>2)
        !          2140:     { fprintferr(" u = "); outerr(u); fprintferr(" v = "); outerr(v); }
        !          2141:   U=cgetg(4,t_MAT);
        !          2142:   p1=cgetg(4,t_COL); p2=cgetg(4,t_COL); p3=cgetg(4,t_COL);
        !          2143:   U[1]=(long)p1; U[2]=(long)p2; U[3]=(long)p3;
        !          2144:   p1[1]=lsub(element_mul(nf,X,c1),element_mul(nf,Y,b1));
        !          2145:   p1[2]=(long)c1; p1[3]=lneg(b1);
        !          2146:   int0 = zerocol(N);
        !          2147:   p2[1]=(long)gscalcol_i(gun,N);
        !          2148:   p2[2]=p2[3]=(long)int0;
        !          2149:   Z=gadd(element_mul(nf,X,u),element_mul(nf,Y,v));
        !          2150:   pk=nfreducemat(nf,c1,(GEN)p1[3],u,v);
        !          2151:   p3[1]=(long)int0; p3[2]=lsub(u,element_mul(nf,pk,c1));
        !          2152:   p3[3]=(long)gadd(v,element_mul(nf,pk,b1));
        !          2153:   e=gadd(e,element_mul(nf,a,gsub(element_mul(nf,pk,(GEN)p1[1]),Z)));
        !          2154:   tetpil=avma;
        !          2155:   y=cgetg(4,t_VEC); y[1]=lcopy(a); y[2]=lcopy(e); y[3]=lcopy(U);
        !          2156:   if (DEBUGLEVEL>2)
        !          2157:     { fprintferr(" sortie de threetotwo2() : y = "); outerr(y); }
        !          2158:   return gerepile(av,tetpil,y);
        !          2159: }
        !          2160:
        !          2161: /* Given 3 algebraic integers a,b,c in a number field nf given by their
        !          2162:  * components on the integral basis, gives a three-component vector [d,e,U]
        !          2163:  * whose first two components are algebraic integers d,e and the third a
        !          2164:  * unimodular 3x3-matrix U such that [a,b,c]*U=[0,d,e] Naive method which may
        !          2165:  * not work, but fast and small coefficients.
        !          2166:  */
        !          2167: GEN
        !          2168: threetotwo(GEN nf, GEN a, GEN b, GEN c)
        !          2169: {
        !          2170:   long av=avma,tetpil,i,N;
        !          2171:   GEN pol,p1,p2,p3,p4,y,id,hu,h,V,U,r,vd,q1,q1a,q2,q2a,na,nb,nc,nr;
        !          2172:
        !          2173:   nf=checknf(nf); pol=(GEN)nf[1]; N=lgef(pol)-3; id=idmat(N);
        !          2174:   na=gnorml2(a); nb=gnorml2(b); nc=gnorml2(c);
        !          2175:   U=gmul(idmat(3),gmodulsg(1,pol));
        !          2176:   if (gcmp(nc,nb)<0)
        !          2177:   {
        !          2178:     p1=c; c=b; b=p1; p1=nc; nc=nb; nb=p1;
        !          2179:     p1=(GEN)U[3]; U[3]=U[2]; U[2]=(long)p1;
        !          2180:   }
        !          2181:   if (gcmp(nc,na)<0)
        !          2182:   {
        !          2183:     p1=a; a=c; c=p1; p1=na; na=nc; nc=p1;
        !          2184:     p1=(GEN)U[1]; U[1]=U[3]; U[3]=(long)p1;
        !          2185:   }
        !          2186:   while (!gcmp0(gmin(na,nb)))
        !          2187:   {
        !          2188:     p1=cgetg(2*N+1,t_MAT);
        !          2189:     for (i=1; i<=N; i++)
        !          2190:     {
        !          2191:       p1[i]=(long)element_mul(nf,a,(GEN)id[i]);
        !          2192:       p1[i+N]=(long)element_mul(nf,b,(GEN)id[i]);
        !          2193:     }
        !          2194:     hu=hnfall(p1); h=(GEN)hu[1]; V=(GEN)hu[2];
        !          2195:     p2=(GEN)ker(concatsp(h,c))[1]; p3=(GEN)p2[N+1];
        !          2196:     p4=cgetg(N+1,t_COL);
        !          2197:     for (i=1; i<=N; i++) p4[i]=(long)ground(gdiv((GEN)p2[i],p3));
        !          2198:     r=gadd(c,gmul(h,p4));
        !          2199:     vd=cgetg(N+1,t_MAT); for (i=1; i<=N; i++) vd[i]=V[N+i];
        !          2200:     p2=gmul(vd,p4);
        !          2201:     q1=cgetg(N+1,t_COL); q2=cgetg(N+1,t_COL);
        !          2202:     for (i=1; i<=N; i++) { q1[i]=p2[i]; q2[i]=p2[i+N]; }
        !          2203:     q1a=basistoalg(nf,q1); q2a=basistoalg(nf,q2);
        !          2204:     U[3]=(long)gadd((GEN)U[3],gadd(gmul(q1a,(GEN)U[1]),gmul(q2a,(GEN)U[2])));
        !          2205:     nr=gnorml2(r);
        !          2206:     if (gcmp(nr,gmax(na,nb))>=0) err(talker,"threetotwo does not work");
        !          2207:     if (gcmp(na,nb)>=0)
        !          2208:     {
        !          2209:       c=a; nc=na; a=r; na=nr; p1=(GEN)U[1]; U[1]=U[3]; U[3]=(long)p1;
        !          2210:     }
        !          2211:     else
        !          2212:     {
        !          2213:       c=b; nc=nb; b=r; nb=nr; p1=(GEN)U[2]; U[2]=U[3]; U[3]=(long)p1;
        !          2214:     }
        !          2215:   }
        !          2216:   if (!gcmp0(na))
        !          2217:   {
        !          2218:     p1=a; a=b; b=p1; p1=(GEN)U[1]; U[1]=U[2]; U[2]=(long)p1;
        !          2219:   }
        !          2220:   tetpil=avma; y=cgetg(4,t_VEC); y[1]=lcopy(b); y[2]=lcopy(c);
        !          2221:   y[3]=(long)algtobasis(nf,U); return gerepile(av,tetpil,y);
        !          2222: }
        !          2223:
        !          2224: /* Given 2 algebraic integers a,b in a number field nf given by their
        !          2225:  * components on the integral basis, gives a three-components vector [d,e,U]
        !          2226:  * whose first two component are algebraic integers d,e and the third a
        !          2227:  * unimodular 2x2-matrix U such that [a,b]*U=[d,e], with d and e hopefully
        !          2228:  * smaller than a and b.
        !          2229:  */
        !          2230: GEN
        !          2231: twototwo(GEN nf, GEN a, GEN b)
        !          2232: {
        !          2233:   long av=avma,tetpil;
        !          2234:   GEN pol,p1,y,U,r,qr,qa,na,nb,nr;
        !          2235:
        !          2236:   nf=checknf(nf);
        !          2237:   pol=(GEN)nf[1];
        !          2238:   na=gnorml2(a); nb=gnorml2(b);
        !          2239:   U=gmul(idmat(2),gmodulsg(1,pol));
        !          2240:   if (gcmp(na,nb)>0)
        !          2241:   {
        !          2242:     p1=a; a=b; b=p1; p1=na; na=nb; nb=p1;
        !          2243:     p1=(GEN)U[2]; U[2]=U[1]; U[1]=(long)p1;
        !          2244:   }
        !          2245:
        !          2246:   while (!gcmp0(na))
        !          2247:   {
        !          2248:     qr=nfdivres(nf,b,a); r=(GEN)qr[2]; nr=gnorml2(r);
        !          2249:     if (gcmp(nr,na)<0)
        !          2250:     {
        !          2251:       b=a; a=r; nb=na; na=nr; qa=basistoalg(nf,(GEN)qr[1]);
        !          2252:       p1=gsub((GEN)U[2],gmul(qa,(GEN)U[1])); U[2]=U[1]; U[1]=(long)p1;
        !          2253:     }
        !          2254:     else
        !          2255:     {
        !          2256:       if (gcmp(nr,nb)<0)
        !          2257:       {
        !          2258:        qa=basistoalg(nf,(GEN)qr[1]);
        !          2259:        U[2]=lsub((GEN)U[2],gmul(qa,(GEN)U[1]));
        !          2260:       }
        !          2261:       break;
        !          2262:     }
        !          2263:   }
        !          2264:   tetpil=avma; y=cgetg(4,t_VEC); y[1]=lcopy(a); y[2]=lcopy(b);
        !          2265:   y[3]=(long)algtobasis(nf,U); return gerepile(av,tetpil,y);
        !          2266: }
        !          2267:
        !          2268: GEN
        !          2269: elt_mul_get_table(GEN nf, GEN x)
        !          2270: {
        !          2271:   long i,lx = lg(x);
        !          2272:   GEN mul=cgetg(lx,t_MAT);
        !          2273:
        !          2274:   /* assume w_1 = 1 */
        !          2275:   mul[1]=(long)x;
        !          2276:   for (i=2; i<lx; i++) mul[i] = (long)element_mulid(nf,x,i);
        !          2277:   return mul;
        !          2278: }
        !          2279:
        !          2280: GEN
        !          2281: elt_mul_table(GEN mul, GEN z)
        !          2282: {
        !          2283:   long av = avma, i, lx = lg(mul);
        !          2284:   GEN p1 = gmul((GEN)z[1], (GEN)mul[1]);
        !          2285:
        !          2286:   for (i=2; i<lx; i++)
        !          2287:     if (!gcmp0((GEN)z[i])) p1 = gadd(p1, gmul((GEN)z[i], (GEN)mul[i]));
        !          2288:   return gerepileupto(av, p1);
        !          2289: }
        !          2290:
        !          2291: GEN
        !          2292: element_mulvec(GEN nf, GEN x, GEN v)
        !          2293: {
        !          2294:   long lv=lg(v),i;
        !          2295:   GEN mul = elt_mul_get_table(nf,x), y=cgetg(lv,t_COL);
        !          2296:
        !          2297:   for (i=1; i<lv; i++)
        !          2298:     y[i] = (long)elt_mul_table(mul,(GEN)v[i]);
        !          2299:   return y;
        !          2300: }
        !          2301:
        !          2302: static GEN
        !          2303: element_mulvecrow(GEN nf, GEN x, GEN m, long i, long lim)
        !          2304: {
        !          2305:   long lv,j;
        !          2306:   GEN y, mul = elt_mul_get_table(nf,x);
        !          2307:
        !          2308:   lv=min(lg(m),lim+1); y=cgetg(lv,t_VEC);
        !          2309:   for (j=1; j<lv; j++)
        !          2310:     y[j] = (long)elt_mul_table(mul,gcoeff(m,i,j));
        !          2311:   return y;
        !          2312: }
        !          2313:
        !          2314: /* Given an element x and an ideal in matrix form (not necessarily HNF),
        !          2315:  * gives an r such that x-r is in ideal and r is small. No checks
        !          2316:  */
        !          2317: GEN
        !          2318: element_reduce(GEN nf, GEN x, GEN ideal)
        !          2319: {
        !          2320:   long tx=typ(x),av=avma,tetpil,N,i;
        !          2321:   GEN p1,u;
        !          2322:
        !          2323:   if (is_extscalar_t(tx))
        !          2324:     x = algtobasis_intern(checknf(nf), x);
        !          2325:   N = lg(x); p1=cgetg(N+1,t_MAT);
        !          2326:   for (i=1; i<N; i++) p1[i]=ideal[i];
        !          2327:   p1[N]=(long)x; u=(GEN)ker(p1)[1];
        !          2328:   p1=(GEN)u[N]; setlg(u,N);
        !          2329:   for (i=1; i<N; i++) u[i]=lround(gdiv((GEN)u[i],p1));
        !          2330:   u=gmul(ideal,u); tetpil=avma;
        !          2331:   return gerepile(av,tetpil,gadd(u,x));
        !          2332: }
        !          2333:
        !          2334: /* A torsion-free module M over Z_K will be given by a row vector [A,I] with
        !          2335:  * two components. I=[\a_1,...,\a_k] is a row vector of k fractional ideals
        !          2336:  * given in HNF. A is an nxk matrix (same k and n the rank of the module)
        !          2337:  * such that if A_j is the j-th column of A then M=\a_1A_1+...\a_kA_k. We say
        !          2338:  * that [A,I] is a pseudo-basis if k=n
        !          2339:  */
        !          2340:
        !          2341: /* Given a torsion-free module x as above outputs a pseudo-basis for x in
        !          2342:  * Hermite Normal Form
        !          2343:  */
        !          2344: GEN
        !          2345: nfhermite(GEN nf, GEN x)
        !          2346: {
        !          2347:   long av=avma,tetpil,i,j,def,k,m;
        !          2348:   GEN p1,p2,y,A,I,J;
        !          2349:
        !          2350:   nf=checknf(nf);
        !          2351:   if (typ(x)!=t_VEC || lg(x)!=3) err(talker,"not a module in nfhermite");
        !          2352:   A=(GEN)x[1]; I=(GEN)x[2]; k=lg(A)-1;
        !          2353:   if (typ(A)!=t_MAT) err(talker,"not a matrix in nfhermite");
        !          2354:   if (typ(I)!=t_VEC || lg(I)!=k+1)
        !          2355:     err(talker,"not a correct ideal list in nfhermite");
        !          2356:   if (!k) err(talker,"not a matrix of maximal rank in nfhermite");
        !          2357:   m=lg(A[1])-1;
        !          2358:   if (k<m) err(talker,"not a matrix of maximal rank in nfhermite");
        !          2359:
        !          2360:   p1 = cgetg(k+1,t_MAT); for (j=1; j<=k; j++) p1[j]=A[j];
        !          2361:   A = p1; I = dummycopy(I);
        !          2362:   for (j=1; j<=k; j++)
        !          2363:     if (typ(I[j])!=t_MAT) I[j]=(long)idealhermite_aux(nf,(GEN)I[j]);
        !          2364:
        !          2365:   J=cgetg(k+1,t_VEC); def=k+1;
        !          2366:   for (i=m; i>=1; i--)
        !          2367:   {
        !          2368:     GEN den,p4,p5,p6,u,v,newid, invnewid = NULL;
        !          2369:
        !          2370:     def--; j=def; while (j>=1 && gcmp0(gcoeff(A,i,j))) j--;
        !          2371:     if (!j) err(talker,"not a matrix of maximal rank in nfhermite");
        !          2372:     if (j==def) j--;
        !          2373:     else
        !          2374:     {
        !          2375:       p1=(GEN)A[j]; A[j]=A[def]; A[def]=(long)p1;
        !          2376:       p1=(GEN)I[j]; I[j]=I[def]; I[def]=(long)p1;
        !          2377:     }
        !          2378:     p1=gcoeff(A,i,def); p2=element_inv(nf,p1);
        !          2379:     A[def]=(long)element_mulvec(nf,p2,(GEN)A[def]);
        !          2380:     I[def]=(long)idealmul(nf,p1,(GEN)I[def]);
        !          2381:     for (  ; j; j--)
        !          2382:     {
        !          2383:       p1=gcoeff(A,i,j);
        !          2384:       if (!gcmp0(p1))
        !          2385:       {
        !          2386:        p2=idealmul(nf,p1,(GEN)I[j]);
        !          2387:        newid = idealadd(nf,p2,(GEN)I[def]);
        !          2388:        invnewid = hnfideal_inv(nf,newid);
        !          2389:        p4 = idealmul(nf, p2,        invnewid);
        !          2390:        p5 = idealmul(nf,(GEN)I[def],invnewid);
        !          2391:        y = idealaddtoone(nf,p4,p5);
        !          2392:        u=element_div(nf,(GEN)y[1],p1); v=(GEN)y[2];
        !          2393:        p6=gsub((GEN)A[j],element_mulvec(nf,p1,(GEN)A[def]));
        !          2394:        A[def]=ladd(element_mulvec(nf,u,(GEN)A[j]),
        !          2395:                    element_mulvec(nf,v,(GEN)A[def]));
        !          2396:        A[j]=(long)p6;
        !          2397:        I[j]=(long)idealmul(nf,idealmul(nf,(GEN)I[j],(GEN)I[def]),invnewid);
        !          2398:        I[def]=(long)newid; den=denom((GEN)I[j]);
        !          2399:        if (!gcmp1(den))
        !          2400:        {
        !          2401:          I[j]=lmul(den,(GEN)I[j]);
        !          2402:          A[j]=ldiv((GEN)A[j],den);
        !          2403:        }
        !          2404:       }
        !          2405:     }
        !          2406:     if (!invnewid) invnewid = hnfideal_inv(nf,(GEN)I[def]);
        !          2407:     p1=(GEN)I[def]; J[def]=(long)invnewid;
        !          2408:     for (j=def+1; j<=k; j++)
        !          2409:     {
        !          2410:       p2=gsub(element_reduce(nf,gcoeff(A,i,j),idealmul(nf,p1,(GEN)J[j])),
        !          2411:               gcoeff(A,i,j));
        !          2412:       A[j]=ladd((GEN)A[j],element_mulvec(nf,p2,(GEN)A[def]));
        !          2413:     }
        !          2414:   }
        !          2415:   tetpil=avma; y=cgetg(3,t_VEC);
        !          2416:   p1=cgetg(m+1,t_MAT); y[1]=(long)p1;
        !          2417:   p2=cgetg(m+1,t_VEC); y[2]=(long)p2;
        !          2418:   for (j=1; j<=m; j++) p1[j]=lcopy((GEN)A[j+k-m]);
        !          2419:   for (j=1; j<=m; j++) p2[j]=lcopy((GEN)I[j+k-m]);
        !          2420:   return gerepile(av,tetpil,y);
        !          2421: }
        !          2422:
        !          2423: /* A torsion module M over Z_K will be given by a row vector [A,I,J] with
        !          2424:  * three components. I=[b_1,...,b_n] is a row vector of k fractional ideals
        !          2425:  * given in HNF, J=[a_1,...,a_n] is a row vector of n fractional ideals in
        !          2426:  * HNF. A is an nxn matrix (same n) such that if A_j is the j-th column of A
        !          2427:  * and e_n is the canonical basis of K^n, then
        !          2428:  * M=(b_1e_1+...+b_ne_n)/(a_1A_1+...a_nA_n)
        !          2429:  */
        !          2430:
        !          2431: /* We input a torsion module x=[A,I,J] as above, and output the
        !          2432:  * smith normal form as K=[\c_1,...,\c_n] such that x=Z_K/\c_1+...+Z_K/\c_n.
        !          2433:  */
        !          2434: GEN
        !          2435: nfsmith(GEN nf, GEN x)
        !          2436: {
        !          2437:   long av,tetpil,i,j,k,l,lim,c,fl,n,m,N;
        !          2438:   GEN p1,p2,p3,p4,z,b,u,v,w,d,dinv,unnf,A,I,J;
        !          2439:
        !          2440:   nf=checknf(nf); N=lgef(nf[1])-3;
        !          2441:   if (typ(x)!=t_VEC || lg(x)!=4) err(talker,"not a module in nfsmith");
        !          2442:   A=(GEN)x[1]; I=(GEN)x[2]; J=(GEN)x[3];
        !          2443:   if (typ(A)!=t_MAT) err(talker,"not a matrix in nfsmith");
        !          2444:   n=lg(A)-1;
        !          2445:   if (typ(I)!=t_VEC || lg(I)!=n+1 || typ(J)!=t_VEC || lg(J)!=n+1)
        !          2446:     err(talker,"not a correct ideal list in nfsmith");
        !          2447:   if (!n) err(talker,"not a matrix of maximal rank in nfsmith");
        !          2448:   m=lg(A[1])-1;
        !          2449:   if (n<m) err(talker,"not a matrix of maximal rank in nfsmith");
        !          2450:   if (n>m) err(impl,"nfsmith for non square matrices");
        !          2451:
        !          2452:   av=avma; lim=stack_lim(av,1);
        !          2453:   p1 = cgetg(n+1,t_MAT); for (j=1; j<=n; j++) p1[j]=A[j];
        !          2454:   A = p1; I = dummycopy(I); J=dummycopy(J);
        !          2455:   for (j=1; j<=n; j++)
        !          2456:     if (typ(I[j])!=t_MAT) I[j]=(long)idealhermite_aux(nf,(GEN)I[j]);
        !          2457:   for (j=1; j<=n; j++)
        !          2458:     if (typ(J[j])!=t_MAT) J[j]=(long)idealhermite_aux(nf,(GEN)J[j]);
        !          2459:   for (i=n; i>=2; i--)
        !          2460:   {
        !          2461:     do
        !          2462:     {
        !          2463:       c=0;
        !          2464:       for (j=i-1; j>=1; j--)
        !          2465:       {
        !          2466:        p1=gcoeff(A,i,j);
        !          2467:        if (!gcmp0(p1))
        !          2468:        {
        !          2469:          p2=gcoeff(A,i,i);
        !          2470:          d=nfbezout(nf,p2,p1,(GEN)J[i],(GEN)J[j],&u,&v,&w,&dinv);
        !          2471:          if (!gcmp0(u))
        !          2472:          {
        !          2473:            if (!gcmp0(v))
        !          2474:              b=gadd(element_mulvec(nf,u,(GEN)A[i]),
        !          2475:                     element_mulvec(nf,v,(GEN)A[j]));
        !          2476:            else b=element_mulvec(nf,u,(GEN)A[i]);
        !          2477:          }
        !          2478:          else b=element_mulvec(nf,v,(GEN)A[j]);
        !          2479:          A[j]=lsub(element_mulvec(nf,p2,(GEN)A[j]),
        !          2480:                    element_mulvec(nf,p1,(GEN)A[i]));
        !          2481:          A[i]=(long)b; J[j]=(long)w; J[i]=(long)d;
        !          2482:        }
        !          2483:       }
        !          2484:       for (j=i-1; j>=1; j--)
        !          2485:       {
        !          2486:        p1=gcoeff(A,j,i);
        !          2487:        if (!gcmp0(p1))
        !          2488:        {
        !          2489:          p2=gcoeff(A,i,i);
        !          2490:          d=nfbezout(nf,p2,p1,(GEN)I[i],(GEN)I[j],&u,&v,&w,&dinv);
        !          2491:          if (gcmp0(u))
        !          2492:            b=element_mulvecrow(nf,v,A,j,i);
        !          2493:          else
        !          2494:          {
        !          2495:            if (gcmp0(v))
        !          2496:              b=element_mulvecrow(nf,u,A,i,i);
        !          2497:            else
        !          2498:              b=gadd(element_mulvecrow(nf,u,A,i,i),
        !          2499:                     element_mulvecrow(nf,v,A,j,i));
        !          2500:          }
        !          2501:          p3=gsub(element_mulvecrow(nf,p2,A,j,i),
        !          2502:                  element_mulvecrow(nf,p1,A,i,i));
        !          2503:          for (k=1; k<=i; k++) { coeff(A,j,k)=p3[k]; coeff(A,i,k)=b[k]; }
        !          2504:          I[j]=(long)w; I[i]=(long)d; c++;
        !          2505:        }
        !          2506:       }
        !          2507:       if (!c)
        !          2508:       {
        !          2509:        b=gcoeff(A,i,i); if (gcmp0(b)) break;
        !          2510:
        !          2511:        b=idealmul(nf,b,idealmul(nf,(GEN)J[i],(GEN)I[i]));
        !          2512:        fl=1;
        !          2513:        for (k=1; k<i && fl; k++)
        !          2514:          for (l=1; l<i && fl; l++)
        !          2515:          {
        !          2516:            p3=gcoeff(A,k,l);
        !          2517:            if (!gcmp0(p3))
        !          2518:              fl=gegal(idealadd(nf,b,idealmul(nf,p3,idealmul(nf,(GEN)J[l],(GEN)I[k]))),b);
        !          2519:          }
        !          2520:        if (!fl)
        !          2521:        {
        !          2522:          k--; l--;
        !          2523:          b=idealdiv(nf,(GEN)I[k],(GEN)I[i]);
        !          2524:          p4=gauss(idealdiv(nf,(GEN)J[i],idealmul(nf,p3,(GEN)J[l])),b);
        !          2525:          l=1; while (l<=N && gcmp1(denom((GEN)p4[l]))) l++;
        !          2526:          if (l>N) err(talker,"bug2 in nfsmith");
        !          2527:          p3=element_mulvecrow(nf,(GEN)b[l],A,k,i);
        !          2528:          for (l=1; l<=i; l++)
        !          2529:            coeff(A,i,l) = ladd(gcoeff(A,i,l),(GEN)p3[l]);
        !          2530:        }
        !          2531:       }
        !          2532:       if (low_stack(lim, stack_lim(av,1)))
        !          2533:       {
        !          2534:         GEN *gptr[3];
        !          2535:        if(DEBUGMEM>1) err(warnmem,"nfsmith");
        !          2536:         gptr[0]=&A; gptr[1]=&I; gptr[2]=&J; gerepilemany(av,gptr,3);
        !          2537:       }
        !          2538:     }
        !          2539:     while (c || !fl);
        !          2540:   }
        !          2541:   unnf=gscalcol_i(gun,N);
        !          2542:   p1=gcoeff(A,1,1); coeff(A,1,1)=(long)unnf;
        !          2543:   J[1]=(long)idealmul(nf,p1,(GEN)J[1]);
        !          2544:   for (i=2; i<=n; i++)
        !          2545:     if (!gegal(gcoeff(A,i,i),unnf)) err(talker,"bug in nfsmith");
        !          2546:   tetpil=avma; z=cgetg(n+1,t_VEC);
        !          2547:   for (i=1; i<=n; i++) z[i]=(long)idealmul(nf,(GEN)I[i],(GEN)J[i]);
        !          2548:   return gerepile(av,tetpil,z);
        !          2549: }
        !          2550:
        !          2551: /*******************************************************************/
        !          2552: /*                                                                 */
        !          2553: /*          ALGEBRE LINEAIRE DANS LES CORPS DE NOMBRES             */
        !          2554: /*                                                                 */
        !          2555: /*******************************************************************/
        !          2556:
        !          2557: #define trivlift(x) ((typ(x)==t_POLMOD)? (GEN)x[2]: lift_intern(x))
        !          2558:
        !          2559: GEN
        !          2560: element_mulmodpr2(GEN nf, GEN x, GEN y, GEN prhall)
        !          2561: {
        !          2562:   long av=avma;
        !          2563:   GEN p1;
        !          2564:
        !          2565:   nf=checknf(nf); checkprhall(prhall);
        !          2566:   p1 = element_mul(nf,x,y);
        !          2567:   return gerepileupto(av,nfreducemodpr(nf,p1,prhall));
        !          2568: }
        !          2569:
        !          2570: /* On ne peut PAS definir ca comme les autres par
        !          2571:  * #define element_divmodpr() nfreducemodpr(element_div())
        !          2572:  * car le element_div ne marche pas en general
        !          2573:  */
        !          2574: GEN
        !          2575: element_divmodpr(GEN nf, GEN x, GEN y, GEN prhall)
        !          2576: {
        !          2577:   long av=avma;
        !          2578:   GEN p1;
        !          2579:
        !          2580:   nf=checknf(nf); checkprhall(prhall);
        !          2581:   p1=lift_intern(gdiv(gmodulcp(gmul((GEN)nf[7],trivlift(x)), (GEN)nf[1]),
        !          2582:                       gmodulcp(gmul((GEN)nf[7],trivlift(y)), (GEN)nf[1])));
        !          2583:   p1=algtobasis_intern(nf,p1);
        !          2584:   return gerepileupto(av,nfreducemodpr(nf,p1,prhall));
        !          2585: }
        !          2586:
        !          2587: GEN
        !          2588: element_invmodpr(GEN nf, GEN y, GEN prhall)
        !          2589: {
        !          2590:   long av=avma;
        !          2591:   GEN p1;
        !          2592:
        !          2593:   p1=ginvmod(gmul((GEN)nf[7],trivlift(y)), (GEN)nf[1]);
        !          2594:   p1=algtobasis_intern(nf,p1);
        !          2595:   return gerepileupto(av,nfreducemodpr(nf,p1,prhall));
        !          2596: }
        !          2597:
        !          2598: GEN
        !          2599: element_powmodpr(GEN nf,GEN x,GEN k,GEN prhall)
        !          2600: {
        !          2601:   long av=avma,N,s;
        !          2602:   GEN y,z;
        !          2603:
        !          2604:   nf=checknf(nf); checkprhall(prhall);
        !          2605:   N=lgef(nf[1])-3;
        !          2606:   s=signe(k); k=(s>=0)?k:negi(k);
        !          2607:   z=x; y = gscalcol_i(gun,N);
        !          2608:   for(;;)
        !          2609:   {
        !          2610:     if (mpodd(k)) y=element_mulmodpr(nf,z,y,prhall);
        !          2611:     k=shifti(k,-1);
        !          2612:     if (signe(k)) z=element_sqrmodpr(nf,z,prhall);
        !          2613:     else
        !          2614:     {
        !          2615:       cgiv(k); if (s<0) y = element_invmodpr(nf,y,prhall);
        !          2616:       return gerepileupto(av,y);
        !          2617:     }
        !          2618:   }
        !          2619: }
        !          2620:
        !          2621: /* x est une matrice dont les coefficients sont des vecteurs dans la base
        !          2622:  * d'entiers modulo un ideal premier prhall, sous forme reduite modulo prhall.
        !          2623:  */
        !          2624: GEN
        !          2625: nfkermodpr(GEN nf, GEN x, GEN prhall)
        !          2626: {
        !          2627:   long i,j,k,r,t,n,m,av0,av,av1,av2,N,lim;
        !          2628:   GEN c,d,y,unnf,munnf,zeromodp,zeronf,p,pp,prh;
        !          2629:
        !          2630:   nf=checknf(nf); checkprhall(prhall);
        !          2631:   if (typ(x)!=t_MAT) err(typeer,"nfkermodpr");
        !          2632:   n=lg(x)-1; if (!n) return cgetg(1,t_MAT);
        !          2633:   prh=(GEN)prhall[1]; av0=avma;
        !          2634:   N=lgef(nf[1])-3; pp=gcoeff(prh,1,1);
        !          2635:
        !          2636:   zeromodp=gmodulsg(0,pp);
        !          2637:   unnf=cgetg(N+1,t_COL); unnf[1]=(long)gmodulsg(1,pp);
        !          2638:   zeronf=cgetg(N+1,t_COL); zeronf[1]=(long)zeromodp;
        !          2639:
        !          2640:   av=avma; munnf=cgetg(N+1,t_COL); munnf[1]=(long)gmodulsg(-1,pp);
        !          2641:   for (i=2; i<=N; i++)
        !          2642:     zeronf[i] = munnf[i] = unnf[i] = (long)zeromodp;
        !          2643:
        !          2644:   m=lg(x[1])-1; x=dummycopy(x); r=0;
        !          2645:   c=new_chunk(m+1); for (k=1; k<=m; k++) c[k]=0;
        !          2646:   d=new_chunk(n+1); av1=avma; lim=stack_lim(av1,1);
        !          2647:   for (k=1; k<=n; k++)
        !          2648:   {
        !          2649:     j=1;
        !          2650:     while (j<=m && (c[j] || gcmp0(gcoeff(x,j,k)))) j++;
        !          2651:     if (j>m) { r++; d[k]=0; }
        !          2652:     else
        !          2653:     {
        !          2654:       p=element_divmodpr(nf,munnf,gcoeff(x,j,k),prhall);
        !          2655:       c[j]=k; d[k]=j; coeff(x,j,k)=(long)munnf;
        !          2656:       for (i=k+1; i<=n; i++)
        !          2657:        coeff(x,j,i)=(long)element_mulmodpr(nf,p,gcoeff(x,j,i),prhall);
        !          2658:       for (t=1; t<=m; t++)
        !          2659:        if (t!=j)
        !          2660:        {
        !          2661:          p=gcoeff(x,t,k); coeff(x,t,k)=(long)zeronf;
        !          2662:          for (i=k+1; i<=n; i++)
        !          2663:             coeff(x,t,i)=ladd(gcoeff(x,t,i),
        !          2664:                              element_mulmodpr(nf,p,gcoeff(x,j,i),prhall));
        !          2665:        }
        !          2666:       if (low_stack(lim, stack_lim(av1,1)))
        !          2667:       {
        !          2668:         if (DEBUGMEM>1) err(warnmem,"nfkermodpr, k = %ld / %ld",k,n);
        !          2669:         av2=avma; x=gerepile(av1,av2,gcopy(x));
        !          2670:       }
        !          2671:     }
        !          2672:   }
        !          2673:   if (!r) { avma=av0; return cgetg(1,t_MAT); }
        !          2674:   av1=avma; y=cgetg(r+1,t_MAT);
        !          2675:   for (j=k=1; j<=r; j++,k++)
        !          2676:   {
        !          2677:     p=cgetg(n+1,t_COL); y[j]=(long)p; while (d[k]) k++;
        !          2678:     for (i=1; i<k; i++) p[i]=d[i]? lcopy(gcoeff(x,d[i],k)): (long)zeronf;
        !          2679:     p[k]=(long)unnf; for (i=k+1; i<=n; i++) p[i]=(long)zeronf;
        !          2680:   }
        !          2681:   return gerepile(av,av1,y);
        !          2682: }
        !          2683:
        !          2684: /* a.x=b ou b est un vecteur */
        !          2685: GEN
        !          2686: nfsolvemodpr(GEN nf, GEN a, GEN b, GEN prhall)
        !          2687: {
        !          2688:   long nbli,nbco,i,j,k,av=avma,tetpil;
        !          2689:   GEN aa,x,p,m,u;
        !          2690:
        !          2691:   nf=checknf(nf); checkprhall(prhall);
        !          2692:   if (typ(a)!=t_MAT) err(typeer,"nfsolvemodpr");
        !          2693:   nbco=lg(a)-1; nbli=lg(a[1])-1;
        !          2694:   if (typ(b)!=t_COL) err(typeer,"nfsolvemodpr");
        !          2695:   if (lg(b)!=nbco+1) err(mattype1,"nfsolvemodpr");
        !          2696:   x=cgetg(nbli+1,t_COL);
        !          2697:   for (j=1; j<=nbco; j++) x[j]=b[j];
        !          2698:   aa=cgetg(nbco+1,t_MAT);
        !          2699:   for (j=1; j<=nbco; j++)
        !          2700:   {
        !          2701:     aa[j]=lgetg(nbli+1,t_COL);
        !          2702:     for (i=1; i<=nbli; i++) coeff(aa,i,j)=coeff(a,i,j);
        !          2703:   }
        !          2704:   for (i=1; i<nbli; i++)
        !          2705:   {
        !          2706:     p=gcoeff(aa,i,i); k=i;
        !          2707:     if (gcmp0(p))
        !          2708:     {
        !          2709:       k=i+1; while (k<=nbli && gcmp0(gcoeff(aa,k,i))) k++;
        !          2710:       if (k>nbco) err(matinv1);
        !          2711:       for (j=i; j<=nbco; j++)
        !          2712:       {
        !          2713:        u=gcoeff(aa,i,j); coeff(aa,i,j)=coeff(aa,k,j);
        !          2714:        coeff(aa,k,j)=(long)u;
        !          2715:       }
        !          2716:       u=(GEN)x[i]; x[i]=x[k]; x[k]=(long)u;
        !          2717:       p=gcoeff(aa,i,i);
        !          2718:     }
        !          2719:     for (k=i+1; k<=nbli; k++)
        !          2720:     {
        !          2721:       m=gcoeff(aa,k,i);
        !          2722:       if (!gcmp0(m))
        !          2723:       {
        !          2724:        m=element_divmodpr(nf,m,p,prhall);
        !          2725:        for (j=i+1; j<=nbco; j++)
        !          2726:          coeff(aa,k,j)=lsub(gcoeff(aa,k,j),
        !          2727:                             element_mulmodpr(nf,m,gcoeff(aa,i,j),prhall));
        !          2728:        x[k]=lsub((GEN)x[k],element_mulmodpr(nf,m,(GEN)x[i],prhall));
        !          2729:       }
        !          2730:     }
        !          2731:   }
        !          2732:   /* Resolution systeme triangularise */
        !          2733:   p=gcoeff(aa,nbli,nbco); if (gcmp0(p)) err(matinv1);
        !          2734:
        !          2735:   x[nbli]=(long)element_divmodpr(nf,(GEN)x[nbli],p,prhall);
        !          2736:   for (i=nbli-1; i>0; i--)
        !          2737:   {
        !          2738:     m=(GEN)x[i];
        !          2739:     for (j=i+1; j<=nbco; j++)
        !          2740:       m=gsub(m,element_mulmodpr(nf,gcoeff(aa,i,j),(GEN)x[j],prhall));
        !          2741:     x[i]=(long)element_divmodpr(nf,m,gcoeff(aa,i,i),prhall);
        !          2742:   }
        !          2743:   tetpil=avma; return gerepile(av,tetpil,gcopy(x));
        !          2744: }
        !          2745:
        !          2746: GEN
        !          2747: nfsuppl(GEN nf, GEN x, long n, GEN prhall)
        !          2748: {
        !          2749:   long av=avma,av2,k,s,t,N,lx=lg(x);
        !          2750:   GEN y,p1,p2,p,unmodp,zeromodp,unnf,zeronf,prh;
        !          2751:   stackzone *zone;
        !          2752:
        !          2753:   k=lx-1; if (k>n) err(suppler2);
        !          2754:   if (k && lg(x[1])!=n+1) err(talker,"incorrect dimension in nfsupl");
        !          2755:   N=lgef(nf[1])-3; prh=(GEN)prhall[1]; p=gcoeff(prh,1,1);
        !          2756:
        !          2757:   zone  = switch_stack(NULL, 2*(3 + 2*lg(p) + N+1) + (n+3)*(n+1));
        !          2758:   switch_stack(zone,1);
        !          2759:   unmodp=gmodulsg(1,p); zeromodp=gmodulsg(0,p);
        !          2760:   unnf=gscalcol_proto(unmodp,zeromodp,N);
        !          2761:   zeronf=gscalcol_proto(zeromodp,zeromodp,N);
        !          2762:   y = idmat_intern(n,unnf,zeronf);
        !          2763:   switch_stack(zone,0); av2=avma;
        !          2764:
        !          2765:   for (s=1; s<=k; s++)
        !          2766:   {
        !          2767:     p1=nfsolvemodpr(nf,y,(GEN)x[s],prhall); t=s;
        !          2768:     while (t<=n && gcmp0((GEN)p1[t])) t++;
        !          2769:     avma=av2; if (t>n) err(suppler2);
        !          2770:     p2=(GEN)y[s]; y[s]=x[s]; if (s!=t) y[t]=(long)p2;
        !          2771:   }
        !          2772:   avma=av; y=gcopy(y);
        !          2773:   free(zone); return y;
        !          2774: }
        !          2775:
        !          2776: /* Given two fractional ideals a and b, gives x in a, y in b, z in b^-1,
        !          2777:    t in a^-1 such that xt-yz=1. In the present version, z is in Z. */
        !          2778: GEN
        !          2779: nfidealdet1(GEN nf, GEN a, GEN b)
        !          2780: {
        !          2781:   long av=avma,tetpil;
        !          2782:   GEN x,p1,p2,res,z,da,db;
        !          2783:
        !          2784:   da=denom(a); if (gcmp1(da)) da = NULL; else a=gmul(da,a);
        !          2785:   db=denom(b); if (gcmp1(db)) db = NULL; else b=gmul(db,b);
        !          2786:   a = idealinv(nf,a); x=idealcoprime(nf,a,b);
        !          2787:   p1=idealmul(nf,x,a); p2=idealaddtoone(nf,p1,b);
        !          2788:
        !          2789:   tetpil=avma; res=cgetg(5,t_VEC);
        !          2790:   res[1] = da? ldiv(x,da): lcopy(x);
        !          2791:   res[2] = db? ldiv((GEN)p2[2],db): lcopy((GEN)p2[2]);
        !          2792:   z = db? gneg_i(db): negi(gun);
        !          2793:   res[3] = (long) gscalcol_i(z, lgef(nf[1])-3);
        !          2794:   res[4] = (long) element_div(nf,(GEN)p2[1],(GEN)res[1]);
        !          2795:   return gerepile(av,tetpil,res);
        !          2796: }
        !          2797:
        !          2798: /* Given a pseudo basis pseudo, outputs a multiple of its ideal determinant */
        !          2799: GEN
        !          2800: nfdetint(GEN nf,GEN pseudo)
        !          2801: {
        !          2802:   GEN pass,c,v,det1,piv,pivprec,vi,p1,x,I,unnf,zeronf,id,idprod;
        !          2803:   long i,j,k,rg,n,n1,m,m1,av=avma,av1,tetpil,lim,cm=0,N;
        !          2804:
        !          2805:   nf=checknf(nf); N=lgef(nf[1])-3;
        !          2806:   if (typ(pseudo)!=t_VEC || lg(pseudo)!=3)
        !          2807:     err(talker,"not a module in nfdetint");
        !          2808:   x=(GEN)pseudo[1]; I=(GEN)pseudo[2];
        !          2809:   if (typ(x)!=t_MAT) err(talker,"not a matrix in nfdetint");
        !          2810:   n1=lg(x); n=n1-1; if (!n) return gun;
        !          2811:
        !          2812:   m1=lg(x[1]); m=m1-1;
        !          2813:   if (typ(I)!=t_VEC || lg(I)!=n1)
        !          2814:     err(talker,"not a correct ideal list in nfdetint");
        !          2815:
        !          2816:   unnf=gscalcol_i(gun,N); zeronf=zerocol(N);
        !          2817:   id=idmat(N); c=new_chunk(m1); for (k=1; k<=m; k++) c[k]=0;
        !          2818:   piv = pivprec = unnf;
        !          2819:
        !          2820:   av1=avma; lim=stack_lim(av1,1);
        !          2821:   det1=idprod=gzero; /* dummy for gerepilemany */
        !          2822:   pass=cgetg(m1,t_MAT); v=cgetg(m1,t_COL);
        !          2823:   for (j=1; j<=m; j++)
        !          2824:   {
        !          2825:     v[j] = zero; /* dummy */
        !          2826:     p1=cgetg(m1,t_COL); pass[j]=(long)p1;
        !          2827:     for (i=1; i<=m; i++) p1[i]=(long)zeronf;
        !          2828:   }
        !          2829:   for (rg=0,k=1; k<=n; k++)
        !          2830:   {
        !          2831:     long t = 0;
        !          2832:     for (i=1; i<=m; i++)
        !          2833:       if (!c[i])
        !          2834:       {
        !          2835:        vi=element_mul(nf,piv,gcoeff(x,i,k));
        !          2836:        for (j=1; j<=m; j++)
        !          2837:          if (c[j]) vi=gadd(vi,element_mul(nf,gcoeff(pass,i,j),gcoeff(x,j,k)));
        !          2838:        v[i]=(long)vi; if (!t && !gcmp0(vi)) t=i;
        !          2839:       }
        !          2840:     if (t)
        !          2841:     {
        !          2842:       pivprec = piv;
        !          2843:       if (rg == m-1)
        !          2844:       {
        !          2845:         if (!cm)
        !          2846:         {
        !          2847:           cm=1; idprod = id;
        !          2848:           for (i=1; i<=m; i++)
        !          2849:             if (i!=t)
        !          2850:               idprod = (idprod==id)? (GEN)I[c[i]]
        !          2851:                                    : idealmul(nf,idprod,(GEN)I[c[i]]);
        !          2852:         }
        !          2853:         p1 = idealmul(nf,(GEN)v[t],(GEN)I[k]); c[t]=0;
        !          2854:         det1 = (typ(det1)==t_INT)? p1: idealadd(nf,p1,det1);
        !          2855:       }
        !          2856:       else
        !          2857:       {
        !          2858:         rg++; piv=(GEN)v[t]; c[t]=k;
        !          2859:        for (i=1; i<=m; i++)
        !          2860:          if (!c[i])
        !          2861:           {
        !          2862:            for (j=1; j<=m; j++)
        !          2863:              if (c[j] && j!=t)
        !          2864:              {
        !          2865:                p1=gsub(element_mul(nf,piv,gcoeff(pass,i,j)),
        !          2866:                        element_mul(nf,(GEN)v[i],gcoeff(pass,t,j)));
        !          2867:                coeff(pass,i,j) = rg>1? (long) element_div(nf,p1,pivprec)
        !          2868:                                      : (long) p1;
        !          2869:              }
        !          2870:             coeff(pass,i,t)=lneg((GEN)v[i]);
        !          2871:           }
        !          2872:       }
        !          2873:     }
        !          2874:     if (low_stack(lim, stack_lim(av1,1)))
        !          2875:     {
        !          2876:       GEN *gptr[6];
        !          2877:       if(DEBUGMEM>1) err(warnmem,"nfdetint");
        !          2878:       gptr[0]=&det1; gptr[1]=&piv; gptr[2]=&pivprec; gptr[3]=&pass;
        !          2879:       gptr[4]=&v; gptr[5]=&idprod; gerepilemany(av1,gptr,6);
        !          2880:     }
        !          2881:   }
        !          2882:   if (!cm) { avma=av; return gscalmat(gzero,N); }
        !          2883:   tetpil=avma; return gerepile(av,tetpil,idealmul(nf,idprod,det1));
        !          2884: }
        !          2885:
        !          2886: /* clean in place (destroy x) */
        !          2887: static void
        !          2888: nfcleanmod(GEN nf, GEN x, long lim, GEN detmat)
        !          2889: {
        !          2890:   long lx=lg(x),i;
        !          2891:
        !          2892:   if (lim<=0 || lim>=lx) lim=lx-1;
        !          2893:   for (i=1; i<=lim; i++)
        !          2894:     x[i]=(long)element_reduce(nf,(GEN)x[i],detmat);
        !          2895: }
        !          2896:
        !          2897: static GEN
        !          2898: zero_nfbezout(GEN nf,GEN b, GEN ida,GEN idb,GEN *u,GEN *v,GEN *w,GEN *di)
        !          2899: {
        !          2900:   long av, tetpil, j, N=lgef(nf[1])-3;
        !          2901:   GEN pab,d;
        !          2902:
        !          2903:   d=idealmulelt(nf,b,idb); *di=idealinv(nf,d);
        !          2904:   av=avma; pab=idealmul(nf,ida,idb); tetpil=avma;
        !          2905:   *w=gerepile(av,tetpil, idealmul(nf,pab,*di));
        !          2906:
        !          2907:   *u=cgetg(N+1,t_COL); for (j=1; j<=N; j++) (*u)[j]=zero;
        !          2908:   *v=element_inv(nf,b); return d;
        !          2909: }
        !          2910:
        !          2911: /* a usage interne
        !          2912:  * Given elements a,b, ideals ida, idb, outputs d=a.ida+b.idb and gives
        !          2913:  * di=d^-1, w=ida.idb.di, u, v such that au+bv=1 and u in ida.di, v in
        !          2914:  * idb.di. We assume ida, idb non-zero, but a and b can be zero. Error if a
        !          2915:  * and b are both zero.
        !          2916:  */
        !          2917: static GEN
        !          2918: nfbezout(GEN nf,GEN a,GEN b, GEN ida,GEN idb, GEN *u,GEN *v,GEN *w,GEN *di)
        !          2919: {
        !          2920:   GEN pab,pu,pv,pw,uv,d,dinv,pa,pb,pa1,pb1, *gptr[5];
        !          2921:   long av,tetpil;
        !          2922:
        !          2923:   if (gcmp0(a))
        !          2924:   {
        !          2925:     if (gcmp0(b)) err(talker,"both elements zero in nfbezout");
        !          2926:     return zero_nfbezout(nf,b,ida,idb,u,v,w,di);
        !          2927:   }
        !          2928:   if (gcmp0(b))
        !          2929:     return zero_nfbezout(nf,a,idb,ida,v,u,w,di);
        !          2930:
        !          2931:   av = avma;
        !          2932:   pa=idealmulelt(nf,a,ida);
        !          2933:   pb=idealmulelt(nf,b,idb);
        !          2934:
        !          2935:   d=idealadd(nf,pa,pb); dinv=idealinv(nf,d);
        !          2936:   pa1=idealmullll(nf,pa,dinv);
        !          2937:   pb1=idealmullll(nf,pb,dinv);
        !          2938:   uv=idealaddtoone(nf,pa1,pb1);
        !          2939:   pab=idealmul(nf,ida,idb); tetpil=avma;
        !          2940:
        !          2941:   pu=element_div(nf,(GEN)uv[1],a);
        !          2942:   pv=element_div(nf,(GEN)uv[2],b);
        !          2943:   d=gcopy(d); dinv=gcopy(dinv);
        !          2944:   pw=idealmul(nf,pab,dinv);
        !          2945:
        !          2946:   *u=pu; *v=pv; *w=pw; *di=dinv;
        !          2947:   gptr[0]=u; gptr[1]=v; gptr[2]=w; gptr[3]=di;
        !          2948:   gptr[4]=&d; gerepilemanysp(av,tetpil,gptr,5);
        !          2949:   return d;
        !          2950: }
        !          2951:
        !          2952: /* A usage interne. Pas de verifs ni gestion de pile */
        !          2953: GEN
        !          2954: idealoplll(GEN op(GEN,GEN,GEN), GEN nf, GEN x, GEN y)
        !          2955: {
        !          2956:   GEN z = op(nf,x,y), den = denom(z);
        !          2957:
        !          2958:   if (gcmp1(den)) den = NULL; else z=gmul(den,z);
        !          2959:   z=gmul(z,lllintpartial(z));
        !          2960:   return den? gdiv(z,den): z;
        !          2961: }
        !          2962:
        !          2963: /* A usage interne. Pas de verifs ni gestion de pile */
        !          2964: GEN
        !          2965: idealmulelt(GEN nf, GEN elt, GEN x)
        !          2966: {
        !          2967:   long lx=lg(x),j;
        !          2968:   GEN z=cgetg(lx,t_MAT);
        !          2969:   for (j=1; j<lx; j++) z[j]=(long)element_mul(nf,elt,(GEN)x[j]);
        !          2970:   return z;
        !          2971: }
        !          2972:
        !          2973: GEN
        !          2974: nfhermitemod(GEN nf, GEN pseudo, GEN detmat)
        !          2975: {
        !          2976:   long av0=avma,li,co,av,tetpil,i,j,jm1,def,ldef,lim,N;
        !          2977:   GEN b,q,w,p1,p2,d,u,v,den,x,I,J,dinv,unnf,wh;
        !          2978:
        !          2979:   nf=checknf(nf); N=lgef(nf[1])-3;
        !          2980:   if (typ(pseudo)!=t_VEC || lg(pseudo)!=3)
        !          2981:     err(talker,"not a module in nfhermitemod");
        !          2982:   x=(GEN)pseudo[1]; I=(GEN)pseudo[2];
        !          2983:   if (typ(x)!=t_MAT) err(talker,"not a matrix in nfhermitemod");
        !          2984:   co=lg(x);
        !          2985:   if (typ(I)!=t_VEC || lg(I)!=co)
        !          2986:     err(talker,"not a correct ideal list in nfhermitemod");
        !          2987:   if (co==1) return cgetg(1,t_MAT);
        !          2988:
        !          2989:   li=lg(x[1]); x=dummycopy(x); I=dummycopy(I);
        !          2990:   unnf=gscalcol_i(gun,N);
        !          2991:   for (j=1; j<co; j++)
        !          2992:     if (typ(I[j])!=t_MAT) I[j]=(long)idealhermite_aux(nf,(GEN)I[j]);
        !          2993:
        !          2994:   den=denom(detmat); if (!gcmp1(den)) detmat=gmul(den,detmat);
        !          2995:   detmat=gmul(detmat,lllintpartial(detmat));
        !          2996:
        !          2997:   av=avma; lim=stack_lim(av,1);
        !          2998:   def=co; ldef=(li>co)?li-co+1:1;
        !          2999:   for (i=li-1; i>=ldef; i--)
        !          3000:   {
        !          3001:     def--; j=def-1; while (j && gcmp0(gcoeff(x,i,j))) j--;
        !          3002:     while (j)
        !          3003:     {
        !          3004:       jm1=j-1; if (!jm1) jm1=def;
        !          3005:       d=nfbezout(nf,gcoeff(x,i,j),gcoeff(x,i,jm1),(GEN)I[j],(GEN)I[jm1],
        !          3006:                  &u,&v,&w,&dinv);
        !          3007:       if (!gcmp0(u))
        !          3008:       {
        !          3009:        p1=element_mulvec(nf,u,(GEN)x[j]);
        !          3010:        if (!gcmp0(v)) p1=gadd(p1, element_mulvec(nf,v,(GEN)x[jm1]));
        !          3011:       }
        !          3012:       else p1=element_mulvec(nf,v,(GEN)x[jm1]);
        !          3013:       x[j]=lsub(element_mulvec(nf,gcoeff(x,i,j),(GEN)x[jm1]),
        !          3014:                 element_mulvec(nf,gcoeff(x,i,jm1),(GEN)x[j]));
        !          3015:       nfcleanmod(nf,(GEN)x[j],i,idealdivlll(nf,detmat,w));
        !          3016:       nfcleanmod(nf,p1,i,idealmullll(nf,detmat,dinv));
        !          3017:       x[jm1]=(long)p1; I[j]=(long)w; I[jm1]=(long)d;
        !          3018:       j--; while (j && gcmp0(gcoeff(x,i,j))) j--;
        !          3019:     }
        !          3020:     if (low_stack(lim, stack_lim(av,1)))
        !          3021:     {
        !          3022:       GEN *gptr[2];
        !          3023:       if(DEBUGMEM>1) err(warnmem,"[1]: nfhermitemod");
        !          3024:       gptr[0]=&x; gptr[1]=&I; gerepilemany(av,gptr,2);
        !          3025:     }
        !          3026:   }
        !          3027:   b=detmat; wh=cgetg(li,t_MAT); def--;
        !          3028:   for (i=li-1; i>=1; i--)
        !          3029:   {
        !          3030:     d = nfbezout(nf,gcoeff(x,i,i+def),unnf,(GEN)I[i+def],b,&u,&v,&w,&dinv);
        !          3031:     p1 = element_mulvec(nf,u,(GEN)x[i+def]);
        !          3032:     nfcleanmod(nf,p1,i,idealmullll(nf,b,dinv));
        !          3033:     wh[i]=(long)p1; coeff(wh,i,i)=(long)unnf; I[i+def]=(long)d;
        !          3034:     if (i>1) b=idealmul(nf,b,dinv);
        !          3035:   }
        !          3036:   J=cgetg(li,t_VEC); J[1]=zero;
        !          3037:   for (j=2; j<li; j++) J[j]=(long)idealinv(nf,(GEN)I[j+def]);
        !          3038:   for (i=li-2; i>=1; i--)
        !          3039:   {
        !          3040:     for (j=i+1; j<li; j++)
        !          3041:     {
        !          3042:       q=idealmul(nf,(GEN)I[i+def],(GEN)J[j]);
        !          3043:       p1=gsub(element_reduce(nf,gcoeff(wh,i,j),q),gcoeff(wh,i,j));
        !          3044:       wh[j]=(long)gadd((GEN)wh[j],element_mulvec(nf,p1,(GEN)wh[i]));
        !          3045:     }
        !          3046:     if (low_stack(lim, stack_lim(av,1)))
        !          3047:     {
        !          3048:       GEN *gptr[3];
        !          3049:       if(DEBUGMEM>1) err(warnmem,"[2]: nfhermitemod");
        !          3050:       gptr[0]=&wh; gptr[1]=&I; gptr[2]=&J; gerepilemany(av,gptr,3);
        !          3051:     }
        !          3052:   }
        !          3053:   tetpil=avma; p1=cgetg(3,t_VEC); p1[1]=lcopy(wh);
        !          3054:   p2=cgetg(li,t_VEC); p1[2]=(long)p2;
        !          3055:   for (j=1; j<li; j++) p2[j]=lcopy((GEN)I[j+def]);
        !          3056:   return gerepile(av0,tetpil,p1);
        !          3057: }

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