[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.2

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

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