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

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

1.1       noro        1: /* $Id: buch3.c,v 1.47 2001/10/01 12:11:30 karim Exp $
                      2:
                      3: Copyright (C) 2000  The PARI group.
                      4:
                      5: This file is part of the PARI/GP package.
                      6:
                      7: PARI/GP is free software; you can redistribute it and/or modify it under the
                      8: terms of the GNU General Public License as published by the Free Software
                      9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     10: ANY WARRANTY WHATSOEVER.
                     11:
                     12: Check the License for details. You should have received a copy of it, along
                     13: with the package; see the file 'COPYING'. If not, write to the Free Software
                     14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
                     15:
                     16: /*******************************************************************/
                     17: /*                                                                 */
                     18: /*                       RAY CLASS FIELDS                          */
                     19: /*                                                                 */
                     20: /*******************************************************************/
                     21: #include "pari.h"
                     22: #include "parinf.h"
                     23:
                     24: extern GEN concatsp3(GEN x, GEN y, GEN z);
                     25: extern GEN check_and_build_cycgen(GEN bnf);
                     26: extern GEN gmul_mat_smallvec(GEN x, GEN y);
                     27: extern GEN ideleaddone_aux(GEN nf,GEN x,GEN ideal);
                     28: extern GEN logunitmatrix(GEN nf,GEN funits,GEN racunit,GEN bid);
                     29: extern GEN vconcat(GEN Q1, GEN Q2);
                     30: extern void minim_alloc(long n, double ***q, GEN *x, double **y,  double **z, double **v);
                     31: extern GEN to_famat_all(GEN x, GEN y);
                     32: extern GEN trivfact(void);
                     33: extern GEN arch_mul(GEN x, GEN y);
                     34: extern GEN isprincipalfact(GEN bnf,GEN P, GEN e, GEN C, long flag);
                     35: extern GEN idealaddtoone_i(GEN nf, GEN x, GEN y);
                     36: extern GEN ideallllred_elt(GEN nf, GEN I);
                     37:
                     38: /* U W V = D, Ui = U^(-1) */
                     39: GEN
                     40: compute_class_number(GEN W, GEN *D,GEN *Ui,GEN *V)
                     41: {
                     42:   GEN S = smith2(W);
                     43:
                     44:   *Ui= ginv((GEN)S[1]);
                     45:   if (V) *V = (GEN)S[2];
                     46:   *D = (GEN)S[3];
                     47:   if (DEBUGLEVEL>=4) msgtimer("smith/class group");
                     48:   return dethnf_i(*D);
                     49: }
                     50:
                     51: /* FIXME: obsolete, see zarchstar (which is much slower unfortunately). */
                     52: static GEN
                     53: get_full_rank(GEN nf, GEN v, GEN _0, GEN _1, GEN gen, long ngen, long rankmax)
                     54: {
                     55:   GEN vecsign,v1,p1,alpha, bas=(GEN)nf[7], rac=(GEN)nf[6];
                     56:   long rankinit = lg(v)-1, N = degpol(nf[1]), va = varn(nf[1]);
                     57:   long limr,i,k,kk,r,rr;
                     58:   vecsign = cgetg(rankmax+1,t_COL);
                     59:   for (r=1,rr=3; ; r++,rr+=2)
                     60:   {
                     61:     p1 = gpowgs(stoi(rr),N);
                     62:     limr = is_bigint(p1)? BIGINT: p1[2];
                     63:     limr = (limr-1)>>1;
                     64:     for (k=rr;  k<=limr; k++)
                     65:     {
                     66:       long av1=avma;
                     67:       alpha = gzero;
                     68:       for (kk=k,i=1; i<=N; i++,kk/=rr)
                     69:       {
                     70:         long lambda = (kk+r)%rr - r;
                     71:         if (lambda)
                     72:           alpha = gadd(alpha,gmulsg(lambda,(GEN)bas[i]));
                     73:       }
                     74:       for (i=1; i<=rankmax; i++)
                     75:        vecsign[i] = (gsigne(gsubst(alpha,va,(GEN)rac[i])) > 0)? (long)_0
                     76:                                                                : (long)_1;
                     77:       v1 = concatsp(v, vecsign);
                     78:       if (rank(v1) == rankinit) avma=av1;
                     79:       else
                     80:       {
                     81:        v=v1; rankinit++; ngen++;
                     82:         gen[ngen] = (long) alpha;
                     83:        if (rankinit == rankmax) return ginv(v); /* full rank */
                     84:       }
                     85:     }
                     86:   }
                     87: }
                     88:
                     89: /* FIXME: obsolete. Replace by a call to buchrayall (currently much slower) */
                     90: GEN
                     91: buchnarrow(GEN bnf)
                     92: {
                     93:   GEN nf,_0,_1,cyc,gen,v,matsign,arch,cycgen,logs;
                     94:   GEN dataunit,p1,p2,h,clh,basecl,met,u1;
                     95:   long r1,R,i,j,ngen,sizeh,t,lo,c;
                     96:   ulong av = avma;
                     97:
                     98:   bnf = checkbnf(bnf);
                     99:   nf = checknf(bnf); r1 = nf_get_r1(nf);
                    100:   if (!r1) return gcopy(gmael(bnf,8,1));
                    101:
                    102:   _1 = gmodulss(1,2);
                    103:   _0 = gmodulss(0,2);
                    104:   cyc = gmael3(bnf,8,1,2);
                    105:   gen = gmael3(bnf,8,1,3); ngen = lg(gen)-1;
                    106:   matsign = signunits(bnf); R = lg(matsign);
                    107:   dataunit = cgetg(R+1,t_MAT);
                    108:   for (j=1; j<R; j++)
                    109:   {
                    110:     p1=cgetg(r1+1,t_COL); dataunit[j]=(long)p1;
                    111:     for (i=1; i<=r1; i++)
                    112:       p1[i] = (signe(gcoeff(matsign,i,j)) > 0)? (long)_0: (long)_1;
                    113:   }
                    114:   v = cgetg(r1+1,t_COL); for (i=1; i<=r1; i++) v[i] = (long)_1;
                    115:   dataunit[R] = (long)v; v = image(dataunit); t = lg(v)-1;
                    116:   if (t == r1) { avma = av; return gcopy(gmael(bnf,8,1)); }
                    117:
                    118:   sizeh = ngen+r1-t; p1 = cgetg(sizeh+1,t_COL);
                    119:   for (i=1; i<=ngen; i++) p1[i] = gen[i];
                    120:   gen = p1;
                    121:   v = get_full_rank(nf,v,_0,_1,gen,ngen,r1);
                    122:
                    123:   arch = cgetg(r1+1,t_VEC); for (i=1; i<=r1; i++) arch[i]=un;
                    124:   cycgen = check_and_build_cycgen(bnf);
                    125:   logs = cgetg(ngen+1,t_MAT);
                    126:   for (j=1; j<=ngen; j++)
                    127:   {
                    128:     GEN u = lift_intern(gmul(v, zsigne(nf,(GEN)cycgen[j],arch)));
                    129:     logs[j] = (long)vecextract_i(u, t+1, r1);
                    130:   }
                    131:   /* [ cyc  0 ]
                    132:    * [ logs 2 ] = relation matrix for Cl_f */
                    133:   h = concatsp(
                    134:     vconcat(diagonal(cyc), logs),
                    135:     vconcat(zeromat(ngen, r1-t), gscalmat(gdeux,r1-t))
                    136:   );
                    137:   clh = compute_class_number(h,&met,&u1,NULL);
                    138:   lo = lg(met)-1;
                    139:   for (c=1; c<=lo; c++)
                    140:     if (gcmp1(gcoeff(met,c,c))) break;
                    141:
                    142:   u1 = reducemodmatrix(u1,h);
                    143:   basecl = cgetg(c,t_VEC);
                    144:   for (j=1; j<c; j++)
                    145:   {
                    146:     p1 = gcoeff(u1,1,j);
                    147:     p2 = idealpow(nf,(GEN)gen[1],p1);
                    148:     if (signe(p1) < 0) p2 = numer(p2);
                    149:     for (i=2; i<=lo; i++)
                    150:     {
                    151:       p1 = gcoeff(u1,i,j);
                    152:       if (signe(p1))
                    153:       {
                    154:        p2 = idealmul(nf,p2, idealpow(nf,(GEN)gen[i],p1));
                    155:         p1 = content(p2); if (!gcmp1(p1)) p2 = gdiv(p2,p1);
                    156:       }
                    157:     }
                    158:     basecl[j] = (long)p2;
                    159:   }
                    160:   v = cgetg(4,t_VEC);
                    161:   v[1] = lcopy(clh); setlg(met,c);
                    162:   v[2] = (long)mattodiagonal(met);
                    163:   v[3] = lcopy(basecl); return gerepileupto(av, v);
                    164: }
                    165:
                    166: /* given two coprime ideals x (integral) and id, compute alpha in x,
                    167:  * alpha = 1 mod (id), with x/alpha nearly reduced.
                    168:  */
                    169: static GEN
                    170: findalpha(GEN nf,GEN x,GEN id)
                    171: {
                    172:   GEN p1, y;
                    173:   GEN alp = idealaddtoone_i(nf,x,id);
                    174:
                    175:   y = ideallllred_elt(nf, idealmullll(nf,x,id));
                    176:   p1 = ground(element_div(nf,alp,y));
                    177:   alp = gsub(alp, element_mul(nf,p1,y));
                    178:   return gcmp0(alp)? y: alp;
                    179: }
                    180:
                    181: static int
                    182: too_big(GEN nf, GEN bet)
                    183: {
                    184:   GEN x = gnorm(basistoalg(nf,bet));
                    185:   switch (typ(x))
                    186:   {
                    187:     case t_INT: return absi_cmp(x, gun);
                    188:     case t_FRAC: return absi_cmp((GEN)x[1], (GEN)x[2]);
                    189:   }
                    190:   err(bugparier, "wrong type in too_big");
                    191:   return 0; /* not reached */
                    192: }
                    193:
                    194: static GEN
                    195: idealmodidele(GEN nf, GEN x, GEN ideal, GEN sarch, GEN arch)
                    196: {
                    197:   long av = avma,i,l;
                    198:   GEN p1,p2,alp,bet,b;
                    199:
                    200:   nf=checknf(nf); alp=findalpha(nf,x,ideal);
                    201:   p1=idealdiv(nf,alp,x);
                    202:   bet = element_div(nf,findalpha(nf,p1,ideal),alp);
                    203:   if (too_big(nf,bet) > 0) { avma=av; return x; }
                    204:   p1=(GEN)sarch[2]; l=lg(p1);
                    205:   if (l > 1)
                    206:   {
                    207:     b=bet; p2=lift_intern(gmul((GEN)sarch[3],zsigne(nf,bet,arch)));
                    208:     for (i=1; i<l; i++)
                    209:     if (signe(p2[i])) bet = element_mul(nf,bet,(GEN)p1[i]);
                    210:     if (b != bet && too_big(nf,bet) > 0) { avma=av; return x; }
                    211:   }
                    212:   return idealmul(nf,bet,x);
                    213: }
                    214:
                    215: static GEN
                    216: idealmulmodidele(GEN nf,GEN x,GEN y, GEN ideal,GEN sarch,GEN arch)
                    217: {
                    218:   return idealmodidele(nf,idealmul(nf,x,y),ideal,sarch,arch);
                    219: }
                    220:
                    221: /* assume n > 0 */
                    222: /* FIXME: should compute x^n = a I using idealred, then reduce a mod idele */
                    223: static GEN
                    224: idealpowmodidele(GEN nf,GEN x,GEN n, GEN ideal,GEN sarch,GEN arch)
                    225: {
                    226:   long i,m,av=avma;
                    227:   GEN y;
                    228:   ulong j;
                    229:
                    230:   if (cmpis(n, 16) < 0)
                    231:   {
                    232:     if (gcmp1(n)) return x;
                    233:     x = idealpow(nf,x,n);
                    234:     x = idealmodidele(nf,x,ideal,sarch,arch);
                    235:     return gerepileupto(av,x);
                    236:   }
                    237:
                    238:   i = lgefint(n)-1; m=n[i]; j=HIGHBIT;
                    239:   while ((m&j)==0) j>>=1;
                    240:   y = x;
                    241:   for (j>>=1; j; j>>=1)
                    242:   {
                    243:     y = idealmul(nf,y,y);
                    244:     if (m&j) y = idealmul(nf,y,x);
                    245:     y = idealmodidele(nf,y,ideal,sarch,arch);
                    246:   }
                    247:   for (i--; i>=2; i--)
                    248:     for (m=n[i],j=HIGHBIT; j; j>>=1)
                    249:     {
                    250:       y = idealmul(nf,y,y);
                    251:       if (m&j) y = idealmul(nf,y,x);
                    252:       y = idealmodidele(nf,y,ideal,sarch,arch);
                    253:     }
                    254:   return gerepileupto(av,y);
                    255: }
                    256:
                    257: static GEN
                    258: buchrayall(GEN bnf,GEN module,long flag)
                    259: {
                    260:   GEN nf,cyc,gen,genplus,fa2,sarch,hmatu,u,clg,logs;
                    261:   GEN dataunit,p1,p2,h,clh,genray,met,u1,u2,u1old,cycgen;
                    262:   GEN racunit,bigres,bid,cycbid,genbid,x,y,funits,hmat,vecel;
                    263:   long RU,Ri,i,j,ngen,lh,lo,c,av=avma;
                    264:
                    265:   bnf = checkbnf(bnf); nf = checknf(bnf);
                    266:   funits = check_units(bnf, "buchrayall"); RU = lg(funits);
                    267:   vecel = genplus = NULL; /* gcc -Wall */
                    268:   bigres = (GEN)bnf[8];
                    269:   cyc = gmael(bigres,1,2);
                    270:   gen = gmael(bigres,1,3); ngen = lg(cyc)-1;
                    271:
                    272:   bid = zidealstarinitall(nf,module,1);
                    273:   cycbid = gmael(bid,2,2);
                    274:   genbid = gmael(bid,2,3);
                    275:   Ri = lg(cycbid)-1; lh = ngen+Ri;
                    276:
                    277:   x = idealhermite(nf,module);
                    278:   if (Ri || flag & (nf_INIT|nf_GEN))
                    279:   {
                    280:     vecel = cgetg(ngen+1,t_VEC);
                    281:     for (j=1; j<=ngen; j++)
                    282:     {
                    283:       p1 = idealcoprime(nf,(GEN)gen[j],x);
                    284:       if (isnfscalar(p1)) p1 = (GEN)p1[1];
                    285:       vecel[j]=(long)p1;
                    286:     }
                    287:   }
                    288:   if (flag & nf_GEN)
                    289:   {
                    290:     genplus = cgetg(lh+1,t_VEC);
                    291:     for (j=1; j<=ngen; j++)
                    292:       genplus[j] = (long) idealmul(nf,(GEN)vecel[j],(GEN)gen[j]);
                    293:     for (  ; j<=lh; j++)
                    294:       genplus[j] = genbid[j-ngen];
                    295:   }
                    296:   if (!Ri)
                    297:   {
                    298:     if (!(flag & nf_GEN)) clg = cgetg(3,t_VEC);
                    299:     else
                    300:       { clg = cgetg(4,t_VEC); clg[3] = (long)genplus; }
                    301:     clg[1] = mael(bigres,1,1);
                    302:     clg[2] = (long)cyc;
                    303:     if (!(flag & nf_INIT)) return gerepilecopy(av,clg);
                    304:     y = cgetg(7,t_VEC);
                    305:     y[1] = lcopy(bnf);
                    306:     y[2] = lcopy(bid);
                    307:     y[3] = lcopy(vecel);
                    308:     y[4] = (long)idmat(ngen);
                    309:     y[5] = lcopy(clg); u = cgetg(3,t_VEC);
                    310:     y[6] = (long)u;
                    311:       u[1] = lgetg(1,t_MAT);
                    312:       u[2] = (long)idmat(RU);
                    313:     return gerepileupto(av,y);
                    314:   }
                    315:   fa2 = (GEN)bid[4]; sarch = (GEN)fa2[lg(fa2)-1];
                    316:
                    317:   cycgen = check_and_build_cycgen(bnf);
                    318:   dataunit = cgetg(RU+1,t_MAT); racunit = gmael(bigres,4,2);
                    319:   dataunit[1] = (long)zideallog(nf,racunit,bid);
                    320:   for (j=2; j<=RU; j++)
                    321:     dataunit[j] = (long)zideallog(nf,(GEN)funits[j-1],bid);
                    322:   dataunit = concatsp(dataunit, diagonal(cycbid));
                    323:   hmatu = hnfall(dataunit); hmat = (GEN)hmatu[1];
                    324:
                    325:   logs = cgetg(ngen+1, t_MAT);
                    326:   /* FIXME: cycgen[j] is not necessarily coprime to bid, but it is made coprime
                    327:    * in zideallog using canonical uniformizers [from bid data]: no need to
                    328:    * correct it here. The same ones will be used in isprincipalrayall. Hence
                    329:    * modification by vecel is useless. */
                    330:   for (j=1; j<=ngen; j++)
                    331:   {
                    332:     p1 = (GEN)cycgen[j];
                    333:     if (typ(vecel[j]) != t_INT) /* <==> != 1 */
                    334:       p1 = arch_mul(to_famat_all((GEN)vecel[j], (GEN)cyc[j]), p1);
                    335:     logs[j] = (long)zideallog(nf,p1,bid); /* = log(genplus[j]) */
                    336:   }
                    337:   /* [ cyc  0   ]
                    338:    * [-logs hmat] = relation matrix for Cl_f */
                    339:   h = concatsp(
                    340:     vconcat(diagonal(cyc), gneg_i(logs)),
                    341:     vconcat(zeromat(ngen, Ri), hmat)
                    342:   );
                    343:   clh = compute_class_number(h,&met,&u1,NULL);
                    344:   u1old = u1; lo = lg(met)-1;
                    345:   for (c=1; c<=lo; c++)
                    346:     if (gcmp1(gcoeff(met,c,c))) break;
                    347:
                    348:   if (flag & nf_GEN)
                    349:   {
                    350:     GEN Id = idmat(degpol(nf[1])), arch = (GEN)module[2];
                    351:     u1 = reducemodmatrix(u1,h);
                    352:     genray = cgetg(c,t_VEC);
                    353:     for (j=1; j<c; j++)
                    354:     {
                    355:       GEN *op, minus = Id, plus = Id;
                    356:       long av1 = avma, s;
                    357:       for (i=1; i<=lo; i++)
                    358:       {
                    359:        p1 = gcoeff(u1,i,j);
                    360:         if (!(s = signe(p1))) continue;
                    361:
                    362:         if (s > 0) op = &plus; else { op = &minus; p1 = negi(p1); }
                    363:         p1 = idealpowmodidele(nf,(GEN)genplus[i],p1,x,sarch,arch);
                    364:         *op = *op==Id? p1
                    365:                      : idealmulmodidele(nf,*op,p1,x,sarch,arch);
                    366:       }
                    367:       if (minus == Id) p1 = plus;
                    368:       else
                    369:       {
                    370:         p2 = ideleaddone_aux(nf,minus,module);
                    371:         p1 = idealdivexact(nf,idealmul(nf,p2,plus),minus);
                    372:         p1 = idealmodidele(nf,p1,x,sarch,arch);
                    373:       }
                    374:       genray[j]=lpileupto(av1,p1);
                    375:     }
                    376:     clg = cgetg(4,t_VEC); clg[3] = lcopy(genray);
                    377:   } else clg = cgetg(3,t_VEC);
                    378:   clg[1] = licopy(clh); setlg(met,c);
                    379:   clg[2] = (long)mattodiagonal(met);
                    380:   if (!(flag & nf_INIT)) return gerepileupto(av,clg);
                    381:
                    382:   u2 = cgetg(Ri+1,t_MAT);
                    383:   u1 = cgetg(RU+1,t_MAT); u = (GEN)hmatu[2];
                    384:   for (j=1; j<=RU; j++) { u1[j]=u[j]; setlg(u[j],RU+1); }
                    385:   u += RU;
                    386:   for (j=1; j<=Ri; j++) { u2[j]=u[j]; setlg(u[j],RU+1); }
                    387:   p1 = lllint(u1); p2 = ginv(hmat);
                    388:   y = cgetg(7,t_VEC);
                    389:   y[1] = lcopy(bnf);
                    390:   y[2] = lcopy(bid);
                    391:   y[3] = lcopy(vecel);
                    392:   y[4] = linv(u1old);
                    393:   y[5] = lcopy(clg); u = cgetg(3,t_VEC);
                    394:   y[6] = (long)u;
                    395:     u[1] = lmul(u2,p2);
                    396:     u[2] = lmul(u1,p1);
                    397:   return gerepileupto(av,y);
                    398: }
                    399:
                    400: GEN
                    401: buchrayinitgen(GEN bnf, GEN ideal)
                    402: {
                    403:   return buchrayall(bnf,ideal, nf_INIT | nf_GEN);
                    404: }
                    405:
                    406: GEN
                    407: buchrayinit(GEN bnf, GEN ideal)
                    408: {
                    409:   return buchrayall(bnf,ideal, nf_INIT);
                    410: }
                    411:
                    412: GEN
                    413: buchray(GEN bnf, GEN ideal)
                    414: {
                    415:   return buchrayall(bnf,ideal, nf_GEN);
                    416: }
                    417:
                    418: GEN
                    419: bnrclass0(GEN bnf, GEN ideal, long flag)
                    420: {
                    421:   switch(flag)
                    422:   {
                    423:     case 0: flag = nf_GEN; break;
                    424:     case 1: flag = nf_INIT; break;
                    425:     case 2: flag = nf_INIT | nf_GEN; break;
                    426:     default: err(flagerr,"bnrclass");
                    427:   }
                    428:   return buchrayall(bnf,ideal,flag);
                    429: }
                    430:
                    431: GEN
                    432: bnrinit0(GEN bnf, GEN ideal, long flag)
                    433: {
                    434:   switch(flag)
                    435:   {
                    436:     case 0: flag = nf_INIT; break;
                    437:     case 1: flag = nf_INIT | nf_GEN; break;
                    438:     default: err(flagerr,"bnrinit");
                    439:   }
                    440:   return buchrayall(bnf,ideal,flag);
                    441: }
                    442:
                    443: GEN
                    444: rayclassno(GEN bnf,GEN ideal)
                    445: {
                    446:   GEN nf,h,dataunit,racunit,bigres,bid,cycbid,funits,H;
                    447:   long RU,i;
                    448:   ulong av = avma;
                    449:
                    450:   bnf = checkbnf(bnf); nf = (GEN)bnf[7];
                    451:   bigres = (GEN)bnf[8]; h = gmael(bigres,1,1); /* class number */
                    452:   bid = zidealstarinitall(nf,ideal,0);
                    453:   cycbid = gmael(bid,2,2);
                    454:   if (lg(cycbid) == 1) return gerepileuptoint(av, icopy(h));
                    455:
                    456:   funits = check_units(bnf,"rayclassno");
                    457:   RU = lg(funits); racunit = gmael(bigres,4,2);
                    458:   dataunit = cgetg(RU+1,t_MAT);
                    459:   dataunit[1] = (long)zideallog(nf,racunit,bid);
                    460:   for (i=2; i<=RU; i++)
                    461:     dataunit[i] = (long)zideallog(nf,(GEN)funits[i-1],bid);
                    462:   dataunit = concatsp(dataunit, diagonal(cycbid));
                    463:   H = hnfmodid(dataunit,(GEN)cycbid[1]); /* (Z_K/f)^* / units ~ Z^n / H */
                    464:   return gerepileuptoint(av, mulii(h, dethnf_i(H)));
                    465: }
                    466:
                    467: GEN
                    468: quick_isprincipalgen(GEN bnf, GEN x)
                    469: {
                    470:   GEN z = cgetg(3, t_VEC), gen = gmael3(bnf,8,1,3);
                    471:   GEN idep, ep = isprincipal(bnf,x);
                    472:   /* x \prod g[i]^(-ep[i]) = factorisation of principal ideal */
                    473:   idep = isprincipalfact(bnf, gen, gneg(ep), x, nf_GENMAT | nf_GEN);
                    474:   z[1] = (long)ep;
                    475:   z[2] = idep[2]; return z;
                    476: }
                    477:
                    478: GEN
                    479: isprincipalrayall(GEN bnr, GEN x, long flag)
                    480: {
                    481:   long av=avma,i,j,c;
                    482:   GEN bnf,nf,bid,matu,vecel,ep,p1,beta,idep,y,rayclass;
                    483:   GEN divray,genray,alpha,alphaall,racunit,res,funit;
                    484:
                    485:   checkbnr(bnr);
                    486:   bnf = (GEN)bnr[1]; nf = (GEN)bnf[7];
                    487:   bid = (GEN)bnr[2];
                    488:   vecel=(GEN)bnr[3];
                    489:   matu =(GEN)bnr[4];
                    490:   rayclass=(GEN)bnr[5];
                    491:
                    492:   if (typ(x) == t_VEC && lg(x) == 3)
                    493:   { idep = (GEN)x[2]; x = (GEN)x[1]; }  /* precomputed */
                    494:   else
                    495:     idep = quick_isprincipalgen(bnf, x);
                    496:   ep  = (GEN)idep[1];
                    497:   beta= (GEN)idep[2];
                    498:   c = lg(ep);
                    499:   for (i=1; i<c; i++) /* modify beta as if gen -> vecel.gen (coprime to bid) */
                    500:     if (typ(vecel[i]) != t_INT && signe(ep[i])) /* <==> != 1 */
                    501:       beta = arch_mul(to_famat_all((GEN)vecel[i], negi((GEN)ep[i])), beta);
                    502:   p1 = gmul(matu, concatsp(ep, zideallog(nf,beta,bid)));
                    503:   divray = (GEN)rayclass[2]; c = lg(divray);
                    504:   y = cgetg(c,t_COL);
                    505:   for (i=1; i<c; i++)
                    506:     y[i] = lmodii((GEN)p1[i],(GEN)divray[i]);
                    507:   if (!(flag & nf_GEN)) return gerepileupto(av, y);
                    508:
                    509:   /* compute generator */
                    510:   if (lg(rayclass)<=3)
                    511:     err(talker,"please apply bnrinit(,,1) and not bnrinit(,,0)");
                    512:
                    513:   genray = (GEN)rayclass[3];
                    514:   /* TODO: should be using nf_GENMAT and function should return a famat */
                    515:   alphaall = isprincipalfact(bnf, genray, gneg(y), x, nf_GEN | nf_FORCE);
                    516:   if (!gcmp0((GEN)alphaall[1])) err(bugparier,"isprincipalray (bug1)");
                    517:
                    518:   res = (GEN)bnf[8];
                    519:   funit = check_units(bnf,"isprincipalrayall");
                    520:   alpha = basistoalg(nf,(GEN)alphaall[2]);
                    521:   p1 = zideallog(nf,(GEN)alphaall[2],bid);
                    522:   if (lg(p1) > 1)
                    523:   {
                    524:     GEN mat = (GEN)bnr[6], pol = (GEN)nf[1];
                    525:     p1 = gmul((GEN)mat[1],p1);
                    526:     if (!gcmp1(denom(p1))) err(bugparier,"isprincipalray (bug2)");
                    527:
                    528:     x = reducemodinvertible(p1,(GEN)mat[2]);
                    529:     racunit = gmael(res,4,2);
                    530:     p1 = powgi(gmodulcp(racunit,pol), (GEN)x[1]);
                    531:     for (j=1; j<lg(funit); j++)
                    532:       p1 = gmul(p1, powgi(gmodulcp((GEN)funit[j],pol), (GEN)x[j+1]));
                    533:     alpha = gdiv(alpha,p1);
                    534:   }
                    535:   p1 = cgetg(4,t_VEC);
                    536:   p1[1] = lcopy(y);
                    537:   p1[2] = (long)algtobasis(nf,alpha);
                    538:   p1[3] = lcopy((GEN)alphaall[3]);
                    539:   return gerepileupto(av, p1);
                    540: }
                    541:
                    542: GEN
                    543: isprincipalray(GEN bnr, GEN x)
                    544: {
                    545:   return isprincipalrayall(bnr,x,nf_REGULAR);
                    546: }
                    547:
                    548: GEN
                    549: isprincipalraygen(GEN bnr, GEN x)
                    550: {
                    551:   return isprincipalrayall(bnr,x,nf_GEN);
                    552: }
                    553:
                    554: GEN
                    555: minkowski_bound(GEN D, long N, long r2, long prec)
                    556: {
                    557:   long av = avma;
                    558:   GEN p1;
                    559:   p1 = gdiv(mpfactr(N,prec), gpowgs(stoi(N),N));
                    560:   p1 = gmul(p1, gpowgs(gdivsg(4,mppi(prec)), r2));
                    561:   p1 = gmul(p1, gsqrt(absi(D),prec));
                    562:   return gerepileupto(av, p1);
                    563: }
                    564:
                    565: /* DK = |dK| */
                    566: static long
                    567: zimmertbound(long N,long R2,GEN DK)
                    568: {
                    569:   long av = avma;
                    570:   GEN w;
                    571:
                    572:   if (N < 2) return 1;
                    573:   if (N < 21)
                    574:   {
                    575:     static double c[21][11] = {
                    576: {/*2*/  0.6931,     0.45158},
                    577: {/*3*/  1.71733859, 1.37420604},
                    578: {/*4*/  2.91799837, 2.50091538, 2.11943331},
                    579: {/*5*/  4.22701425, 3.75471588, 3.31196660},
                    580: {/*6*/  5.61209925, 5.09730381, 4.60693851, 4.14303665},
                    581: {/*7*/  7.05406203, 6.50550021, 5.97735406, 5.47145968},
                    582: {/*8*/  8.54052636, 7.96438858, 7.40555445, 6.86558259, 6.34608077},
                    583: {/*9*/ 10.0630022,  9.46382812, 8.87952524, 8.31139202, 7.76081149},
                    584: {/*10*/11.6153797, 10.9966020, 10.3907654,  9.79895170, 9.22232770, 8.66213267},
                    585: {/*11*/13.1930961, 12.5573772, 11.9330458, 11.3210061, 10.7222412, 10.1378082},
                    586: {/*12*/14.7926394, 14.1420915, 13.5016616, 12.8721114, 12.2542699, 11.6490374,
                    587:        11.0573775},
                    588: {/*13*/16.4112395, 15.7475710, 15.0929680, 14.4480777, 13.8136054, 13.1903162,
                    589:        12.5790381},
                    590: {/*14*/18.0466672, 17.3712806, 16.7040780, 16.0456127, 15.3964878, 14.7573587,
                    591:        14.1289364, 13.5119848},
                    592: {/*15*/19.6970961, 19.0111606, 18.3326615, 17.6620757, 16.9999233, 16.3467686,
                    593:        15.7032228, 15.0699480},
                    594: {/*16*/21.3610081, 20.6655103, 19.9768082, 19.2953176, 18.6214885, 17.9558093,
                    595:        17.2988108, 16.6510652, 16.0131906},
                    596:
                    597: {/*17*/23.0371259, 22.3329066, 21.6349299, 20.9435607, 20.2591899, 19.5822454,
                    598:        18.9131878, 18.2525157, 17.6007672},
                    599:
                    600: {/*18*/24.7243611, 24.0121449, 23.3056902, 22.6053167, 21.9113705, 21.2242247,
                    601:        20.5442836, 19.8719830, 19.2077941, 18.5522234},
                    602:
                    603: {/*19*/26.4217792, 25.7021950, 24.9879497, 24.2793271, 23.5766321, 22.8801952,
                    604:        22.1903709, 21.5075437, 20.8321263, 20.1645647},
                    605: {/*20*/28.1285704, 27.4021674, 26.6807314, 25.9645140, 25.2537867, 24.5488420,
                    606:        23.8499943, 23.1575823, 22.4719720, 21.7935548, 21.1227537}
                    607:     };
                    608:     w = gmul(dbltor(exp(-c[N-2][R2])), gsqrt(DK,MEDDEFAULTPREC));
                    609:   }
                    610:   else
                    611:   {
                    612:     w = minkowski_bound(DK, N, R2, MEDDEFAULTPREC);
                    613:     if (cmpis(w, 500000))
                    614:       err(warner,"large Minkowski bound: certification will be VERY long");
                    615:   }
                    616:   w = gceil(w);
                    617:   if (is_bigint(w))
                    618:     err(talker,"Minkowski bound is too large");
                    619:   avma = av; return itos(w);
                    620: }
                    621:
                    622: /* all primes up to Minkowski bound factor on factorbase ? */
                    623: static void
                    624: testprime(GEN bnf, long minkowski)
                    625: {
                    626:   ulong av = avma;
                    627:   long pp,i,nbideal,k,pmax;
                    628:   GEN f,p1,vectpp,fb,dK, nf=checknf(bnf);
                    629:   byteptr delta = diffptr;
                    630:
                    631:   if (DEBUGLEVEL>1)
                    632:     fprintferr("PHASE 1: check primes to Zimmert bound = %ld\n\n",minkowski);
                    633:   f=(GEN)nf[4]; dK=(GEN)nf[3];
                    634:   if (!gcmp1(f))
                    635:   {
                    636:     GEN different = gmael(nf,5,5);
                    637:     if (DEBUGLEVEL>1)
                    638:       fprintferr("**** Testing Different = %Z\n",different);
                    639:     p1 = isprincipalall(bnf,different,nf_FORCE);
                    640:     if (DEBUGLEVEL>1) fprintferr("     is %Z\n",p1);
                    641:   }
                    642:   fb=(GEN)bnf[5];
                    643:   p1 = gmael(fb, lg(fb)-1, 1); /* largest p in factorbase */
                    644:   pp = 0; pmax = is_bigint(p1)? VERYBIGINT: itos(p1);
                    645:   if ((ulong)minkowski > maxprime()) err(primer1);
                    646:   while (pp < minkowski)
                    647:   {
                    648:     pp += *delta++;
                    649:     if (DEBUGLEVEL>1) fprintferr("*** p = %ld\n",pp);
                    650:     vectpp=primedec(bnf,stoi(pp)); nbideal=lg(vectpp)-1;
                    651:     /* loop through all P | p if ramified, all but one otherwise */
                    652:     if (!smodis(dK,pp)) nbideal++;
                    653:     for (i=1; i<nbideal; i++)
                    654:     {
                    655:       GEN P = (GEN)vectpp[i];
                    656:       if (DEBUGLEVEL>1)
                    657:         fprintferr("  Testing P = %Z\n",P);
                    658:       if (cmpis(idealnorm(bnf,P), minkowski) < 1)
                    659:       {
                    660:        if (pp <= pmax && (k = tablesearch(fb, P, cmp_prime_ideal)))
                    661:        {
                    662:          if (DEBUGLEVEL>1) fprintferr("    #%ld in factor base\n",k);
                    663:        }
                    664:        else
                    665:        {
                    666:          p1 = isprincipal(bnf,P);
                    667:          if (DEBUGLEVEL>1) fprintferr("    is %Z\n",p1);
                    668:        }
                    669:       }
                    670:       else if (DEBUGLEVEL>1)
                    671:         fprintferr("    Norm(P) > Zimmert bound\n");
                    672:     }
                    673:     avma = av;
                    674:   }
                    675:   if (DEBUGLEVEL>1) { fprintferr("End of PHASE 1.\n\n"); flusherr(); }
                    676: }
                    677:
                    678: /* return \gamma_n^n if known, an upper bound otherwise */
                    679: static GEN
                    680: hermiteconstant(long n)
                    681: {
                    682:   GEN h,h1;
                    683:   long av;
                    684:
                    685:   switch(n)
                    686:   {
                    687:     case 1: return gun;
                    688:     case 2: h=cgetg(3,t_FRAC); h[1]=lstoi(4); h[2]=lstoi(3); return h;
                    689:     case 3: return gdeux;
                    690:     case 4: return stoi(4);
                    691:     case 5: return stoi(8);
                    692:     case 6: h=cgetg(3,t_FRAC); h[1]=lstoi(64); h[2]=lstoi(3); return h;
                    693:     case 7: return stoi(64);
                    694:     case 8: return stoi(256);
                    695:   }
                    696:   av = avma;
                    697:   h  = gpuigs(divsr(2,mppi(DEFAULTPREC)), n);
                    698:   h1 = gsqr(ggamma(gdivgs(stoi(n+4),2),DEFAULTPREC));
                    699:   return gerepileupto(av, gmul(h,h1));
                    700: }
                    701:
                    702: /* 1 if L (= nf != Q) primitive for sure, 0 if MAYBE imprimitive (may have a
                    703:  * subfield K) */
                    704: static long
                    705: isprimitive(GEN nf)
                    706: {
                    707:   long N,p,i,l,ep;
                    708:   GEN d,fa;
                    709:
                    710:   N = degpol(nf[1]); fa = (GEN)factor(stoi(N))[1]; /* primes | N */
                    711:   p = itos((GEN)fa[1]); if (p == N) return 1; /* prime degree */
                    712:
                    713:   /* N = [L:Q] = product of primes >= p, same is true for [L:K]
                    714:    * d_L = t d_K^[L:K] --> check that some q^p divides d_L */
                    715:   d = absi((GEN)nf[3]);
                    716:   fa = (GEN)auxdecomp(d,0)[2]; /* list of v_q(d_L). Don't check large primes */
                    717:   if (mod2(d)) i = 1;
                    718:   else
                    719:   { /* q = 2 */
                    720:     ep = itos((GEN)fa[1]);
                    721:     if ((ep>>1) >= p) return 0; /* 2 | d_K ==> 4 | d_K */
                    722:     i = 2;
                    723:   }
                    724:   l = lg(fa);
                    725:   for ( ; i < l; i++)
                    726:   {
                    727:     ep = itos((GEN)fa[i]);
                    728:     if (ep >= p) return 0;
                    729:   }
                    730:   return 1;
                    731: }
                    732:
                    733: static GEN
                    734: regulatorbound(GEN bnf)
                    735: {
                    736:   long N,R1,R2,R;
                    737:   GEN nf,dKa,bound,p1,c1;
                    738:
                    739:   nf = (GEN)bnf[7]; N = degpol(nf[1]);
                    740:   bound = dbltor(0.2);
                    741:   if (!isprimitive(nf))
                    742:   {
                    743:     if (DEBUGLEVEL>1) fprintferr("Default bound for regulator: 0.2\n");
                    744:     return bound;
                    745:   }
                    746:   dKa = absi((GEN)nf[3]);
                    747:   R1 = itos(gmael(nf,2,1));
                    748:   R2 = itos(gmael(nf,2,2)); R = R1+R2-1;
                    749:   if (!R2 && N<12) c1 = gpuigs(stoi(4),N>>1); else c1 = gpuigs(stoi(N),N);
                    750:   if (cmpii(dKa,c1) <= 0)
                    751:   {
                    752:     if (DEBUGLEVEL>1) fprintferr("Default bound for regulator: 0.2\n");
                    753:     return bound;
                    754:   }
                    755:   p1 = gsqr(glog(gdiv(dKa,c1),DEFAULTPREC));
                    756:   p1 = gdivgs(gmul2n(gpuigs(gdivgs(gmulgs(p1,3),N*(N*N-1)-6*R2),R),R2),N);
                    757:   p1 = gsqrt(gdiv(p1, hermiteconstant(R)), DEFAULTPREC);
                    758:   if (gcmp(p1,bound) > 0) bound = p1;
                    759:   if (DEBUGLEVEL>1) fprintferr("Mahler bound for regulator: %Z\n",p1);
                    760:   return bound;
                    761: }
                    762:
                    763: /* x given by its embeddings */
                    764: GEN
                    765: norm_by_embed(long r1, GEN x)
                    766: {
                    767:   long i, ru = lg(x)-1;
                    768:   GEN p = (GEN)x[ru];
                    769:   if (r1 == ru)
                    770:   {
                    771:     for (i=ru-1; i>0; i--) p = gmul(p, (GEN)x[i]);
                    772:     return p;
                    773:   }
                    774:   p = gnorm(p);
                    775:   for (i=ru-1; i>r1; i--) p = gmul(p, gnorm((GEN)x[i]));
                    776:   for (      ; i>0 ; i--) p = gmul(p, (GEN)x[i]);
                    777:   return p;
                    778: }
                    779:
                    780: static int
                    781: is_unit(GEN M, long r1, GEN x)
                    782: {
                    783:   long av = avma;
                    784:   GEN Nx = ground( norm_by_embed(r1, gmul_mat_smallvec(M,x)) );
                    785:   int ok = is_pm1(Nx);
                    786:   avma = av; return ok;
                    787: }
                    788:
                    789: #define NBMAX 5000
                    790: /* FIXME: should use smallvectors */
                    791: static GEN
                    792: minimforunits(GEN nf, long BORNE, long stockmax)
                    793: {
                    794:   const long prec = MEDDEFAULTPREC;
                    795:   long av = avma,n,i,j,k,s,norme,normax,*x,cmpt,r1;
                    796:   GEN u,r,S,a,M,p1;
                    797:   double p;
                    798:   double **q,*v,*y,*z;
                    799:   double eps=0.000001, BOUND = BORNE + eps;
                    800:
                    801:   if (DEBUGLEVEL>=2)
                    802:   {
                    803:     fprintferr("Searching minimum of T2-form on units:\n");
                    804:     if (DEBUGLEVEL>2) fprintferr("   BOUND = %ld\n",BOUND);
                    805:     flusherr();
                    806:   }
                    807:   r1 = nf_get_r1(nf);
                    808:   a = gmael(nf,5,3); n = lg(a);
                    809:   minim_alloc(n, &q, &x, &y, &z, &v);
                    810:   n--;
                    811:   u = lllgram(a,prec);
                    812:   M = gmul(gmael(nf,5,1), u); /* embeddings of T2-reduced basis */
                    813:   M = gprec_w(M, prec);
                    814:   a = gmul(qf_base_change(a,u,1), realun(prec));
                    815:   r = sqred1(a);
                    816:   for (j=1; j<=n; j++)
                    817:   {
                    818:     v[j] = rtodbl(gcoeff(r,j,j));
                    819:     for (i=1; i<j; i++) q[i][j] = rtodbl(gcoeff(r,i,j));
                    820:   }
                    821:   normax=0;
                    822:   S = cgetg(stockmax+1,t_MAT);
                    823:   s=0; k=n; cmpt=0; y[n]=z[n]=0;
                    824:   x[n]=(long)(sqrt(BOUND/v[n]));
                    825:
                    826:   for(;;)
                    827:   {
                    828:     do
                    829:     {
                    830:       if (k>1)
                    831:       {
                    832:         long l = k-1;
                    833:        z[l] = 0;
                    834:        for (j=k; j<=n; j++) z[l] = z[l]+q[l][j]*x[j];
                    835:        p = x[k]+z[k];
                    836:        y[l] = y[k]+p*p*v[k];
                    837:        x[l] = (long)floor(sqrt((BOUND-y[l])/v[l])-z[l]);
                    838:         k = l;
                    839:       }
                    840:       for(;;)
                    841:       {
                    842:         p = x[k]+z[k];
                    843:         if (y[k] + p*p*v[k] <= BOUND) break;
                    844:        k++; x[k]--;
                    845:       }
                    846:     }
                    847:     while (k>1);
                    848:     if (!x[1] && y[1]<=eps) break;
                    849:     if (++cmpt > NBMAX) { av=avma; return NULL; }
                    850:
                    851:     if (DEBUGLEVEL>8){ fprintferr("."); flusherr(); }
                    852:     p = x[1]+z[1]; norme = (long)(y[1] + p*p*v[1] + eps);
                    853:     if (norme > normax) normax = norme;
                    854:     if (is_unit(M,r1, x))
                    855:     {
                    856:       if (DEBUGLEVEL>=2) { fprintferr("*"); flusherr(); }
                    857:       cmpt = 0;
                    858:       if (++s <= stockmax)
                    859:       {
                    860:        p1 = cgetg(n+1,t_COL);
                    861:        for (i=1; i<=n; i++) p1[i]=lstoi(x[i]);
                    862:        S[s] = lmul(u,p1);
                    863:       }
                    864:     }
                    865:     x[k]--;
                    866:   }
                    867:   if (DEBUGLEVEL>=2){ fprintferr("\n"); flusherr(); }
                    868:   k = (s<stockmax)? s:stockmax; setlg(S,k+1);
                    869:   S = gerepilecopy(av, S);
                    870:   u = cgetg(4,t_VEC);
                    871:   u[1] = lstoi(s<<1);
                    872:   u[2] = lstoi(normax);
                    873:   u[3] = (long)S; return u;
                    874: }
                    875:
                    876: #undef NBMAX
                    877: static int
                    878: is_zero(GEN x, long bitprec) { return (gexpo(x) < -bitprec); }
                    879:
                    880: static int
                    881: is_complex(GEN x, long bitprec) { return (!is_zero(gimag(x), bitprec)); }
                    882:
                    883: static GEN
                    884: compute_M0(GEN M_star,long N)
                    885: {
                    886:   long m1,m2,n1,n2,n3,k,kk,lr,lr1,lr2,i,j,l,vx,vy,vz,vM,prec;
                    887:   GEN pol,p1,p2,p3,p4,p5,p6,p7,p8,p9,u,v,w,r,r1,r2,M0,M0_pro,S,P,M;
                    888:   GEN f1,f2,f3,g1,g2,g3,pg1,pg2,pg3,pf1,pf2,pf3,X,Y,Z;
                    889:   long bitprec = 24, PREC = gprecision(M_star);
                    890:
                    891:   if (N==2) return gmul2n(gsqr(gach(gmul2n(M_star,-1),PREC)), -1);
                    892:   vM = fetch_var(); M = polx[vM];
                    893:   vz = fetch_var(); Z = polx[vz];
                    894:   vy = fetch_var(); Y = polx[vy];
                    895:   vx = fetch_var(); X = polx[vx];
                    896:
                    897:   PREC = PREC>>1; if (!PREC) PREC = DEFAULTPREC;
                    898:   M0 = NULL; m1 = N/3;
                    899:   for (n1=1; n1<=m1; n1++)
                    900:   {
                    901:     m2 = (N-n1)>>1;
                    902:     for (n2=n1; n2<=m2; n2++)
                    903:     {
                    904:       long av = avma; n3=N-n1-n2; prec=PREC;
                    905:       if (n1==n2 && n1==n3) /* n1 = n2 = n3 = m1 = N/3 */
                    906:       {
                    907:        p1=gdivgs(M_star,m1);
                    908:         p2=gaddsg(1,p1);
                    909:         p3=gsubgs(p1,3);
                    910:        p4=gsqrt(gmul(p2,p3),prec);
                    911:         p5=gsubgs(p1,1);
                    912:        u=gun;
                    913:         v=gmul2n(gadd(p5,p4),-1);
                    914:         w=gmul2n(gsub(p5,p4),-1);
                    915:        M0_pro=gmul2n(gmulsg(m1,gadd(gsqr(glog(v,prec)),gsqr(glog(w,prec)))),-2);
                    916:        if (DEBUGLEVEL>2)
                    917:        {
                    918:          fprintferr("[ %ld, %ld, %ld ]: %Z\n",n1,n2,n3,gprec_w(M0_pro,3));
                    919:          flusherr();
                    920:        }
                    921:        if (!M0 || gcmp(M0_pro,M0)<0) M0 = M0_pro;
                    922:       }
                    923:       else if (n1==n2 || n2==n3)
                    924:       { /* n3 > N/3 >= n1 */
                    925:        k = n2; kk = N-2*k;
                    926:        p2=gsub(M_star,gmulgs(X,k));
                    927:        p3=gmul(gpuigs(stoi(kk),kk),gpuigs(gsubgs(gmul(M_star,p2),kk*kk),k));
                    928:        pol=gsub(p3,gmul(gmul(gpuigs(stoi(k),k),gpuigs(X,k)),gpuigs(p2,N-k)));
                    929:        prec=gprecision(pol); if (!prec) prec = MEDDEFAULTPREC;
                    930:        r=roots(pol,prec); lr = lg(r);
                    931:        for (i=1; i<lr; i++)
                    932:        {
                    933:          if (is_complex((GEN)r[i], bitprec) ||
                    934:              signe(S = greal((GEN)r[i])) <= 0) continue;
                    935:
                    936:           p4=gsub(M_star,gmulsg(k,S));
                    937:           P=gdiv(gmul(gmulsg(k,S),p4),gsubgs(gmul(M_star,p4),kk*kk));
                    938:           p5=gsub(gsqr(S),gmul2n(P,2));
                    939:           if (gsigne(p5) < 0) continue;
                    940:
                    941:           p6=gsqrt(p5,prec);
                    942:           v=gmul2n(gsub(S,p6),-1);
                    943:           if (gsigne(v) <= 0) continue;
                    944:
                    945:           u=gmul2n(gadd(S,p6),-1);
                    946:           w=gpui(P,gdivgs(stoi(-k),kk),prec);
                    947:           p6=gmulsg(k,gadd(gsqr(glog(u,prec)),gsqr(glog(v,prec))));
                    948:           M0_pro=gmul2n(gadd(p6,gmulsg(kk,gsqr(glog(w,prec)))),-2);
                    949:           if (DEBUGLEVEL>2)
                    950:           {
                    951:             fprintferr("[ %ld, %ld, %ld ]: %Z\n",n1,n2,n3,gprec_w(M0_pro,3));
                    952:             flusherr();
                    953:           }
                    954:           if (!M0 || gcmp(M0_pro,M0)<0) M0 = M0_pro;
                    955:        }
                    956:       }
                    957:       else
                    958:       {
                    959:        f1 = gsub(gadd(gmulsg(n1,X),gadd(gmulsg(n2,Y),gmulsg(n3,Z))), M);
                    960:        f2 =         gmulsg(n1,gmul(Y,Z));
                    961:        f2 = gadd(f2,gmulsg(n2,gmul(X,Z)));
                    962:        f2 = gadd(f2,gmulsg(n3,gmul(X,Y)));
                    963:        f2 = gsub(f2,gmul(M,gmul(X,gmul(Y,Z))));
                    964:        f3 = gsub(gmul(gpuigs(X,n1),gmul(gpuigs(Y,n2),gpuigs(Z,n3))), gun);
                    965:         /* f1 = n1 X + n2 Y + n3 Z - M */
                    966:         /* f2 = n1 YZ + n2 XZ + n3 XY */
                    967:         /* f3 = X^n1 Y^n2 Z^n3 - 1*/
                    968:        g1=subres(f1,f2); g1=gdiv(g1,content(g1));
                    969:        g2=subres(f1,f3); g2=gdiv(g2,content(g2));
                    970:        g3=subres(g1,g2); g3=gdiv(g3,content(g3));
                    971:        pf1=gsubst(f1,vM,M_star); pg1=gsubst(g1,vM,M_star);
                    972:        pf2=gsubst(f2,vM,M_star); pg2=gsubst(g2,vM,M_star);
                    973:        pf3=gsubst(f3,vM,M_star); pg3=gsubst(g3,vM,M_star);
                    974:        prec=gprecision(pg3); if (!prec) prec = MEDDEFAULTPREC;
                    975:        r=roots(pg3,prec); lr = lg(r);
                    976:        for (i=1; i<lr; i++)
                    977:        {
                    978:          if (is_complex((GEN)r[i], bitprec) ||
                    979:              signe(w = greal((GEN)r[i])) <= 0) continue;
                    980:           p1=gsubst(pg1,vz,w);
                    981:           p2=gsubst(pg2,vz,w);
                    982:           p3=gsubst(pf1,vz,w);
                    983:           p4=gsubst(pf2,vz,w);
                    984:           p5=gsubst(pf3,vz,w);
                    985:           prec=gprecision(p1); if (!prec) prec = MEDDEFAULTPREC;
                    986:           r1 = roots(p1,prec); lr1 = lg(r1);
                    987:           for (j=1; j<lr1; j++)
                    988:           {
                    989:             if (is_complex((GEN)r1[j], bitprec)
                    990:              || signe(v = greal((GEN)r1[j])) <= 0
                    991:              || !is_zero(gsubst(p2,vy,v), bitprec)) continue;
                    992:
                    993:             p7=gsubst(p3,vy,v);
                    994:             p8=gsubst(p4,vy,v);
                    995:             p9=gsubst(p5,vy,v);
                    996:             prec=gprecision(p7); if (!prec) prec = MEDDEFAULTPREC;
                    997:             r2 = roots(p7,prec); lr2 = lg(r2);
                    998:             for (l=1; l<lr2; l++)
                    999:             {
                   1000:               if (is_complex((GEN)r2[l], bitprec)
                   1001:                || signe(u = greal((GEN)r2[l])) <= 0
                   1002:                || !is_zero(gsubst(p8,vx,u), bitprec)
                   1003:                || !is_zero(gsubst(p9,vx,u), bitprec)) continue;
                   1004:
                   1005:               M0_pro =              gmulsg(n1,gsqr(mplog(u)));
                   1006:               M0_pro = gadd(M0_pro, gmulsg(n2,gsqr(mplog(v))));
                   1007:               M0_pro = gadd(M0_pro, gmulsg(n3,gsqr(mplog(w))));
                   1008:               M0_pro = gmul2n(M0_pro,-2);
                   1009:               if (DEBUGLEVEL>2)
                   1010:               {
                   1011:                fprintferr("[ %ld, %ld, %ld ]: %Z\n",n1,n2,n3,gprec_w(M0_pro,3));
                   1012:                flusherr();
                   1013:               }
                   1014:               if (!M0 || gcmp(M0_pro,M0) < 0) M0 = M0_pro;
                   1015:             }
                   1016:           }
                   1017:        }
                   1018:       }
                   1019:       if (!M0) avma = av; else M0 = gerepilecopy(av, M0);
                   1020:     }
                   1021:   }
                   1022:   for (i=1;i<=4;i++) delete_var();
                   1023:   return M0? M0: gzero;
                   1024: }
                   1025:
                   1026: static GEN
                   1027: lowerboundforregulator_i(GEN bnf)
                   1028: {
                   1029:   long N,R1,R2,RU,i,nbrootsofone,nbmin;
                   1030:   GEN rootsofone,nf,M0,M,m,col,T2,bound,minunit,newminunit;
                   1031:   GEN vecminim,colalg,p1,pol,y;
                   1032:   GEN units = check_units(bnf,"bnfcertify");
                   1033:
                   1034:   rootsofone=gmael(bnf,8,4); nbrootsofone=itos((GEN)rootsofone[1]);
                   1035:   nf=(GEN)bnf[7]; T2=gmael(nf,5,3); N=degpol(nf[1]);
                   1036:   R1=itos(gmael(nf,2,1)); R2=itos(gmael(nf,2,2)); RU=R1+R2-1;
                   1037:   if (RU==0) return gun;
                   1038:
                   1039:   units=algtobasis(bnf,units); minunit=qfeval(T2,(GEN)units[1]);
                   1040:   for (i=2; i<=RU; i++)
                   1041:   {
                   1042:     newminunit=qfeval(T2,(GEN)units[i]);
                   1043:     if (gcmp(newminunit,minunit)<0) minunit=newminunit;
                   1044:   }
                   1045:   if (gcmpgs(minunit,1000000000)>0) return NULL;
                   1046:
                   1047:   vecminim = minimforunits(nf,itos(gceil(minunit)),10000);
                   1048:   if (!vecminim) return NULL;
                   1049:   m=(GEN)vecminim[3]; nbmin=lg(m)-1;
                   1050:   if (nbmin==10000) return NULL;
                   1051:   bound=gaddgs(minunit,1);
                   1052:   for (i=1; i<=nbmin; i++)
                   1053:   {
                   1054:     col=(GEN)m[i]; colalg=basistoalg(nf,col);
                   1055:     if (!gcmp1(lift_intern(gpuigs(colalg,nbrootsofone))))
                   1056:     {
                   1057:       newminunit=qfeval(T2,col);
                   1058:       if (gcmp(newminunit,bound)<0) bound=newminunit;
                   1059:     }
                   1060:   }
                   1061:   if (gcmp(bound,minunit)>0) err(talker,"bug in lowerboundforregulator");
                   1062:   if (DEBUGLEVEL>1)
                   1063:   {
                   1064:     fprintferr("M* = %Z\n",gprec_w(bound,3));
                   1065:     if (DEBUGLEVEL>2)
                   1066:     {
                   1067:       p1=polx[0]; pol=gaddgs(gsub(gpuigs(p1,N),gmul(bound,p1)),N-1);
                   1068:       p1 = roots(pol,DEFAULTPREC);
                   1069:       if (N&1) y=greal((GEN)p1[3]); else y=greal((GEN)p1[2]);
                   1070:       M0 = gmul2n(gmulsg(N*(N-1),gsqr(glog(y,DEFAULTPREC))),-2);
                   1071:       fprintferr("pol = %Z\n",pol);
                   1072:       fprintferr("old method: y = %Z, M0 = %Z\n",y,gprec_w(M0,3));
                   1073:     }
                   1074:     flusherr();
                   1075:   }
                   1076:   M0 = compute_M0(bound,N);
                   1077:   if (DEBUGLEVEL>1) { fprintferr("M0 = %Z\n",gprec_w(M0,3)); flusherr(); }
                   1078:   M = gmul2n(gdivgs(gdiv(gpuigs(M0,RU),hermiteconstant(RU)),N),R2);
                   1079:   if (gcmp(M,dbltor(0.04))<0) return NULL;
                   1080:   M = gsqrt(M,DEFAULTPREC);
                   1081:   if (DEBUGLEVEL>1)
                   1082:   {
                   1083:     fprintferr("(lower bound for regulator) M = %Z\n",gprec_w(M,3));
                   1084:     flusherr();
                   1085:   }
                   1086:   return M;
                   1087: }
                   1088:
                   1089: static GEN
                   1090: lowerboundforregulator(GEN bnf)
                   1091: {
                   1092:   long av = avma;
                   1093:   GEN x = lowerboundforregulator_i(bnf);
                   1094:   if (!x) { avma = av; x = regulatorbound(bnf); }
                   1095:   return x;
                   1096: }
                   1097:
                   1098: extern GEN to_Fp_simple(GEN x, GEN prh);
                   1099: extern GEN Fp_PHlog(GEN a, GEN g, GEN p, GEN ord);
                   1100:
                   1101: /* Compute a square matrix of rank length(beta) associated to a family
                   1102:  * (P_i), 1<=i<=length(beta), of primes s.t. N(P_i) = 1 mod pp, and
                   1103:  * (P_i,beta[j]) = 1 for all i,j */
                   1104: static void
                   1105: primecertify(GEN bnf,GEN beta,long pp,GEN big)
                   1106: {
                   1107:   long i,j,qq,nbcol,lb,nbqq,ra,N;
                   1108:   GEN nf,mat,mat1,qgen,decqq,newcol,Qh,Q,g,ord;
                   1109:
                   1110:   ord = NULL; /* gcc -Wall */
                   1111:   nbcol = 0; nf = (GEN)bnf[7]; N = degpol(nf[1]);
                   1112:   lb = lg(beta)-1; mat = cgetg(1,t_MAT); qq = 1;
                   1113:   for(;;)
                   1114:   {
                   1115:     qq += 2*pp; qgen = stoi(qq);
                   1116:     if (smodis(big,qq)==0 || !isprime(qgen)) continue;
                   1117:
                   1118:     decqq = primedec(bnf,qgen); nbqq = lg(decqq)-1;
                   1119:     g = NULL;
                   1120:     for (i=1; i<=nbqq; i++)
                   1121:     {
                   1122:       Q = (GEN)decqq[i]; if (!gcmp1((GEN)Q[4])) break;
                   1123:       /* Q has degree 1 */
                   1124:       if (!g)
                   1125:       {
                   1126:         g = lift_intern(gener(qgen)); /* primitive root */
                   1127:         ord = decomp(stoi(qq-1));
                   1128:       }
                   1129:       Qh = prime_to_ideal(nf,Q);
                   1130:       newcol = cgetg(lb+1,t_COL);
                   1131:       for (j=1; j<=lb; j++)
                   1132:       {
                   1133:         GEN t = to_Fp_simple((GEN)beta[j], Qh);
                   1134:         newcol[j] = (long)Fp_PHlog(t,g,qgen,ord);
                   1135:       }
                   1136:       if (DEBUGLEVEL>3)
                   1137:       {
                   1138:         if (i==1) fprintferr("       generator of (Zk/Q)^*: %Z\n", g);
                   1139:         fprintferr("       prime ideal Q: %Z\n",Q);
                   1140:         fprintferr("       column #%ld of the matrix log(b_j/Q): %Z\n",
                   1141:                    nbcol, newcol);
                   1142:       }
                   1143:       mat1 = concatsp(mat,newcol); ra = rank(mat1);
                   1144:       if (ra==nbcol) continue;
                   1145:
                   1146:       if (DEBUGLEVEL>2) fprintferr("       new rank: %ld\n\n",ra);
                   1147:       if (++nbcol == lb) return;
                   1148:       mat = mat1;
                   1149:     }
                   1150:   }
                   1151: }
                   1152:
                   1153: static void
                   1154: check_prime(long p, GEN bnf, GEN cyc, GEN cycgen, GEN fu, GEN mu, GEN big)
                   1155: {
                   1156:   ulong av = avma;
                   1157:   long i,b, lc = lg(cyc), w = itos((GEN)mu[1]), lf = lg(fu);
                   1158:   GEN beta = cgetg(lf+lc, t_VEC);
                   1159:
                   1160:   if (DEBUGLEVEL>1) fprintferr("  *** testing p = %ld\n",p);
                   1161:   for (b=1; b<lc; b++)
                   1162:   {
                   1163:     if (smodis((GEN)cyc[b], p)) break; /* p \nmod cyc[b] */
                   1164:     if (b==1 && DEBUGLEVEL>2) fprintferr("     p divides h(K)\n");
                   1165:     beta[b] = cycgen[b];
                   1166:   }
                   1167:   if (w % p == 0)
                   1168:   {
                   1169:     if (DEBUGLEVEL>2) fprintferr("     p divides w(K)\n");
                   1170:     beta[b++] = mu[2];
                   1171:   }
                   1172:   for (i=1; i<lf; i++) beta[b++] = fu[i];
                   1173:   setlg(beta, b); /* beta = [cycgen[i] if p|cyc[i], tu if p|w, fu] */
                   1174:   if (DEBUGLEVEL>3) {fprintferr("     Beta list = %Z\n",beta); flusherr();}
                   1175:   primecertify(bnf,beta,p,big); avma = av;
                   1176: }
                   1177:
                   1178: long
                   1179: certifybuchall(GEN bnf)
                   1180: {
                   1181:   ulong av = avma;
                   1182:   long nbgen,i,j,p,N,R1,R2,R,bound;
                   1183:   GEN big,nf,reg,rootsofone,funits,gen,p1,gbound,cycgen,cyc;
                   1184:   byteptr delta = diffptr;
                   1185:
                   1186:   bnf = checkbnf(bnf); nf = (GEN)bnf[7];
                   1187:   N=degpol(nf[1]); if (N==1) return 1;
                   1188:   R1=itos(gmael(nf,2,1)); R2=itos(gmael(nf,2,2)); R=R1+R2-1;
                   1189:   funits = check_units(bnf,"bnfcertify");
                   1190:   testprime(bnf, zimmertbound(N,R2,absi((GEN)nf[3])));
                   1191:   reg = gmael(bnf,8,2);
                   1192:   cyc = gmael3(bnf,8,1,2); nbgen = lg(cyc)-1;
                   1193:   gen = gmael3(bnf,8,1,3); rootsofone = gmael(bnf,8,4);
                   1194:   gbound = ground(gdiv(reg,lowerboundforregulator(bnf)));
                   1195:   if (is_bigint(gbound))
                   1196:     err(talker,"sorry, too many primes to check");
                   1197:
                   1198:   bound = itos(gbound); if ((ulong)bound > maxprime()) err(primer1);
                   1199:   if (DEBUGLEVEL>1)
                   1200:   {
                   1201:     fprintferr("\nPHASE 2: are all primes good ?\n\n");
                   1202:     fprintferr("  Testing primes <= B (= %ld)\n\n",bound); flusherr();
                   1203:   }
                   1204:   cycgen = check_and_build_cycgen(bnf);
                   1205:   for (big=gun,i=1; i<=nbgen; i++)
                   1206:     big = mpppcm(big, gcoeff(gen[i],1,1));
                   1207:   for (i=1; i<=nbgen; i++)
                   1208:   {
                   1209:     p1 = (GEN)cycgen[i];
                   1210:     if (typ(p1) == t_MAT)
                   1211:     {
                   1212:       GEN h, g = (GEN)p1[1];
                   1213:       for (j=1; j<lg(g); j++)
                   1214:       {
                   1215:         h = idealhermite(nf, (GEN)g[j]);
                   1216:         big = mpppcm(big, gcoeff(h,1,1));
                   1217:       }
                   1218:     }
                   1219:   } /* p | big <--> p | some cycgen[i]  */
                   1220:
                   1221:   funits = dummycopy(funits);
                   1222:   for (i=1; i<lg(funits); i++)
                   1223:     funits[i] = (long)algtobasis(nf, (GEN)funits[i]);
                   1224:   rootsofone = dummycopy(rootsofone);
                   1225:   rootsofone[2] = (long)algtobasis(nf, (GEN)rootsofone[2]);
                   1226:
                   1227:   for (p = *delta++; p <= bound; p += *delta++)
                   1228:     check_prime(p,bnf,cyc,cycgen,funits,rootsofone,big);
                   1229:
                   1230:   if (nbgen)
                   1231:   {
                   1232:     GEN f = factor((GEN)cyc[1]), f1 = (GEN)f[1];
                   1233:     long nbf1 = lg(f1);
                   1234:     if (DEBUGLEVEL>1) { fprintferr("  Testing primes | h(K)\n\n"); flusherr(); }
                   1235:     for (i=1; i<nbf1; i++)
                   1236:     {
                   1237:       p = itos((GEN)f1[i]);
                   1238:       if (p > bound) check_prime(p,bnf,cyc,cycgen,funits,rootsofone,big);
                   1239:     }
                   1240:   }
                   1241:   avma=av; return 1;
                   1242: }
                   1243:
                   1244: /*******************************************************************/
                   1245: /*                                                                 */
                   1246: /*        RAY CLASS FIELDS: CONDUCTORS AND DISCRIMINANTS           */
                   1247: /*                                                                 */
                   1248: /*******************************************************************/
                   1249:
                   1250: /* s: <gen> = Cl_f --> Cl_n --> 0, H subgroup of Cl_f (generators given as
                   1251:  * HNF on [gen]). Return subgroup s(H) in Cl_n (associated to bnr) */
                   1252: static GEN
                   1253: imageofgroup0(GEN gen,GEN bnr,GEN H)
                   1254: {
                   1255:   long j,l;
                   1256:   GEN E,Delta = diagonal(gmael(bnr,5,2)); /* SNF structure of Cl_n */
                   1257:
                   1258:   if (!H || gcmp0(H)) return Delta;
                   1259:
                   1260:   l=lg(gen); E=cgetg(l,t_MAT);
                   1261:   for (j=1; j<l; j++) /* compute s(gen) */
                   1262:     E[j] = (long)isprincipalray(bnr,(GEN)gen[j]);
                   1263:   return hnf(concatsp(gmul(E,H), Delta)); /* s(H) in Cl_n */
                   1264: }
                   1265:
                   1266: static GEN
                   1267: imageofgroup(GEN gen,GEN bnr,GEN H)
                   1268: {
                   1269:   ulong av = avma;
                   1270:   return gerepileupto(av,imageofgroup0(gen,bnr,H));
                   1271: }
                   1272:
                   1273: /* see imageofgroup0, return [Cl_f : s(H)], H given on gen */
                   1274: static GEN
                   1275: orderofquotient(GEN bnf, GEN f, GEN H, GEN gen)
                   1276: {
                   1277:   GEN bnr;
                   1278:   if (!H) return rayclassno(bnf,f);
                   1279:   bnr = buchrayall(bnf,f,nf_INIT);
                   1280:   return dethnf_i(imageofgroup0(gen,bnr,H));
                   1281: }
                   1282:
                   1283: static GEN
                   1284: args_to_bnr(GEN arg0, GEN arg1, GEN arg2, GEN *subgroup)
                   1285: {
                   1286:   GEN bnr,bnf;
                   1287:
                   1288:   if (typ(arg0)!=t_VEC)
                   1289:     err(talker,"neither bnf nor bnr in conductor or discray");
                   1290:   if (!arg1) arg1 = gzero;
                   1291:   if (!arg2) arg2 = gzero;
                   1292:
                   1293:   switch(lg(arg0))
                   1294:   {
                   1295:     case 7:  /* bnr */
                   1296:       bnr=arg0; (void)checkbnf((GEN)bnr[1]);
                   1297:       *subgroup=arg1; break;
                   1298:
                   1299:     case 11: /* bnf */
                   1300:       bnf = checkbnf(arg0);
                   1301:       bnr=buchrayall(bnf,arg1,nf_INIT | nf_GEN);
                   1302:       *subgroup=arg2; break;
                   1303:
                   1304:     default: err(talker,"neither bnf nor bnr in conductor or discray");
                   1305:       return NULL; /* not reached */
                   1306:   }
                   1307:   if (!gcmp0(*subgroup))
                   1308:   {
                   1309:     long tx=typ(*subgroup);
                   1310:     if (!is_matvec_t(tx))
                   1311:       err(talker,"bad subgroup in conductor or discray");
                   1312:   }
                   1313:   return bnr;
                   1314: }
                   1315:
                   1316: GEN
                   1317: bnrconductor(GEN arg0,GEN arg1,GEN arg2,long all)
                   1318: {
                   1319:   GEN sub=arg1, bnr=args_to_bnr(arg0,arg1,arg2,&sub);
                   1320:   return conductor(bnr,sub,all);
                   1321: }
                   1322:
                   1323: long
                   1324: bnrisconductor(GEN arg0,GEN arg1,GEN arg2)
                   1325: {
                   1326:   GEN sub=arg1, bnr=args_to_bnr(arg0,arg1,arg2,&sub);
                   1327:   return itos(conductor(bnr,sub,-1));
                   1328: }
                   1329:
                   1330: /* special for isprincipalrayall */
                   1331: static GEN
                   1332: getgen(GEN bnf, GEN gen)
                   1333: {
                   1334:   long i,l = lg(gen);
                   1335:   GEN p1, g = cgetg(l, t_VEC);
                   1336:   for (i=1; i<l; i++)
                   1337:   {
                   1338:     p1 = cgetg(3,t_VEC); g[i] = (long)p1;
                   1339:     p1[1] = (long)gen[i];
                   1340:     p1[2] = (long)quick_isprincipalgen(bnf, (GEN)gen[i]);
                   1341:   }
                   1342:   return g;
                   1343: }
                   1344:
                   1345: /* Given a number field bnf=bnr[1], a ray class group structure bnr (from
                   1346:  * buchrayinit), and a subgroup H (HNF form) of the ray class group, compute
                   1347:  * the conductor of H (copy of discrayrelall) if all=0. If all > 0, compute
                   1348:  * furthermore the corresponding H' and output
                   1349:  * if all = 1: [[ideal,arch],[hm,cyc,gen],H']
                   1350:  * if all = 2: [[ideal,arch],newbnr,H']
                   1351:  * if all < 0, answer only 1 is module is the conductor, 0 otherwise. */
                   1352: GEN
                   1353: conductor(GEN bnr, GEN H, long all)
                   1354: {
                   1355:   ulong av = avma;
                   1356:   long r1,j,k,ep;
                   1357:   GEN bnf,nf,gen,bid,ideal,arch,p1,clhray,clhss,fa,arch2,bnr2,P,ex,mod;
                   1358:
                   1359:   checkbnrgen(bnr);
                   1360:   bnf = (GEN)bnr[1];
                   1361:   bid = (GEN)bnr[2];
                   1362:   clhray = gmael(bnr,5,1); gen = gmael(bnr,5,3);
                   1363:   nf = (GEN)bnf[7]; r1 = nf_get_r1(nf);
                   1364:   ideal= gmael(bid,1,1);
                   1365:   arch = gmael(bid,1,2);
                   1366:   if (gcmp0(H)) H = NULL;
                   1367:   else
                   1368:   {
                   1369:     p1 = gauss(H, diagonal(gmael(bnr,5,2)));
                   1370:     if (!gcmp1(denom(p1))) err(talker,"incorrect subgroup in conductor");
                   1371:     p1 = absi(det(H));
                   1372:     if (egalii(p1, clhray)) H = NULL; else clhray = p1;
                   1373:   }
                   1374:   /* H = NULL --> trivial subgroup, else precompute isprincipal(gen) */
                   1375:   if (H || all > 0) gen = getgen(bnf, gen);
                   1376:
                   1377:   fa = (GEN)bid[3];
                   1378:   P  = (GEN)fa[1];
                   1379:   ex = (GEN)fa[2];
                   1380:   mod = cgetg(3,t_VEC); mod[2] = (long)arch;
                   1381:   for (k=1; k<lg(ex); k++)
                   1382:   {
                   1383:     GEN pr = (GEN)P[k];
                   1384:     ep = (all>=0)? itos((GEN)ex[k]): 1;
                   1385:     for (j=1; j<=ep; j++)
                   1386:     {
                   1387:       mod[1] = (long)idealdivexact(nf,ideal,pr);
                   1388:       clhss = orderofquotient(bnf,mod,H,gen);
                   1389:       if (!egalii(clhss,clhray)) break;
                   1390:       if (all < 0) { avma = av; return gzero; }
                   1391:       ideal = (GEN)mod[1];
                   1392:     }
                   1393:   }
                   1394:   mod[1] = (long)ideal; arch2 = dummycopy(arch);
                   1395:   mod[2] = (long)arch2;
                   1396:   for (k=1; k<=r1; k++)
                   1397:     if (signe(arch[k]))
                   1398:     {
                   1399:       arch2[k] = zero;
                   1400:       clhss = orderofquotient(bnf,mod,H,gen);
                   1401:       if (!egalii(clhss,clhray)) { arch2[k] = un; continue; }
                   1402:       if (all < 0) { avma = av; return gzero; }
                   1403:     }
                   1404:   if (all < 0) { avma = av; return gun; }
                   1405:   if (!all) return gerepilecopy(av, mod);
                   1406:
                   1407:   bnr2 = buchrayall(bnf,mod,nf_INIT | nf_GEN);
                   1408:   p1 = cgetg(4,t_VEC);
                   1409:   p1[3] = (long)imageofgroup(gen,bnr2,H);
                   1410:   if (all==1) bnr2 = (GEN)bnr2[5];
                   1411:   p1[2] = lcopy(bnr2);
                   1412:   p1[1] = lcopy(mod); return gerepileupto(av, p1);
                   1413: }
                   1414:
                   1415: /* etant donne un bnr et un polynome relatif, trouve le groupe des normes
                   1416:    correspondant a l'extension relative en supposant qu'elle est abelienne
                   1417:    et que le module donnant bnr est multiple du conducteur. Verifie que
                   1418:    l'extension est bien abelienne (sous GRH) si rnf != NULL, dans ce cas
                   1419:    rnf est le rnf de l'extension relative. */
                   1420: static GEN
                   1421: rnfnormgroup0(GEN bnr, GEN polrel, GEN rnf)
                   1422: {
                   1423:   long av=avma,i,j,reldeg,sizemat,p,pmax,nfac,k;
                   1424:   GEN bnf,polreldisc,discnf,nf,raycl,group,detgroup,fa,greldeg;
                   1425:   GEN contreld,primreld,reldisc,famo,ep,fac,col,p1,bd,upnf;
                   1426:   byteptr d = diffptr + 1; /* start at p = 2 */
                   1427:
                   1428:   checkbnr(bnr); bnf=(GEN)bnr[1]; raycl=(GEN)bnr[5];
                   1429:   nf=(GEN)bnf[7];
                   1430:   polrel = fix_relative_pol(nf,polrel,1);
                   1431:   if (typ(polrel)!=t_POL) err(typeer,"rnfnormgroup");
                   1432:   reldeg=degpol(polrel);
                   1433:   /* reldeg-th powers are in norm group */
                   1434:   greldeg = stoi(reldeg);
                   1435:   group = diagonal(gmod((GEN)raycl[2], greldeg));
                   1436:   for (i=1; i<lg(group); i++)
                   1437:     if (!signe(gcoeff(group,i,i))) coeff(group,i,i) = (long)greldeg;
                   1438:   detgroup = dethnf_i(group);
                   1439:   k = cmpis(detgroup,reldeg);
                   1440:   if (k<0)
                   1441:   {
                   1442:     if (rnf) return NULL;
                   1443:     err(talker,"not an Abelian extension in rnfnormgroup?");
                   1444:   }
                   1445:   if (!rnf && !k) return gerepilecopy(av, group);
                   1446:
                   1447:   polreldisc=discsr(polrel);
                   1448:
                   1449:   if (rnf)
                   1450:   {
                   1451:     reldisc=gmael(rnf,3,1);
                   1452:     upnf=nfinit0(gmael(rnf,11,1),1,DEFAULTPREC);
                   1453:   }
                   1454:   else
                   1455:   {
                   1456:     reldisc = idealhermite(nf,polreldisc);
                   1457:     upnf = NULL;
                   1458:   }
                   1459:
                   1460:   reldisc = idealmul(nf, reldisc, gmael3(bnr,2,1,1));
                   1461:   contreld= content(reldisc);
                   1462:   primreld= gcmp1(contreld)? reldisc: gdiv(reldisc, contreld);
                   1463:
                   1464:   discnf = (GEN)nf[3];
                   1465:   k = degpol(nf[1]);
                   1466:   bd = gmulsg(k, glog(absi(discnf), DEFAULTPREC));
                   1467:   bd = gadd(bd,glog(mpabs(det(reldisc)),DEFAULTPREC));
                   1468:   p1 = dbltor(reldeg * k * 2.5 + 5);
                   1469:   bd = gfloor(gsqr(gadd(gmulsg(4,bd),p1)));
                   1470:
                   1471:   pmax = is_bigint(bd)? 0: itos(bd);
                   1472:   if (rnf)
                   1473:   {
                   1474:     if (DEBUGLEVEL) fprintferr("rnfnormgroup: bound for primes = %Z\n", bd);
                   1475:     if (!pmax) err(warner,"rnfnormgroup: prime bound too large, can't certify");
                   1476:   }
                   1477:   sizemat=lg(group)-1;
                   1478:   for (p=2; !pmax || p < pmax; p += *d++)
                   1479:   {
                   1480:     long oldf = -1, lfa;
                   1481:     /* If all pr are unramified and have the same residue degree, p =prod pr
                   1482:      * and including last pr^f or p^f is the same, but the last isprincipal
                   1483:      * is much easier! oldf is used to track this */
                   1484:
                   1485:     if (!*d) err(primer1);
                   1486:     if (!smodis(contreld,p)) continue; /* all pr|p ramified */
                   1487:
                   1488:     fa = primedec(nf,stoi(p)); lfa = lg(fa)-1;
                   1489:
                   1490:     for (i=1; i<=lfa; i++)
                   1491:     {
                   1492:       GEN pr = (GEN)fa[i];
                   1493:       long f;
                   1494:       /* check decomposition of pr has Galois type */
                   1495:       if (element_val(nf,polreldisc,pr) != 0)
                   1496:       {
                   1497:         /* if pr ramified, we will have to use all (non-ram) P | pr */
                   1498:         if (idealval(nf,primreld,pr)!=0) { oldf = 0; continue; }
                   1499:
                   1500:         famo=idealfactor(upnf,rnfidealup(rnf,pr));
                   1501:         ep=(GEN)famo[2];
                   1502:         fac=(GEN)famo[1];
                   1503:         nfac=lg(ep)-1;
                   1504:         f = itos(gmael(fac,1,4));
                   1505:         for (j=1; j<=nfac; j++)
                   1506:         {
                   1507:           if (!gcmp1((GEN)ep[j])) err(bugparier,"rnfnormgroup");
                   1508:           if (itos(gmael(fac,j,4)) != f)
                   1509:           {
                   1510:             if (rnf) return NULL;
                   1511:             err(talker,"non Galois extension in rnfnormgroup");
                   1512:           }
                   1513:         }
                   1514:       }
                   1515:       else
                   1516:       {
                   1517:         famo=nffactormod(nf,polrel,pr);
                   1518:         ep=(GEN)famo[2];
                   1519:         fac=(GEN)famo[1];
                   1520:         nfac=lg(ep)-1;
                   1521:         f = degpol((GEN)fac[1]);
                   1522:         for (j=1; j<=nfac; j++)
                   1523:         {
                   1524:           if (!gcmp1((GEN)ep[j])) err(bugparier,"rnfnormgroup");
                   1525:           if (degpol(fac[j]) != f)
                   1526:           {
                   1527:             if (rnf) return NULL;
                   1528:             err(talker,"non Galois extension in rnfnormgroup");
                   1529:           }
                   1530:         }
                   1531:       }
                   1532:       if (oldf < 0) oldf = f; else if (oldf != f) oldf = 0;
                   1533:       if (f == reldeg) continue; /* reldeg-th powers already included */
                   1534:
                   1535:       if (oldf && i == lfa && !smodis(discnf, p)) pr = stoi(p);
                   1536:
                   1537:       /* pr^f = N P, P | pr, hence is in norm group */
                   1538:       col = gmulsg(f, isprincipalrayall(bnr,pr,nf_REGULAR));
                   1539:       group = hnf(concatsp(group, col));
                   1540:       detgroup = dethnf_i(group);
                   1541:       k = cmpis(detgroup,reldeg);
                   1542:       if (k < 0)
                   1543:       {
                   1544:         if (rnf) return NULL;
                   1545:         err(talker,"not an Abelian extension in rnfnormgroup");
                   1546:       }
                   1547:       if (!rnf && !k) { cgiv(detgroup); return gerepileupto(av,group); }
                   1548:     }
                   1549:   }
                   1550:   if (k>0) err(bugparier,"rnfnormgroup");
                   1551:   cgiv(detgroup); return gerepileupto(av,group);
                   1552: }
                   1553:
                   1554: GEN
                   1555: rnfnormgroup(GEN bnr, GEN polrel)
                   1556: {
                   1557:   return rnfnormgroup0(bnr,polrel,NULL);
                   1558: }
                   1559:
                   1560: /* Etant donne un bnf et un polynome relatif polrel definissant une extension
                   1561:    abelienne, calcule le conducteur et le groupe de congruence correspondant
                   1562:    a l'extension definie par polrel sous la forme
                   1563:    [[ideal,arch],[hm,cyc,gen],group] ou [ideal,arch] est le conducteur, et
                   1564:    [hm,cyc,gen] est le groupe de classes de rayon correspondant. Verifie
                   1565:    (sous GRH) que polrel definit bien une extension abelienne si flag != 0 */
                   1566: GEN
                   1567: rnfconductor(GEN bnf, GEN polrel, long flag)
                   1568: {
                   1569:   long av=avma,tetpil,R1,i,v;
                   1570:   GEN nf,module,rnf,arch,bnr,group,p1,pol2;
                   1571:
                   1572:   bnf = checkbnf(bnf); nf=(GEN)bnf[7];
                   1573:   if (typ(polrel)!=t_POL) err(typeer,"rnfconductor");
                   1574:   module=cgetg(3,t_VEC); R1=itos(gmael(nf,2,1));
                   1575:   v=varn(polrel);
                   1576:   p1=unifpol((GEN)bnf[7],polrel,0);
                   1577:   p1=denom(gtovec(p1));
                   1578:   pol2=gsubst(polrel,v,gdiv(polx[v],p1));
                   1579:   pol2=gmul(pol2,gpuigs(p1,degpol(pol2)));
                   1580:   if (flag)
                   1581:   {
                   1582:     rnf=rnfinitalg(bnf,pol2,DEFAULTPREC);
                   1583:     module[1]=mael(rnf,3,1);
                   1584:   }
                   1585:   else
                   1586:   {
                   1587:     rnf=NULL;
                   1588:     module[1]=rnfdiscf(nf,pol2)[1];
                   1589:   }
                   1590:   arch=cgetg(R1+1,t_VEC);
                   1591:   module[2]=(long)arch; for (i=1; i<=R1; i++) arch[i]=un;
                   1592:   bnr=buchrayall(bnf,module,nf_INIT | nf_GEN);
                   1593:   group=rnfnormgroup0(bnr,pol2,rnf);
                   1594:   if (!group) { avma = av; return gzero; }
                   1595:   tetpil=avma;
                   1596:   return gerepile(av,tetpil,conductor(bnr,group,1));
                   1597: }
                   1598:
                   1599: /* Given a number field bnf=bnr[1], a ray class group structure
                   1600:  * bnr (from buchrayinit), and a subgroup H (HNF form) of the ray class
                   1601:  * group, compute [n, r1, dk] associated to H (cf. discrayall).
                   1602:  * If flcond = 1, abort (return gzero) if module is not the conductor
                   1603:  * If flrel = 0, compute only N(dk) instead of the ideal dk proper */
                   1604: static GEN
                   1605: discrayrelall(GEN bnr, GEN H, long flag)
                   1606: {
                   1607:   ulong av = avma;
                   1608:   long r1,j,k,ep, nz, flrel = flag & nf_REL, flcond = flag & nf_COND;
                   1609:   GEN bnf,nf,gen,bid,ideal,arch,p1,clhray,clhss,fa,arch2,idealrel,P,ex,mod,dlk;
                   1610:
                   1611:   checkbnrgen(bnr);
                   1612:   bnf = (GEN)bnr[1];
                   1613:   bid = (GEN)bnr[2];
                   1614:   clhray = gmael(bnr,5,1); gen = gmael(bnr,5,3);
                   1615:   nf = (GEN)bnf[7]; r1 = nf_get_r1(nf);
                   1616:   ideal= gmael(bid,1,1);
                   1617:   arch = gmael(bid,1,2);
                   1618:   if (gcmp0(H)) H = NULL;
                   1619:   else
                   1620:   {
                   1621:     p1 = gauss(H, diagonal(gmael(bnr,5,2)));
                   1622:     if (!gcmp1(denom(p1))) err(talker,"incorrect subgroup in discray");
                   1623:     p1 = absi(det(H));
                   1624:     if (egalii(p1, clhray)) H = NULL; else clhray = p1;
                   1625:   }
                   1626:   /* H = NULL --> trivial subgroup, else precompute isprincipal(gen) */
                   1627:   if (H) gen = getgen(bnf,gen);
                   1628:
                   1629:   fa = (GEN)bid[3];
                   1630:   P  = (GEN)fa[1];
                   1631:   ex = (GEN)fa[2];
                   1632:   mod = cgetg(3,t_VEC); mod[2] = (long)arch;
                   1633:
                   1634:   idealrel = flrel? idmat(degpol(nf[1])): gun;
                   1635:   for (k=1; k<lg(P); k++)
                   1636:   {
                   1637:     GEN pr = (GEN)P[k], S = gzero;
                   1638:     ep = itos((GEN)ex[k]);
                   1639:     mod[1] = (long)ideal;
                   1640:     for (j=1; j<=ep; j++)
                   1641:     {
                   1642:       mod[1] = (long)idealdivexact(nf,(GEN)mod[1],pr);
                   1643:       clhss = orderofquotient(bnf,mod,H,gen);
                   1644:       if (flcond && j==1 && egalii(clhss,clhray)) { avma = av; return gzero; }
                   1645:       if (is_pm1(clhss)) { S = addis(S, ep-j+1); break; }
                   1646:       S = addii(S, clhss);
                   1647:     }
                   1648:     idealrel = flrel? idealmul(nf,idealrel, idealpow(nf,pr, S))
                   1649:                     : mulii(idealrel, powgi(idealnorm(nf,pr),S));
                   1650:   }
                   1651:   dlk = flrel? idealdivexact(nf,idealpow(nf,ideal,clhray), idealrel)
                   1652:              : divii(powgi(dethnf_i(ideal),clhray), idealrel);
                   1653:
                   1654:   mod[1] = (long)ideal; arch2 = dummycopy(arch);
                   1655:   mod[2] = (long)arch2; nz = 0;
                   1656:   for (k=1; k<=r1; k++)
                   1657:   {
                   1658:     if (signe(arch[k]))
                   1659:     {
                   1660:       arch2[k] = zero;
                   1661:       clhss = orderofquotient(bnf,mod,H,gen);
                   1662:       if (!egalii(clhss,clhray)) { arch2[k] = un; continue; }
                   1663:       if (flcond) { avma = av; return gzero; }
                   1664:     }
                   1665:     nz++;
                   1666:   }
                   1667:   p1 = cgetg(4,t_VEC);
                   1668:   p1[1] = lcopy(clhray);
                   1669:   p1[2] = lstoi(nz);
                   1670:   p1[3] = lcopy(dlk); return gerepileupto(av, p1);
                   1671: }
                   1672:
                   1673: static GEN
                   1674: discrayabsall(GEN bnr, GEN subgroup,long flag)
                   1675: {
                   1676:   ulong av = avma;
                   1677:   long degk,clhray,n,R1;
                   1678:   GEN z,p1,D,dk,nf,dkabs,bnf;
                   1679:
                   1680:   D = discrayrelall(bnr,subgroup,flag);
                   1681:   if (flag & nf_REL) return D;
                   1682:   if (D == gzero) { avma = av; return gzero; }
                   1683:
                   1684:   bnf = (GEN)bnr[1]; nf = (GEN)bnf[7];
                   1685:   degk = degpol(nf[1]);
                   1686:   dkabs = absi((GEN)nf[3]);
                   1687:   dk = (GEN)D[3];
                   1688:   clhray = itos((GEN)D[1]); p1 = gpowgs(dkabs, clhray);
                   1689:   n = clhray * degk;
                   1690:   R1= clhray * itos((GEN)D[2]);
                   1691:   if (((n-R1)&3)==2) dk = negi(dk); /* (2r2) mod 4 = 2 : r2(relext) is odd */
                   1692:   z = cgetg(4,t_VEC);
                   1693:   z[1] = lstoi(n);
                   1694:   z[2] = lstoi(R1);
                   1695:   z[3] = lmulii(dk,p1); return gerepileupto(av, z);
                   1696: }
                   1697:
                   1698: GEN
                   1699: bnrdisc0(GEN arg0, GEN arg1, GEN arg2, long flag)
                   1700: {
                   1701:   GEN H, bnr = args_to_bnr(arg0,arg1,arg2,&H);
                   1702:   return discrayabsall(bnr,H,flag);
                   1703: }
                   1704:
                   1705: GEN
                   1706: discrayrel(GEN bnr, GEN H)
                   1707: {
                   1708:   return discrayrelall(bnr,H,nf_REL);
                   1709: }
                   1710:
                   1711: GEN
                   1712: discrayrelcond(GEN bnr, GEN H)
                   1713: {
                   1714:   return discrayrelall(bnr,H,nf_REL | nf_COND);
                   1715: }
                   1716:
                   1717: GEN
                   1718: discrayabs(GEN bnr, GEN H)
                   1719: {
                   1720:   return discrayabsall(bnr,H,nf_REGULAR);
                   1721: }
                   1722:
                   1723: GEN
                   1724: discrayabscond(GEN bnr, GEN H)
                   1725: {
                   1726:   return discrayabsall(bnr,H,nf_COND);
                   1727: }
                   1728:
                   1729: /* Given a number field bnf=bnr[1], a ray class group structure bnr and a
                   1730:  * vector chi representing a character on the generators bnr[2][3], compute
                   1731:  * the conductor of chi. */
                   1732: GEN
                   1733: bnrconductorofchar(GEN bnr, GEN chi)
                   1734: {
                   1735:   ulong av = avma;
                   1736:   long nbgen,i;
                   1737:   GEN p1,m,U,d1,cyc;
                   1738:
                   1739:   checkbnrgen(bnr);
                   1740:   cyc = gmael(bnr,5,2); nbgen = lg(cyc)-1;
                   1741:   if (lg(chi)-1 != nbgen)
                   1742:     err(talker,"incorrect character length in conductorofchar");
                   1743:   if (!nbgen) return conductor(bnr,gzero,0);
                   1744:
                   1745:   d1 = (GEN)cyc[1]; m = cgetg(nbgen+2,t_MAT);
                   1746:   for (i=1; i<=nbgen; i++)
                   1747:   {
                   1748:     if (typ(chi[i]) != t_INT) err(typeer,"conductorofchar");
                   1749:     p1 = cgetg(2,t_COL); m[i] = (long)p1;
                   1750:     p1[1] = lmulii((GEN)chi[i], divii(d1, (GEN)cyc[i]));
                   1751:   }
                   1752:   p1 = cgetg(2,t_COL); m[i] = (long)p1;
                   1753:   p1[1] = (long)d1; U = (GEN)hnfall(m)[2];
                   1754:   setlg(U,nbgen+1);
                   1755:   for (i=1; i<=nbgen; i++) setlg(U[i],nbgen+1); /* U = Ker chi */
                   1756:   return gerepileupto(av, conductor(bnr,U,0));
                   1757: }
                   1758:
                   1759: /* Given lists of [zidealstarinit, unit ideallogs], return lists of ray class
                   1760:  * numbers */
                   1761: GEN
                   1762: rayclassnolist(GEN bnf,GEN lists)
                   1763: {
                   1764:   ulong av = avma;
                   1765:   long i,j,lx,ly;
                   1766:   GEN blist,ulist,Llist,h,b,u,L,m;
                   1767:
                   1768:   if (typ(lists)!=t_VEC || lg(lists)!=3) err(typeer,"rayclassnolist");
                   1769:   bnf = checkbnf(bnf); h = gmael3(bnf,8,1,1);
                   1770:   blist = (GEN)lists[1];
                   1771:   ulist = (GEN)lists[2];
                   1772:   lx = lg(blist); Llist = cgetg(lx,t_VEC);
                   1773:   for (i=1; i<lx; i++)
                   1774:   {
                   1775:     b = (GEN)blist[i]; /* bid's */
                   1776:     u = (GEN)ulist[i]; /* units zideallogs */
                   1777:     ly = lg(b); L = cgetg(ly,t_VEC); Llist[i] = (long)L;
                   1778:     for (j=1; j<ly; j++)
                   1779:     {
                   1780:       GEN bid = (GEN)b[j], cyc = gmael(bid,2,2);
                   1781:       m = concatsp((GEN)u[j], diagonal(cyc));
                   1782:       L[j] = lmulii(h, dethnf_i(hnf(m)));
                   1783:     }
                   1784:   }
                   1785:   return gerepilecopy(av, Llist);
                   1786: }
                   1787:
                   1788: static long
                   1789: rayclassnolists(GEN sous, GEN sousclass, GEN fac)
                   1790: {
                   1791:   long i;
                   1792:   for (i=1; i<lg(sous); i++)
                   1793:     if (gegal(gmael(sous,i,3),fac)) return itos((GEN)sousclass[i]);
                   1794:   err(bugparier,"discrayabslist");
                   1795:   return 0; /* not reached */
                   1796: }
                   1797:
                   1798: static GEN
                   1799: rayclassnolistessimp(GEN sous, GEN fac)
                   1800: {
                   1801:   long i;
                   1802:   for (i=1; i<lg(sous); i++)
                   1803:     if (gegal(gmael(sous,i,1),fac)) return gmael(sous,i,2);
                   1804:   err(bugparier,"discrayabslistlong");
                   1805:   return NULL; /* not reached */
                   1806: }
                   1807:
                   1808: static GEN
                   1809: factormul(GEN fa1,GEN fa2)
                   1810: {
                   1811:   GEN p,pnew,e,enew,v,P, y = cgetg(3,t_MAT);
                   1812:   long i,c,lx;
                   1813:
                   1814:   p = concatsp((GEN)fa1[1],(GEN)fa2[1]); y[1] = (long)p;
                   1815:   e = concatsp((GEN)fa1[2],(GEN)fa2[2]); y[2] = (long)e;
                   1816:   v = sindexsort(p); lx = lg(p);
                   1817:   pnew = cgetg(lx,t_COL); for (i=1; i<lx; i++) pnew[i] = p[v[i]];
                   1818:   enew = cgetg(lx,t_COL); for (i=1; i<lx; i++) enew[i] = e[v[i]];
                   1819:   P = gzero; c = 0;
                   1820:   for (i=1; i<lx; i++)
                   1821:   {
                   1822:     if (gegal((GEN)pnew[i],P))
                   1823:       e[c] = laddii((GEN)e[c],(GEN)enew[i]);
                   1824:     else
                   1825:     {
                   1826:       c++; P = (GEN)pnew[i];
                   1827:       p[c] = (long)P;
                   1828:       e[c] = enew[i];
                   1829:     }
                   1830:   }
                   1831:   setlg(p, c+1);
                   1832:   setlg(e, c+1); return y;
                   1833: }
                   1834:
                   1835: static GEN
                   1836: factordivexact(GEN fa1,GEN fa2)
                   1837: {
                   1838:   long i,j,k,c,lx1,lx2;
                   1839:   GEN Lpr,Lex,y,Lpr1,Lex1,Lpr2,Lex2,p1;
                   1840:
                   1841:   Lpr1 = (GEN)fa1[1]; Lex1 = (GEN)fa1[2]; lx1 = lg(Lpr1);
                   1842:   Lpr2 = (GEN)fa2[1]; Lex2 = (GEN)fa2[2]; lx2 = lg(Lpr1);
                   1843:   y = cgetg(3,t_MAT);
                   1844:   Lpr = cgetg(lx1,t_COL); y[1] = (long)Lpr;
                   1845:   Lex = cgetg(lx1,t_COL); y[2] = (long)Lex;
                   1846:   for (c=0,i=1; i<lx1; i++)
                   1847:   {
                   1848:     j = isinvector(Lpr2,(GEN)Lpr1[i],lx2-1);
                   1849:     if (!j) { c++; Lpr[c] = Lpr1[i]; Lex[c] = Lex1[i]; }
                   1850:     else
                   1851:     {
                   1852:       p1 = subii((GEN)Lex1[i], (GEN)Lex2[j]); k = signe(p1);
                   1853:       if (k<0) err(talker,"factordivexact is not exact!");
                   1854:       if (k>0) { c++; Lpr[c] = Lpr1[i]; Lex[c] = (long)p1; }
                   1855:     }
                   1856:   }
                   1857:   setlg(Lpr,c+1);
                   1858:   setlg(Lex,c+1); return y;
                   1859: }
                   1860:
                   1861: static GEN
                   1862: factorpow(GEN fa,long n)
                   1863: {
                   1864:   GEN y;
                   1865:   if (!n) return trivfact();
                   1866:   y = cgetg(3,t_MAT);
                   1867:   y[1] = fa[1];
                   1868:   y[2] = lmulsg(n, (GEN)fa[2]); return y;
                   1869: }
                   1870:
                   1871: /* Etant donne la liste des zidealstarinit et des matrices d'unites
                   1872:  * correspondantes, sort la liste des discrayabs. On ne garde pas les modules
                   1873:  * qui ne sont pas des conducteurs
                   1874:  */
                   1875: GEN
                   1876: discrayabslist(GEN bnf,GEN lists)
                   1877: {
                   1878:   ulong av = avma;
                   1879:   long ii,jj,i,j,k,clhss,ep,clhray,lx,ly,r1,degk,nz;
                   1880:   long n,R1,lP;
                   1881:   GEN hlist,blist,dlist,nf,dkabs,b,h,d;
                   1882:   GEN z,ideal,arch,fa,P,ex,idealrel,mod,pr,dlk,arch2,p3,fac;
                   1883:
                   1884:   hlist = rayclassnolist(bnf,lists);
                   1885:   blist = (GEN)lists[1];
                   1886:   lx = lg(hlist); dlist = cgetg(lx,t_VEC);
                   1887:   nf = (GEN)bnf[7]; r1 = nf_get_r1(nf);
                   1888:   degk = degpol(nf[1]); dkabs = absi((GEN)nf[3]);
                   1889:   nz = 0; dlk = NULL; /* gcc -Wall */
                   1890:   for (ii=1; ii<lx; ii++)
                   1891:   {
                   1892:     b = (GEN)blist[ii]; /* zidealstarinits */
                   1893:     h = (GEN)hlist[ii]; /* class numbers */
                   1894:     ly = lg(b); d = cgetg(ly,t_VEC); dlist[ii] = (long)d; /* discriminants */
                   1895:     for (jj=1; jj<ly; jj++)
                   1896:     {
                   1897:       GEN fac1,fac2, bid = (GEN)b[jj];
                   1898:       clhray = itos((GEN)h[jj]);
                   1899:       ideal= gmael(bid,1,1);
                   1900:       arch = gmael(bid,1,2);
                   1901:       fa = (GEN)bid[3]; fac = dummycopy(fa);
                   1902:       P = (GEN)fa[1]; fac1 = (GEN)fac[1];
                   1903:       ex= (GEN)fa[2]; fac2 = (GEN)fac[2];
                   1904:       lP = lg(P)-1; idealrel = trivfact();
                   1905:       for (k=1; k<=lP; k++)
                   1906:       {
                   1907:         GEN normp;
                   1908:         long S = 0, normps, normi;
                   1909:        pr = (GEN)P[k]; ep = itos((GEN)ex[k]);
                   1910:        normi = ii; normps = itos(idealnorm(nf,pr));
                   1911:        for (j=1; j<=ep; j++)
                   1912:        {
                   1913:           GEN fad, fad1, fad2;
                   1914:           if (j < ep) { fac2[k] = lstoi(ep-j); fad = fac; }
                   1915:           else
                   1916:           {
                   1917:             fad = cgetg(3,t_MAT);
                   1918:             fad1 = cgetg(lP,t_COL); fad[1] = (long)fad1;
                   1919:             fad2 = cgetg(lP,t_COL); fad[2] = (long)fad2;
                   1920:             for (i=1; i< k; i++) { fad1[i] = fac1[i];  fad2[i] = fac2[i]; }
                   1921:             for (   ; i<lP; i++) { fad1[i] = fac1[i+1];fad2[i] = fac2[i+1]; }
                   1922:           }
                   1923:           normi /= normps;
                   1924:           clhss = rayclassnolists((GEN)blist[normi],(GEN)hlist[normi], fad);
                   1925:           if (j==1 && clhss==clhray)
                   1926:          {
                   1927:            clhray = 0; fac2[k] = ex[k]; goto LLDISCRAY;
                   1928:          }
                   1929:           if (clhss == 1) { S += ep-j+1; break; }
                   1930:           S += clhss;
                   1931:        }
                   1932:        fac2[k] = ex[k];
                   1933:        normp = to_famat_all((GEN)pr[1], (GEN)pr[4]);
                   1934:        idealrel = factormul(idealrel, factorpow(normp,S));
                   1935:       }
                   1936:       dlk = factordivexact(factorpow(factor(stoi(ii)),clhray), idealrel);
                   1937:       mod = cgetg(3,t_VEC);
                   1938:       mod[1] = (long)ideal; arch2 = dummycopy(arch);
                   1939:       mod[2] = (long)arch2; nz = 0;
                   1940:       for (k=1; k<=r1; k++)
                   1941:       {
                   1942:        if (signe(arch[k]))
                   1943:        {
                   1944:          arch2[k] = zero;
                   1945:          clhss = itos(rayclassno(bnf,mod));
                   1946:          arch2[k] = un;
                   1947:          if (clhss == clhray) { clhray = 0; break; }
                   1948:        }
                   1949:        else nz++;
                   1950:       }
                   1951: LLDISCRAY:
                   1952:       if (!clhray) { d[jj] = lgetg(1,t_VEC); continue; }
                   1953:
                   1954:       p3 = factorpow(factor(dkabs),clhray);
                   1955:       n = clhray * degk;
                   1956:       R1= clhray * nz;
                   1957:       if (((n-R1)&3) == 2) /* r2 odd, set dlk = -dlk */
                   1958:         dlk = factormul(to_famat_all(stoi(-1),gun), dlk);
                   1959:       z = cgetg(4,t_VEC);
                   1960:       z[1] = lstoi(n);
                   1961:       z[2] = lstoi(R1);
                   1962:       z[3] = (long)factormul(dlk,p3);
                   1963:       d[jj] = (long)z;
                   1964:     }
                   1965:   }
                   1966:   return gerepilecopy(av, dlist);
                   1967: }
                   1968:
                   1969: #define SHLGVINT 15
                   1970: #define LGVINT (1L << SHLGVINT)
                   1971:
                   1972: /* Attention: bound est le nombre de vraies composantes voulues. */
                   1973: static GEN
                   1974: bigcgetvec(long bound)
                   1975: {
                   1976:   long nbcext,nbfinal,i;
                   1977:   GEN vext;
                   1978:
                   1979:   nbcext = ((bound-1)>>SHLGVINT)+1;
                   1980:   nbfinal = bound-((nbcext-1)<<SHLGVINT);
                   1981:   vext = cgetg(nbcext+1,t_VEC);
                   1982:   for (i=1; i<nbcext; i++) vext[i] = lgetg(LGVINT+1,t_VEC);
                   1983:   vext[nbcext] = lgetg(nbfinal+1,t_VEC); return vext;
                   1984: }
                   1985:
                   1986: static GEN
                   1987: getcompobig(GEN vext,long i)
                   1988: {
                   1989:   long cext;
                   1990:
                   1991:   if (i<=LGVINT) return gmael(vext,1,i);
                   1992:   cext = ((i-1)>>SHLGVINT)+1;
                   1993:   return gmael(vext, cext, i-((cext-1)<<SHLGVINT));
                   1994: }
                   1995:
                   1996: static void
                   1997: putcompobig(GEN vext,long i,GEN x)
                   1998: {
                   1999:   long cext;
                   2000:
                   2001:   if (i<=LGVINT) { mael(vext,1,i)=(long)x; return; }
                   2002:   cext=((i-1)>>SHLGVINT)+1;
                   2003:   mael(vext, cext, i-((cext-1)<<SHLGVINT)) = (long)x;
                   2004: }
                   2005:
                   2006: static GEN
                   2007: zsimp(GEN bid, GEN matunit)
                   2008: {
                   2009:   GEN y = cgetg(5,t_VEC);
                   2010:   y[1] = bid[3];
                   2011:   y[2] = mael(bid,2,2);
                   2012:   y[3] = bid[5];
                   2013:   y[4] = (long)matunit; return y;
                   2014: }
                   2015:
                   2016: static GEN
                   2017: zsimpjoin(GEN bidsimp, GEN bidp, GEN dummyfa, GEN matunit)
                   2018: {
                   2019:   long i,l1,l2,nbgen,c, av = avma;
                   2020:   GEN U,U1,U2,cyc1,cyc2,cyc,u1u2,met, y = cgetg(5,t_VEC);
                   2021:
                   2022:   y[1] = (long)vconcat((GEN)bidsimp[1],dummyfa);
                   2023:   U1 = (GEN)bidsimp[3]; cyc1 = (GEN)bidsimp[2]; l1 = lg(cyc1);
                   2024:   U2 = (GEN)bidp[5];    cyc2 = gmael(bidp,2,2); l2 = lg(cyc2);
                   2025:   nbgen = l1+l2-2;
                   2026:   if (nbgen)
                   2027:   {
                   2028:     cyc = diagonal(concatsp(cyc1,cyc2));
                   2029:     u1u2 = matsnf0(cyc, 1 | 4); /* all && clean */
                   2030:     U = (GEN)u1u2[1];
                   2031:     met=(GEN)u1u2[3];
                   2032:     y[3] = (long)concatsp(
                   2033:       l1==1   ? zeromat(nbgen, lg(U1)-1): gmul(vecextract_i(U, 1,   l1-1), U1) ,
                   2034:       l1>nbgen? zeromat(nbgen, lg(U2)-1): gmul(vecextract_i(U, l1, nbgen), U2)
                   2035:     );
                   2036:   }
                   2037:   else
                   2038:   {
                   2039:     c = lg(U1)+lg(U2)-1; U = cgetg(c,t_MAT);
                   2040:     for (i=1; i<c; i++) U[i]=lgetg(1,t_COL);
                   2041:     met = cgetg(1,t_MAT);
                   2042:     y[3] = (long)U;
                   2043:   }
                   2044:   c = lg(met); cyc = cgetg(c,t_VEC);
                   2045:   for (i=1; i<c; i++) cyc[i] = coeff(met,i,i);
                   2046:   y[2] = (long)cyc;
                   2047:   y[4] = (long)vconcat((GEN)bidsimp[4],matunit);
                   2048:   return gerepilecopy(av, y);
                   2049: }
                   2050:
                   2051: static GEN
                   2052: rayclassnointern(GEN blist, GEN h)
                   2053: {
                   2054:   long lx,j;
                   2055:   GEN bid,qm,L,cyc,m,z;
                   2056:
                   2057:   lx = lg(blist); L = cgetg(lx,t_VEC);
                   2058:   for (j=1; j<lx; j++)
                   2059:   {
                   2060:     bid = (GEN)blist[j];
                   2061:     qm = gmul((GEN)bid[3],(GEN)bid[4]);
                   2062:     cyc = (GEN)bid[2];
                   2063:     m = concatsp(qm, diagonal(cyc));
                   2064:     z = cgetg(3,t_VEC); L[j] = (long)z;
                   2065:     z[1] = bid[1];
                   2066:     z[2] = lmulii(h, dethnf_i(hnf(m)));
                   2067:   }
                   2068:   return L;
                   2069: }
                   2070:
                   2071: void rowselect_p(GEN A, GEN B, GEN p, long init);
                   2072:
                   2073: static GEN
                   2074: rayclassnointernarch(GEN blist, GEN h, GEN matU)
                   2075: {
                   2076:   long lx,nc,k,kk,j,r1,jj,nba,nbarch;
                   2077:   GEN _2,bid,qm,Lray,cyc,m,z,z2,mm,rowsel;
                   2078:
                   2079:   if (!matU) return rayclassnointern(blist,h);
                   2080:   lx = lg(blist); if (lx == 1) return blist;
                   2081:
                   2082:   r1 = lg(matU[1])-1; _2 = gscalmat(gdeux,r1);
                   2083:   Lray = cgetg(lx,t_VEC); nbarch = 1<<r1;
                   2084:   for (j=1; j<lx; j++)
                   2085:   {
                   2086:     bid = (GEN)blist[j];
                   2087:     qm = gmul((GEN)bid[3],(GEN)bid[4]);
                   2088:     cyc = (GEN)bid[2]; nc = lg(cyc)-1;
                   2089:     /* [ qm   cyc 0 ]
                   2090:      * [ matU  0  2 ] */
                   2091:     m = concatsp3(vconcat(qm, matU),
                   2092:              vconcat(diagonal(cyc), zeromat(r1,nc)),
                   2093:              vconcat(zeromat(nc,r1), _2));
                   2094:     m = hnf(m); mm = dummycopy(m);
                   2095:     z2 = cgetg(nbarch+1,t_VEC);
                   2096:     rowsel = cgetg(nc+r1+1,t_VECSMALL);
                   2097:     for (k = 0; k < nbarch; k++)
                   2098:     {
                   2099:       nba = nc+1;
                   2100:       for (kk=k,jj=1; jj<=r1; jj++,kk>>=1)
                   2101:        if (kk&1) rowsel[nba++] = nc + jj;
                   2102:       setlg(rowsel, nba);
                   2103:       rowselect_p(m, mm, rowsel, nc+1);
                   2104:       z2[k+1] = lmulii(h, dethnf_i(hnf(mm)));
                   2105:     }
                   2106:     z = cgetg(3,t_VEC); Lray[j] = (long)z;
                   2107:     z[1] = bid[1];
                   2108:     z[2] = (long)z2;
                   2109:   }
                   2110:   return Lray;
                   2111: }
                   2112:
                   2113: GEN
                   2114: decodemodule(GEN nf, GEN fa)
                   2115: {
                   2116:   long n,k,j,fauxpr,av=avma;
                   2117:   GEN g,e,id,pr;
                   2118:
                   2119:   nf = checknf(nf);
                   2120:   if (typ(fa)!=t_MAT || lg(fa)!=3)
                   2121:     err(talker,"incorrect factorisation in decodemodule");
                   2122:   n = degpol(nf[1]); id = idmat(n);
                   2123:   g = (GEN)fa[1];
                   2124:   e = (GEN)fa[2];
                   2125:   for (k=1; k<lg(g); k++)
                   2126:   {
                   2127:     fauxpr = itos((GEN)g[k]);
                   2128:     j = (fauxpr%n)+1; fauxpr /= n*n;
                   2129:     pr = (GEN)primedec(nf,stoi(fauxpr))[j];
                   2130:     id = idealmul(nf,id, idealpow(nf,pr,(GEN)e[k]));
                   2131:   }
                   2132:   return gerepileupto(av,id);
                   2133: }
                   2134:
                   2135: /* Do all from scratch, bound < 2^30. For the time being, no subgroups.
                   2136:  * Ouput: vector vext whose components vint have exactly 2^LGVINT entries
                   2137:  * but for the last one which is allowed to be shorter. vext[i][j]
                   2138:  * (where j<=2^LGVINT) is understood as component number I = (i-1)*2^LGVINT+j
                   2139:  * in a unique huge vector V.  Such a component V[I] is a vector indexed by
                   2140:  * all ideals of norm I. Given such an ideal m_0, the component is as follows:
                   2141:  *
                   2142:  * + if arch = NULL, run through all possible archimedean parts, the archs
                   2143:  * are ordered using inverse lexicographic order, [0,..,0], [1,0,..,0],
                   2144:  * [0,1,..,0],... Component is [m_0,V] where V is a vector with
                   2145:  * 2^r1 entries, giving for each arch the triple [N,R1,D], with N, R1, D
                   2146:  * as in discrayabs [D is in factored form]
                   2147:  *
                   2148:  * + otherwise [m_0,arch,N,R1,D]
                   2149:  *
                   2150:  * If ramip != 0 and -1, keep only modules which are squarefree outside ramip
                   2151:  * If ramip < 0, archsquare. (????)
                   2152:  */
                   2153: static GEN
                   2154: discrayabslistarchintern(GEN bnf, GEN arch, long bound, long ramip)
                   2155: {
                   2156:   byteptr ptdif=diffptr;
                   2157:   long degk,i,j,k,p2s,lfa,lp1,sqbou,cex, allarch;
                   2158:   long ffs,fs,resp,flbou,nba, k2,karch,kka,nbarch,jjj,jj,square;
                   2159:   long ii2,ii,ly,clhray,lP,ep,S,clhss,normps,normi,nz,r1,R1,n,c;
                   2160:   ulong q, av0 = avma, av,av1,lim;
                   2161:   GEN nf,p,z,p1,p2,p3,fa,pr,normp,ideal,bidp,z2,matarchunit;
                   2162:   GEN funits,racunit,embunit,sous,clh,sousray,raylist;
                   2163:   GEN clhrayall,discall,faall,Id,idealrel,idealrelinit;
                   2164:   GEN sousdisc,mod,P,ex,fac,fadkabs,pz;
                   2165:   GEN arch2,dlk,disclist,p4,faussefa,fauxpr,gprime;
                   2166:   GEN *gptr[2];
                   2167:
                   2168:   if (bound <= 0) err(talker,"non-positive bound in discrayabslist");
                   2169:   clhray = nz = 0; /* gcc -Wall */
                   2170:   mod = Id = dlk = ideal = clhrayall = discall = faall = NULL;
                   2171:
                   2172:   /* ce qui suit recopie d'assez pres ideallistzstarall */
                   2173:   if (DEBUGLEVEL>2) timer2();
                   2174:   bnf = checkbnf(bnf); flbou=0;
                   2175:   nf = (GEN)bnf[7]; r1 = nf_get_r1(nf);
                   2176:   degk = degpol(nf[1]);
                   2177:   fadkabs = factor(absi((GEN)nf[3]));
                   2178:   clh = gmael3(bnf,8,1,1);
                   2179:   racunit = gmael3(bnf,8,4,2);
                   2180:   funits = check_units(bnf,"discrayabslistarchintern");
                   2181:
                   2182:   if (ramip >= 0) square = 0;
                   2183:   else
                   2184:   {
                   2185:     square = 1; ramip = -ramip;
                   2186:     if (ramip==1) ramip=0;
                   2187:   }
                   2188:   nba = 0; allarch = (arch==NULL);
                   2189:   if (allarch)
                   2190:     { arch=cgetg(r1+1,t_VEC); for (i=1; i<=r1; i++) arch[i]=un; nba=r1; }
                   2191:   else if (gcmp0(arch))
                   2192:     { arch=cgetg(r1+1,t_VEC); for (i=1; i<=r1; i++) arch[i]=zero; }
                   2193:   else
                   2194:   {
                   2195:     if (lg(arch)!=r1+1)
                   2196:       err(talker,"incorrect archimedean argument in discrayabslistarchintern");
                   2197:     for (i=1; i<=r1; i++) if (signe(arch[i])) nba++;
                   2198:     if (nba) mod = cgetg(3,t_VEC);
                   2199:   }
                   2200:   p1 = cgetg(3,t_VEC);
                   2201:   p1[1] = (long)idmat(degk);
                   2202:   p1[2] = (long)arch; bidp = zidealstarinitall(nf,p1,0);
                   2203:   if (allarch)
                   2204:   {
                   2205:     matarchunit = logunitmatrix(nf,funits,racunit,bidp);
                   2206:     if (r1>15) err(talker,"r1>15 in discrayabslistarchintern");
                   2207:   }
                   2208:   else
                   2209:     matarchunit = (GEN)NULL;
                   2210:
                   2211:   p = cgeti(3); p[1] = evalsigne(1)|evallgef(3);
                   2212:   sqbou = (long)sqrt((double)bound) + 1;
                   2213:   av = avma; lim = stack_lim(av,1);
                   2214:   z = bigcgetvec(bound); for (i=2;i<=bound;i++) putcompobig(z,i,cgetg(1,t_VEC));
                   2215:   if (allarch) bidp = zidealstarinitall(nf,idmat(degk),0);
                   2216:   embunit = logunitmatrix(nf,funits,racunit,bidp);
                   2217:   putcompobig(z,1, _vec(zsimp(bidp,embunit)));
                   2218:   if (DEBUGLEVEL>1) fprintferr("Starting zidealstarunits computations\n");
                   2219:   if (bound > (long)maxprime()) err(primer1);
                   2220:   for (p[2]=0; p[2]<=bound; )
                   2221:   {
                   2222:     p[2] += *ptdif++;
                   2223:     if (!flbou && p[2]>sqbou)
                   2224:     {
                   2225:       if (DEBUGLEVEL>1) fprintferr("\nStarting rayclassno computations\n");
                   2226:       flbou = 1;
                   2227:       z = gerepilecopy(av,z);
                   2228:       av1 = avma; raylist = bigcgetvec(bound);
                   2229:       for (i=1; i<=bound; i++)
                   2230:       {
                   2231:        sous = getcompobig(z,i);
                   2232:         sousray = rayclassnointernarch(sous,clh,matarchunit);
                   2233:        putcompobig(raylist,i,sousray);
                   2234:       }
                   2235:       raylist = gerepilecopy(av1,raylist);
                   2236:       z2 = bigcgetvec(sqbou);
                   2237:       for (i=1; i<=sqbou; i++)
                   2238:         putcompobig(z2,i, gcopy(getcompobig(z,i)));
                   2239:       z = z2;
                   2240:     }
                   2241:     fa = primedec(nf,p); lfa = lg(fa)-1;
                   2242:     for (j=1; j<=lfa; j++)
                   2243:     {
                   2244:       pr = (GEN)fa[j]; p1 = powgi(p,(GEN)pr[4]);
                   2245:       if (DEBUGLEVEL>1) { fprintferr("%ld ",p[2]); flusherr(); }
                   2246:       if (is_bigint(p1) || (q = (ulong)itos(p1)) > (ulong)bound) continue;
                   2247:
                   2248:       fauxpr = stoi((p[2]*degk + itos((GEN)pr[4])-1)*degk + j-1);
                   2249:       p2s = q; ideal = pr; cex = 0;
                   2250:       while (q <= (ulong)bound)
                   2251:       {
                   2252:         cex++; bidp = zidealstarinitall(nf,ideal,0);
                   2253:         faussefa = to_famat_all(fauxpr, stoi(cex));
                   2254:         embunit = logunitmatrix(nf,funits,racunit,bidp);
                   2255:         for (i=q; i<=bound; i+=q)
                   2256:         {
                   2257:           p1 = getcompobig(z,i/q); lp1 = lg(p1);
                   2258:           if (lp1 == 1) continue;
                   2259:
                   2260:           p2 = cgetg(lp1,t_VEC); c=0;
                   2261:           for (k=1; k<lp1; k++)
                   2262:           {
                   2263:             p3=(GEN)p1[k];
                   2264:             if (q == (ulong)i ||
                   2265:                 ((p4=gmael(p3,1,1)) && !isinvector(p4,fauxpr,lg(p4)-1)))
                   2266:               p2[++c] = (long)zsimpjoin(p3,bidp,faussefa,embunit);
                   2267:           }
                   2268:
                   2269:           setlg(p2, c+1);
                   2270:           if (p[2] <= sqbou)
                   2271:           {
                   2272:             pz = getcompobig(z,i);
                   2273:             if (lg(pz) > 1) p2 = concatsp(pz,p2);
                   2274:             putcompobig(z,i,p2);
                   2275:           }
                   2276:           else
                   2277:           {
                   2278:             p2 = rayclassnointernarch(p2,clh,matarchunit);
                   2279:             pz = getcompobig(raylist,i);
                   2280:             if (lg(pz) > 1) p2 = concatsp(pz,p2);
                   2281:             putcompobig(raylist,i,p2);
                   2282:           }
                   2283:         }
                   2284:         if (ramip && ramip % p[2]) break;
                   2285:         pz = mulss(q,p2s);
                   2286:         if (is_bigint(pz) || (q = (ulong)pz[2]) > (ulong)bound) break;
                   2287:
                   2288:         ideal = idealmul(nf,ideal,pr);
                   2289:       }
                   2290:     }
                   2291:     if (low_stack(lim, stack_lim(av,1)))
                   2292:     {
                   2293:       if(DEBUGMEM>1) err(warnmem,"[1]: discrayabslistarch");
                   2294:       if (!flbou)
                   2295:       {
                   2296:        if (DEBUGLEVEL>2)
                   2297:           fprintferr("avma = %ld, t(z) = %ld ",avma-bot,taille2(z));
                   2298:         z = gerepilecopy(av, z);
                   2299:       }
                   2300:       else
                   2301:       {
                   2302:        if (DEBUGLEVEL>2)
                   2303:          fprintferr("avma = %ld, t(r) = %ld ",avma-bot,taille2(raylist));
                   2304:        gptr[0]=&z; gptr[1]=&raylist; gerepilemany(av,gptr,2);
                   2305:       }
                   2306:       if (DEBUGLEVEL>2) { fprintferr("avma = %ld ",avma-bot); flusherr(); }
                   2307:     }
                   2308:   }
                   2309:   if (!flbou)
                   2310:   {
                   2311:     if (DEBUGLEVEL>1) fprintferr("\nStarting rayclassno computations\n");
                   2312:     z = gerepilecopy(av, z);
                   2313:     av1 = avma; raylist = bigcgetvec(bound);
                   2314:     for (i=1; i<=bound; i++)
                   2315:     {
                   2316:       sous = getcompobig(z,i);
                   2317:       sousray = rayclassnointernarch(sous,clh,matarchunit);
                   2318:       putcompobig(raylist,i,sousray);
                   2319:     }
                   2320:   }
                   2321:   if (DEBUGLEVEL>2)
                   2322:     fprintferr("avma = %ld, t(r) = %ld ",avma-bot,taille2(raylist));
                   2323:   raylist = gerepilecopy(av, raylist);
                   2324:   if (DEBUGLEVEL>2)
                   2325:     { fprintferr("avma = %ld ",avma-bot); msgtimer("zidealstarlist"); }
                   2326:   /* following discrayabslist */
                   2327:   if (DEBUGLEVEL>1)
                   2328:     { fprintferr("Starting discrayabs computations\n"); flusherr(); }
                   2329:
                   2330:   if (allarch) nbarch = 1<<r1;
                   2331:   else
                   2332:   {
                   2333:     nbarch = 1;
                   2334:     clhrayall = cgetg(2,t_VEC);
                   2335:     discall = cgetg(2,t_VEC);
                   2336:     faall = cgetg(2,t_VEC);
                   2337:     Id = idmat(degk);
                   2338:   }
                   2339:   idealrelinit = trivfact();
                   2340:   av1 = avma; lim = stack_lim(av1,1);
                   2341:   if (square) bound = sqbou-1;
                   2342:   disclist = bigcgetvec(bound);
                   2343:   for (ii=1; ii<=bound; ii++) putcompobig(disclist,ii,cgetg(1,t_VEC));
                   2344:   for (ii2=1; ii2<=bound; ii2++)
                   2345:   {
                   2346:     ii = square? ii2*ii2: ii2;
                   2347:     if (DEBUGLEVEL>1 && ii%100==0) { fprintferr("%ld ",ii); flusherr(); }
                   2348:     sous = getcompobig(raylist,ii); ly = lg(sous); sousdisc = cgetg(ly,t_VEC);
                   2349:     putcompobig(disclist, square? ii2: ii,sousdisc);
                   2350:     for (jj=1; jj<ly; jj++)
                   2351:     {
                   2352:       GEN fac1, fac2, bidsimp = (GEN)sous[jj];
                   2353:       fa = (GEN)bidsimp[1]; fac = dummycopy(fa);
                   2354:       P = (GEN)fa[1]; fac1 = (GEN)fac[1];
                   2355:       ex= (GEN)fa[2]; fac2 = (GEN)fac[2];
                   2356:       lP = lg(P)-1;
                   2357:
                   2358:       if (allarch)
                   2359:       {
                   2360:         clhrayall = (GEN)bidsimp[2];
                   2361:         discall = cgetg(nbarch+1,t_VEC);
                   2362:       }
                   2363:       else
                   2364:         clhray = itos((GEN)bidsimp[2]);
                   2365:       for (karch=0; karch<nbarch; karch++)
                   2366:       {
                   2367:         if (!allarch) ideal = Id;
                   2368:         else
                   2369:         {
                   2370:           nba=0;
                   2371:           for (kka=karch,jjj=1; jjj<=r1; jjj++,kka>>=1)
                   2372:             if (kka & 1) nba++;
                   2373:           clhray = itos((GEN)clhrayall[karch+1]);
                   2374:           for (k2=1,k=1; k<=r1; k++,k2<<=1)
                   2375:           {
                   2376:             if (karch&k2 && clhray==itos((GEN)clhrayall[karch-k2+1]))
                   2377:               { clhray=0; goto LDISCRAY; }
                   2378:           }
                   2379:         }
                   2380:         idealrel = idealrelinit;
                   2381:         for (k=1; k<=lP; k++)
                   2382:         {
                   2383:           fauxpr = (GEN)P[k]; ep = itos((GEN)ex[k]); ffs = itos(fauxpr);
                   2384:           /* Hack for NeXTgcc 2.5.8 -- splitting "resp=fs%degk+1" */
                   2385:           fs = ffs/degk; resp = fs%degk; resp++;
                   2386:           gprime = stoi((long)(fs/degk));
                   2387:           if (!allarch && nba)
                   2388:           {
                   2389:             p1 = (GEN)primedec(nf,gprime)[ffs%degk+1];
                   2390:             ideal = idealmul(nf,ideal,idealpow(nf,p1,(GEN)ex[k]));
                   2391:           }
                   2392:           S=0; clhss=0;
                   2393:           normi = ii; normps= itos(gpuigs(gprime,resp));
                   2394:           for (j=1; j<=ep; j++)
                   2395:           {
                   2396:             GEN fad, fad1, fad2;
                   2397:             if (clhss==1) S++;
                   2398:             else
                   2399:             {
                   2400:               if (j < ep) { fac2[k] = lstoi(ep-j); fad = fac; }
                   2401:               else
                   2402:               {
                   2403:                 fad = cgetg(3,t_MAT);
                   2404:                 fad1 = cgetg(lP,t_COL); fad[1] = (long)fad1;
                   2405:                 fad2 = cgetg(lP,t_COL); fad[2] = (long)fad2;
                   2406:                 for (i=1; i<k; i++) { fad1[i]=fac1[i];   fad2[i]=fac2[i]; }
                   2407:                 for (   ; i<lP; i++){ fad1[i]=fac1[i+1]; fad2[i]=fac2[i+1]; }
                   2408:               }
                   2409:               normi /= normps;
                   2410:              dlk = rayclassnolistessimp(getcompobig(raylist,normi),fad);
                   2411:               if (allarch) dlk = (GEN)dlk[karch+1];
                   2412:              clhss = itos(dlk);
                   2413:               if (j==1 && clhss==clhray)
                   2414:              {
                   2415:                clhray=0; fac2[k] = ex[k]; goto LDISCRAY;
                   2416:              }
                   2417:               S += clhss;
                   2418:             }
                   2419:           }
                   2420:           fac2[k] = ex[k];
                   2421:           normp = to_famat_all(gprime, stoi(resp));
                   2422:           idealrel = factormul(idealrel,factorpow(normp,S));
                   2423:         }
                   2424:         dlk = factordivexact(factorpow(factor(stoi(ii)),clhray),idealrel);
                   2425:         if (!allarch && nba)
                   2426:         {
                   2427:           mod[1] = (long)ideal; arch2 = dummycopy(arch);
                   2428:           mod[2] = (long)arch2; nz = 0;
                   2429:           for (k=1; k<=r1; k++)
                   2430:           {
                   2431:             if (signe(arch[k]))
                   2432:             {
                   2433:               arch2[k] = zero;
                   2434:               clhss = itos(rayclassno(bnf,mod));
                   2435:               arch2[k] = un;
                   2436:               if (clhss==clhray) { clhray=0; goto LDISCRAY; }
                   2437:             }
                   2438:             else nz++;
                   2439:           }
                   2440:         }
                   2441:         else nz = r1-nba;
                   2442: LDISCRAY:
                   2443:         p1=cgetg(4,t_VEC); discall[karch+1]=(long)p1;
                   2444:        if (!clhray) p1[1]=p1[2]=p1[3]=zero;
                   2445:        else
                   2446:        {
                   2447:          p3 = factorpow(fadkabs,clhray);
                   2448:           n = clhray * degk;
                   2449:           R1= clhray * nz;
                   2450:          if (((n-R1)&3)==2)
                   2451:            dlk=factormul(to_famat_all(stoi(-1),gun), dlk);
                   2452:          p1[1] = lstoi(n);
                   2453:           p1[2] = lstoi(R1);
                   2454:           p1[3] = (long)factormul(dlk,p3);
                   2455:        }
                   2456:       }
                   2457:       if (allarch)
                   2458:         { p1 = cgetg(3,t_VEC); p1[1]=(long)fa; p1[2]=(long)discall; }
                   2459:       else
                   2460:         { faall[1]=(long)fa; p1 = concatsp(faall, p1); }
                   2461:       sousdisc[jj]=(long)p1;
                   2462:       if (low_stack(lim, stack_lim(av1,1)))
                   2463:       {
                   2464:         if(DEBUGMEM>1) err(warnmem,"[2]: discrayabslistarch");
                   2465:         if (DEBUGLEVEL>2)
                   2466:           fprintferr("avma = %ld, t(d) = %ld ",avma-bot,taille2(disclist));
                   2467:         disclist = gerepilecopy(av1, disclist);
                   2468:         if (DEBUGLEVEL>2) { fprintferr("avma = %ld ",avma-bot); flusherr(); }
                   2469:       }
                   2470:     }
                   2471:   }
                   2472:   if (DEBUGLEVEL>2) msgtimer("discrayabs");
                   2473:   return gerepilecopy(av0, disclist);
                   2474: }
                   2475:
                   2476: GEN
                   2477: discrayabslistarch(GEN bnf, GEN arch, long bound)
                   2478: { return discrayabslistarchintern(bnf,arch,bound, 0); }
                   2479:
                   2480: GEN
                   2481: discrayabslistlong(GEN bnf, long bound)
                   2482: { return discrayabslistarchintern(bnf,gzero,bound, 0); }
                   2483:
                   2484: GEN
                   2485: discrayabslistarchsquare(GEN bnf, GEN arch, long bound)
                   2486: { return discrayabslistarchintern(bnf,arch,bound, -1); }
                   2487:
                   2488: static GEN
                   2489: computehuv(GEN bnr,GEN id, GEN arch)
                   2490: {
                   2491:   long i,nbgen, av = avma;
                   2492:   GEN bnf,bnrnew,listgen,P,U,DC;
                   2493:   GEN newmod=cgetg(3,t_VEC);
                   2494:   newmod[1]=(long)id;
                   2495:   newmod[2]=(long)arch;
                   2496:
                   2497:   bnf=(GEN)bnr[1];
                   2498:   bnrnew=buchrayall(bnf,newmod,nf_INIT);
                   2499:   listgen=gmael(bnr,5,3); nbgen=lg(listgen);
                   2500:   P=cgetg(nbgen,t_MAT);
                   2501:   for (i=1; i<nbgen; i++)
                   2502:     P[i] = (long)isprincipalray(bnrnew,(GEN)listgen[i]);
                   2503:   DC=diagonal(gmael(bnrnew,5,2));
                   2504:   U=(GEN)hnfall(concatsp(P,DC))[2];
                   2505:   setlg(U,nbgen); for (i=1; i<nbgen; i++) setlg(U[i], nbgen);
                   2506:   return gerepileupto(av, hnf(concatsp(U,diagonal(gmael(bnr,5,2)))));
                   2507: }
                   2508:
                   2509: /* 0 if hinv*list[i] has a denominator for all i, 1 otherwise */
                   2510: static int
                   2511: hnflistdivise(GEN list,GEN h)
                   2512: {
                   2513:   long av = avma, i, I = lg(list);
                   2514:   GEN hinv = ginv(h);
                   2515:
                   2516:   for (i=1; i<I; i++)
                   2517:     if (gcmp1(denom(gmul(hinv,(GEN)list[i])))) break;
                   2518:   avma = av; return i < I;
                   2519: }
                   2520:
                   2521: static GEN
                   2522: subgroupcond(GEN bnr, long indexbound)
                   2523: {
                   2524:   ulong av = avma;
                   2525:   long i,j,lgi,lp;
                   2526:   GEN li,p1,lidet,perm,nf,bid,ideal,arch,primelist,listkernels;
                   2527:
                   2528:   checkbnrgen(bnr); bid=(GEN)bnr[2];
                   2529:   ideal=gmael(bid,1,1);
                   2530:   arch =gmael(bid,1,2); nf=gmael(bnr,1,7);
                   2531:   primelist=gmael(bid,3,1); lp=lg(primelist)-1;
                   2532:   listkernels=cgetg(lp+lg(arch),t_VEC);
                   2533:   for (i=1; i<=lp; )
                   2534:   {
                   2535:     p1=idealdiv(nf,ideal,(GEN)primelist[i]);
                   2536:     listkernels[i++]=(long)computehuv(bnr,p1,arch);
                   2537:   }
                   2538:   for (j=1; j<lg(arch); j++)
                   2539:     if (signe((GEN)arch[j]))
                   2540:     {
                   2541:       p1=dummycopy(arch); p1[j]=zero;
                   2542:       listkernels[i++]=(long)computehuv(bnr,ideal,p1);
                   2543:     }
                   2544:   setlg(listkernels,i);
                   2545:
                   2546:   li=subgrouplist(gmael(bnr,5,2),indexbound);
                   2547:   lgi=lg(li);
                   2548:   for (i=1,j=1; j<lgi; j++)
                   2549:     if (!hnflistdivise(listkernels, (GEN)li[j])) li[i++] = li[j];
                   2550:   /* sort by increasing index */
                   2551:   lgi = i; setlg(li,i); lidet=cgetg(lgi,t_VEC);
                   2552:   for (i=1; i<lgi; i++) lidet[i]=(long)dethnf_i((GEN)li[i]);
                   2553:   perm = sindexsort(lidet); p1=li; li=cgetg(lgi,t_VEC);
                   2554:   for (i=1; i<lgi; i++) li[i] = p1[perm[lgi-i]];
                   2555:   return gerepilecopy(av,li);
                   2556: }
                   2557:
                   2558: GEN
                   2559: subgrouplist0(GEN bnr, long indexbound, long all)
                   2560: {
                   2561:   if (typ(bnr)!=t_VEC) err(typeer,"subgrouplist");
                   2562:   if (lg(bnr)!=1 && typ(bnr[1])!=t_INT)
                   2563:   {
                   2564:     if (!all) return subgroupcond(bnr,indexbound);
                   2565:     checkbnr(bnr); bnr = gmael(bnr,5,2);
                   2566:   }
                   2567:   return subgrouplist(bnr,indexbound);
                   2568: }
                   2569:
                   2570: GEN
                   2571: bnrdisclist0(GEN bnf, GEN borne, GEN arch, long all)
                   2572: {
                   2573:   if (typ(borne)==t_INT)
                   2574:   {
                   2575:     if (!arch) arch = gzero;
                   2576:     if (all==1) { arch = NULL; all = 0; }
                   2577:     return discrayabslistarchintern(bnf,arch,itos(borne),all);
                   2578:   }
                   2579:   return discrayabslist(bnf,borne);
                   2580: }

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