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

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

1.1       noro        1: /* $Id: buch2.c,v 1.90 2001/10/01 12:11:30 karim Exp $
                      2:
                      3: Copyright (C) 2000  The PARI group.
                      4:
                      5: This file is part of the PARI/GP package.
                      6:
                      7: PARI/GP is free software; you can redistribute it and/or modify it under the
                      8: terms of the GNU General Public License as published by the Free Software
                      9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     10: ANY WARRANTY WHATSOEVER.
                     11:
                     12: Check the License for details. You should have received a copy of it, along
                     13: with the package; see the file 'COPYING'. If not, write to the Free Software
                     14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
                     15:
                     16: /*******************************************************************/
                     17: /*                                                                 */
                     18: /*         CLASS GROUP AND REGULATOR (McCURLEY, BUCHMANN)          */
                     19: /*                    GENERAL NUMBER FIELDS                        */
                     20: /*                                                                 */
                     21: /*******************************************************************/
                     22: #include "pari.h"
                     23: #include "parinf.h"
                     24: extern GEN to_famat_all(GEN x, GEN y);
                     25: extern int addcolumntomatrix(GEN V, GEN invp, GEN L);
                     26: extern double check_bach(double cbach, double B);
                     27: extern GEN gmul_mat_smallvec(GEN x, GEN y);
                     28: extern GEN gmul_mati_smallvec(GEN x, GEN y);
                     29: extern GEN get_arch_real(GEN nf,GEN x,GEN *emb,long prec);
                     30: extern GEN get_roots(GEN x,long r1,long ru,long prec);
                     31: extern void get_nf_matrices(GEN nf, long small);
                     32: extern long int_elt_val(GEN nf, GEN x, GEN p, GEN b, GEN *t, long v);
                     33: extern GEN init_idele(GEN nf);
                     34: extern GEN norm_by_embed(long r1, GEN x);
                     35: extern void minim_alloc(long n,double ***q,long **x,double **y,double **z,double **v);
                     36: extern GEN idealmulpowprime(GEN nf, GEN x, GEN vp, GEN n);
                     37: extern GEN arch_mul(GEN x, GEN y);
                     38: extern GEN vecdiv(GEN x, GEN y);
                     39: extern GEN vecmul(GEN x, GEN y);
                     40: extern GEN mul_real(GEN x, GEN y);
                     41:
                     42: #define SFB_MAX 2
                     43: #define SFB_STEP 2
                     44: #define MIN_EXTRA 1
                     45:
                     46: #define RANDOM_BITS 4
                     47: static const int CBUCHG = (1<<RANDOM_BITS) - 1;
                     48: static const int randshift = BITS_IN_RANDOM-1 - RANDOM_BITS;
                     49: #undef RANDOM_BITS
                     50:
                     51: static long KC,KCZ,KCZ2,MAXRELSUP;
                     52: static long primfact[500],expoprimfact[500];
                     53: static GEN *idealbase, vectbase, FB, numFB, powsubFB, numideal;
                     54:
                     55: /* FB[i]     i-th rational prime used in factor base
                     56:  * numFB[i]  index k such that FB[k]=i (0 if i is not prime)
                     57:  *
                     58:  * vectbase          vector of all ideals in FB
                     59:  * vecbase o subFB   part of FB used to build random relations
                     60:  * powsubFB  array lg(subFB) x (CBUCHG+1)   all powers up to CBUCHG
                     61:  *
                     62:  * idealbase[i]      prime ideals above i in FB
                     63:  * numideal[i]       index k such that idealbase[k] = i.
                     64:  *
                     65:  * mat            all relations found (as long integers, not reduced)
                     66:  * cglob          lg(mat) = total number of relations found so far
                     67:  *
                     68:  * Use only non-inert primes, coprime to discriminant index F:
                     69:  *   KC = number of prime ideals in factor base (norm < Bach cst)
                     70:  *   KC2= number of prime ideals assumed to generate class group (>= KC)
                     71:  *
                     72:  *   KCZ = number of rational primes under ideals counted by KC
                     73:  *   KCZ2= same for KC2
                     74:  */
                     75:
                     76: /* x a t_VECSMALL */
                     77: static long
                     78: ccontent(GEN x)
                     79: {
                     80:   long i, l = lg(x), s=labs(x[1]);
                     81:   for (i=2; i<l && s>1; i++) s = cgcd(x[i],s);
                     82:   return s;
                     83: }
                     84:
                     85: static void
                     86: desallocate(GEN **M)
                     87: {
                     88:   GEN *m = *M;
                     89:   long i;
                     90:   if (m)
                     91:   {
                     92:     for (i=lg(m)-1; i; i--) free(m[i]);
                     93:     free(m); *M = NULL;
                     94:   }
                     95: }
                     96:
                     97: /* Return the list of indexes or the primes chosen for the subFB.
                     98:  * Fill vperm (if !=0): primes ideals sorted by increasing norm (except the
                     99:  * ones in subFB come first [dense rows come first for hnfspec])
                    100:  * ss = number of rational primes whose divisors are all in FB
                    101:  */
                    102: static GEN
                    103: subFBgen(long N,long m,long minsFB,GEN vperm, long *ptss)
                    104: {
                    105:   long av = avma,i,j, lv=lg(vectbase),s=0,s1=0,n=0,ss=0,z=0;
                    106:   GEN y1,y2,subFB,perm,perm1,P,Q;
                    107:   double prod;
                    108:
                    109:   (void)new_chunk(lv); /* room for subFB */
                    110:   y1 = cgetg(lv,t_COL);
                    111:   y2 = cgetg(lv,t_COL);
                    112:   for (i=1,P=(GEN)vectbase[i];;P=Q)
                    113:   { /* we'll sort ideals by norm (excluded ideals = "zero") */
                    114:     long e = itos((GEN)P[3]);
                    115:     long ef= e*itos((GEN)P[4]);
                    116:
                    117:     s1 += ef;
                    118:     y2[i] = (long)powgi((GEN)P[1],(GEN)P[4]);
                    119:     /* take only unramified ideals */
                    120:     if (e>1) { y1[i]=zero; s=0; z++; } else { y1[i]=y2[i]; s += ef; }
                    121:
                    122:     i++; Q = (GEN)vectbase[i];
                    123:     if (i == lv || !egalii((GEN)P[1], (GEN)Q[1]))
                    124:     { /* don't take all P above a given p (delete the last one) */
                    125:       if (s == N) { y1[i-1]=zero; z++; }
                    126:       if (s1== N) ss++;
                    127:       if (i == lv) break;
                    128:       s = s1 = 0;
                    129:     }
                    130:   }
                    131:   if (z+minsFB >= lv) return NULL;
                    132:
                    133:   prod = 1.0;
                    134:   perm = sindexsort(y1) + z; /* skip "zeroes" (excluded ideals) */
                    135:   for(;;)
                    136:   {
                    137:     if (++n > minsFB && (z+n >= lv || prod > m + 0.5)) break;
                    138:     prod *= gtodouble((GEN)y1[perm[n]]);
                    139:   }
                    140:   if (prod < m) return NULL;
                    141:   n--;
                    142:
                    143:   /* take the first (non excluded) n ideals (wrt norm), put them first, and
                    144:    * sort the rest by increasing norm */
                    145:   for (j=1; j<=n; j++) y2[perm[j]] = zero;
                    146:   perm1 = sindexsort(y2); avma = av;
                    147:
                    148:   subFB = cgetg(n+1, t_VECSMALL);
                    149:   if (vperm)
                    150:   {
                    151:     for (j=1; j<=n; j++) vperm[j] = perm[j];
                    152:     for (   ; j<lv; j++) vperm[j] = perm1[j];
                    153:   }
                    154:   for (j=1; j<=n; j++) subFB[j] = perm[j];
                    155:
                    156:   if (DEBUGLEVEL)
                    157:   {
                    158:     if (DEBUGLEVEL>3)
                    159:     {
                    160:       fprintferr("\n***** IDEALS IN FACTORBASE *****\n\n");
                    161:       for (i=1; i<=KC; i++) fprintferr("no %ld = %Z\n",i,vectbase[i]);
                    162:       fprintferr("\n***** IDEALS IN SUB FACTORBASE *****\n\n");
                    163:       outerr(vecextract_p(vectbase,subFB));
                    164:       fprintferr("\n***** INITIAL PERMUTATION *****\n\n");
                    165:       fprintferr("vperm = %Z\n\n",vperm);
                    166:     }
                    167:     msgtimer("sub factorbase (%ld elements)",n);
                    168:   }
                    169:   powsubFB = NULL;
                    170:   *ptss = ss; return subFB;
                    171: }
                    172:
                    173: static GEN
                    174: mulred(GEN nf,GEN x, GEN I, long prec)
                    175: {
                    176:   ulong av = avma;
                    177:   GEN y = cgetg(3,t_VEC);
                    178:
                    179:   y[1] = (long)idealmulh(nf,I,(GEN)x[1]);
                    180:   y[2] = x[2];
                    181:   y = ideallllred(nf,y,NULL,prec);
                    182:   y[1] = (long)ideal_two_elt(nf,(GEN)y[1]);
                    183:   return gerepilecopy(av, y);
                    184: }
                    185:
                    186: /* Compute powers of prime ideals (P^0,...,P^a) in subFB (a > 1)
                    187:  * powsubFB[j][i] contains P_i^j in LLL form + archimedean part in
                    188:  * MULTIPLICATIVE form (logs are expensive)
                    189:  */
                    190: static void
                    191: powsubFBgen(GEN nf,GEN subFB,long a,long prec)
                    192: {
                    193:   long i,j, n = lg(subFB), RU = lg(nf[6]);
                    194:   GEN *pow, arch0 = cgetg(RU,t_COL);
                    195:   for (i=1; i<RU; i++) arch0[i] = un; /* 0 in multiplicative notations */
                    196:
                    197:   if (DEBUGLEVEL) fprintferr("Computing powers for sub-factor base:\n");
                    198:   powsubFB = cgetg(n, t_VEC);
                    199:   for (i=1; i<n; i++)
                    200:   {
                    201:     GEN vp = (GEN)vectbase[subFB[i]];
                    202:     GEN z = cgetg(3,t_VEC); z[1]=vp[1]; z[2]=vp[2];
                    203:     pow = (GEN*)cgetg(a+1,t_VEC); powsubFB[i] = (long)pow;
                    204:     pow[1]=cgetg(3,t_VEC);
                    205:     pow[1][1] = (long)z;
                    206:     pow[1][2] = (long)arch0;
                    207:     vp = prime_to_ideal(nf,vp);
                    208:     for (j=2; j<=a; j++)
                    209:     {
                    210:       pow[j] = mulred(nf,pow[j-1],vp,prec);
                    211:       if (DEBUGLEVEL>1) fprintferr(" %ld",j);
                    212:     }
                    213:     if (DEBUGLEVEL>1) { fprintferr("\n"); flusherr(); }
                    214:   }
                    215:   if (DEBUGLEVEL) msgtimer("powsubFBgen");
                    216: }
                    217:
                    218: /* Compute FB, numFB, idealbase, vectbase, numideal.
                    219:  * n2: bound for norm of tested prime ideals (includes be_honest())
                    220:  * n : bound for prime ideals used to build relations (Bach cst) ( <= n2 )
                    221:
                    222:  * Return prod_{p<=n2} (1-1/p) / prod_{Norm(P)<=n2} (1-1/Norm(P)),
                    223:  * close to residue of zeta_K at 1 = 2^r1 (2pi)^r2 h R / (w D)
                    224:  */
                    225: static GEN
                    226: FBgen(GEN nf,long n2,long n)
                    227: {
                    228:   byteptr delta=diffptr;
                    229:   long KC2,i,j,k,p,lon,ip,nor, N = degpol(nf[1]);
                    230:   GEN p2,p1,NormP,lfun;
                    231:   long prim[] = { evaltyp(t_INT)|m_evallg(3), evalsigne(1)|evallgefint(3),0 };
                    232:
                    233:   numFB    = cgetg(n2+1,t_VECSMALL);
                    234:   FB       = cgetg(n2+1,t_VECSMALL);
                    235:   numideal = cgetg(n2+1,t_VECSMALL);
                    236:   idealbase= (GEN*)cgetg(n2+1,t_VEC);
                    237:
                    238:   lfun=realun(DEFAULTPREC);
                    239:   p=*delta++; i=0; ip=0; KC=0;
                    240:   while (p<=n2)
                    241:   {
                    242:     long av = avma, av1;
                    243:     if (DEBUGLEVEL>=2) { fprintferr(" %ld",p); flusherr(); }
                    244:     prim[2] = p; p1 = primedec(nf,prim); lon=lg(p1);
                    245:     av1 = avma;
                    246:     divrsz(mulsr(p-1,lfun),p,lfun);
                    247:     if (itos(gmael(p1,1,4)) == N) /* p inert */
                    248:     {
                    249:       NormP = gpowgs(prim,N);
                    250:       if (!is_bigint(NormP) && (nor=NormP[2]) <= n2)
                    251:        divrsz(mulsr(nor,lfun),nor-1, lfun);
                    252:       avma = av1;
                    253:     }
                    254:     else
                    255:     {
                    256:       numideal[p]=ip;
                    257:       i++; numFB[p]=i; FB[i]=p;
                    258:       for (k=1; k<lon; k++,ip++)
                    259:       {
                    260:        NormP = powgi(prim,gmael(p1,k,4));
                    261:        if (is_bigint(NormP) || (nor=NormP[2]) > n2) break;
                    262:
                    263:         divrsz(mulsr(nor,lfun),nor-1, lfun);
                    264:       }
                    265:       /* keep all ideals with Norm <= n2 */
                    266:       avma = av1;
                    267:       if (k == lon)
                    268:         setisclone(p1); /* flag it: all prime divisors in FB */
                    269:       else
                    270:         { setlg(p1,k); p1 = gerepilecopy(av,p1); }
                    271:       idealbase[i] = p1;
                    272:     }
                    273:     if (!*delta) err(primer1);
                    274:     p += *delta++;
                    275:     if (KC == 0 && p>n) { KCZ=i; KC=ip; }
                    276:   }
                    277:   if (!KC) return NULL;
                    278:   KCZ2=i; KC2=ip; MAXRELSUP = min(50,4*KC);
                    279:
                    280:   setlg(FB,KCZ2);
                    281:   setlg(numFB,KCZ2);
                    282:   setlg(numideal,KCZ2);
                    283:   setlg(idealbase,KCZ2);
                    284:   vectbase=cgetg(KC+1,t_COL);
                    285:   for (i=1; i<=KCZ; i++)
                    286:   {
                    287:     p1 = idealbase[i]; k=lg(p1);
                    288:     p2 = vectbase + numideal[FB[i]];
                    289:     for (j=1; j<k; j++) p2[j]=p1[j];
                    290:   }
                    291:   if (DEBUGLEVEL)
                    292:   {
                    293:     if (DEBUGLEVEL>1) fprintferr("\n");
                    294:     if (DEBUGLEVEL>6)
                    295:     {
                    296:       fprintferr("########## FACTORBASE ##########\n\n");
                    297:       fprintferr("KC2=%ld, KC=%ld, KCZ=%ld, KCZ2=%ld, MAXRELSUP=%ld\n",
                    298:                   KC2, KC, KCZ, KCZ2, MAXRELSUP);
                    299:       for (i=1; i<=KCZ; i++)
                    300:        fprintferr("++ idealbase[%ld] = %Z",i,idealbase[i]);
                    301:     }
                    302:     msgtimer("factor base");
                    303:   }
                    304:   return lfun;
                    305: }
                    306:
                    307: /* can we factor I / m ? (m pseudo minimum, computed in ideallllredpart1) */
                    308: static long
                    309: factorgen(GEN nf,GEN idealvec,long kcz,long limp)
                    310: {
                    311:   long i,j,n1,ip,v,p,k,lo,ifinal;
                    312:   GEN x,q,r,P,p1,listexpo;
                    313:   GEN I = (GEN)idealvec[1];
                    314:   GEN m = (GEN)idealvec[2];
                    315:   GEN Nm= absi( subres(gmul((GEN)nf[7],m), (GEN)nf[1]) ); /* |Nm| */
                    316:
                    317:   x = divii(Nm, dethnf_i(I)); /* m in I, so NI | Nm */
                    318:   if (is_pm1(x)) { primfact[0]=0; return 1; }
                    319:   listexpo = new_chunk(kcz+1);
                    320:   for (i=1; ; i++)
                    321:   {
                    322:     p=FB[i]; q=dvmdis(x,p,&r);
                    323:     for (k=0; !signe(r); k++) { x=q; q=dvmdis(x,p,&r); }
                    324:     listexpo[i] = k;
                    325:     if (cmpis(q,p)<=0) break;
                    326:     if (i==kcz) return 0;
                    327:   }
                    328:   if (cmpis(x,limp) > 0) return 0;
                    329:
                    330:   ifinal = i; lo = 0;
                    331:   for (i=1; i<=ifinal; i++)
                    332:   {
                    333:     k = listexpo[i];
                    334:     if (k)
                    335:     {
                    336:       p = FB[i]; p1 = idealbase[numFB[p]];
                    337:       n1 = lg(p1); ip = numideal[p];
                    338:       for (j=1; j<n1; j++)
                    339:       {
                    340:         P = (GEN)p1[j];
                    341:        v = idealval(nf,I, P) - element_val2(nf,m,Nm, P);
                    342:        if (v) /* hence < 0 */
                    343:        {
                    344:          primfact[++lo]=ip+j; expoprimfact[lo]=v;
                    345:          k += v * itos((GEN)P[4]);
                    346:          if (!k) break;
                    347:        }
                    348:       }
                    349:       if (k) return 0;
                    350:     }
                    351:   }
                    352:   if (is_pm1(x)) { primfact[0]=lo; return 1; }
                    353:
                    354:   p = itos(x); p1 = idealbase[numFB[p]];
                    355:   n1 = lg(p1); ip = numideal[p];
                    356:   for (k=1,j=1; j<n1; j++)
                    357:   {
                    358:     P = (GEN)p1[j];
                    359:     v = idealval(nf,I, P) - element_val2(nf,m,Nm, P);
                    360:     if (v)
                    361:     {
                    362:       primfact[++lo]=ip+j; expoprimfact[lo]=v;
                    363:       k += v*itos((GEN)P[4]);
                    364:       if (!k) { primfact[0]=lo; return 1; }
                    365:     }
                    366:   }
                    367:   return 0;
                    368: }
                    369:
                    370: /* can we factor x ? Nx = norm(x) */
                    371: static long
                    372: factorelt(GEN nf,GEN cbase,GEN x,GEN Nx,long kcz,long limp)
                    373: {
                    374:   long i,j,n1,ip,v,p,k,lo,ifinal;
                    375:   GEN q,r,P,p1,listexpo;
                    376:
                    377:   if (is_pm1(Nx)) { primfact[0]=0; return 1; }
                    378:   listexpo = new_chunk(kcz+1);
                    379:   for (i=1; ; i++)
                    380:   {
                    381:     p=FB[i]; q=dvmdis(Nx,p,&r);
                    382:     for (k=0; !signe(r); k++) { Nx=q; q=dvmdis(Nx,p,&r); }
                    383:     listexpo[i] = k;
                    384:     if (cmpis(q,p)<=0) break;
                    385:     if (i==kcz) return 0;
                    386:   }
                    387:   if (cmpis(Nx,limp) > 0) return 0;
                    388:
                    389:   if (cbase) x = gmul(cbase,x);
                    390:   ifinal=i; lo = 0;
                    391:   for (i=1; i<=ifinal; i++)
                    392:   {
                    393:     k = listexpo[i];
                    394:     if (k)
                    395:     {
                    396:       p = FB[i]; p1 = idealbase[numFB[p]];
                    397:       n1 = lg(p1); ip = numideal[p];
                    398:       for (j=1; j<n1; j++)
                    399:       {
                    400:         P = (GEN)p1[j];
                    401:        v = int_elt_val(nf,x,(GEN)P[1],(GEN)P[5], NULL, k);
                    402:        if (v)
                    403:        {
                    404:          primfact[++lo]=ip+j; expoprimfact[lo]=v;
                    405:          k -= v * itos((GEN)P[4]);
                    406:          if (!k) break;
                    407:        }
                    408:       }
                    409:       if (k) return 0;
                    410:     }
                    411:   }
                    412:   if (is_pm1(Nx)) { primfact[0]=lo; return 1; }
                    413:
                    414:   p = itos(Nx); p1 = idealbase[numFB[p]];
                    415:   n1 = lg(p1); ip = numideal[p];
                    416:   for (k=1,j=1; j<n1; j++)
                    417:   {
                    418:     P = (GEN)p1[j];
                    419:     v = int_elt_val(nf,x,(GEN)P[1],(GEN)P[5], NULL, k);
                    420:     if (v)
                    421:     {
                    422:       primfact[++lo]=ip+j; expoprimfact[lo]=v;
                    423:       k -= v*itos((GEN)P[4]);
                    424:       if (!k) { primfact[0]=lo; return 1; }
                    425:     }
                    426:   }
                    427:   return 0;
                    428: }
                    429:
                    430: static GEN
                    431: cleancol(GEN x,long N,long PRECREG)
                    432: {
                    433:   long i,j,av,tetpil,tx=typ(x),R1,RU;
                    434:   GEN s,s2,re,pi4,im,y;
                    435:
                    436:   if (tx==t_MAT)
                    437:   {
                    438:     y=cgetg(lg(x),tx);
                    439:     for (j=1; j<lg(x); j++)
                    440:       y[j]=(long)cleancol((GEN)x[j],N,PRECREG);
                    441:     return y;
                    442:   }
                    443:   if (!is_vec_t(tx)) err(talker,"not a vector/matrix in cleancol");
                    444:   av = avma; RU=lg(x)-1; R1 = (RU<<1)-N;
                    445:   re = greal(x); s=(GEN)re[1]; for (i=2; i<=RU; i++) s=gadd(s,(GEN)re[i]);
                    446:   im = gimag(x); s = gdivgs(s,-N);
                    447:   s2 = (N>R1)? gmul2n(s,1): NULL;
                    448:   pi4=gmul2n(mppi(PRECREG),2);
                    449:   tetpil=avma; y=cgetg(RU+1,tx);
                    450:   for (i=1; i<=RU; i++)
                    451:   {
                    452:     GEN p1=cgetg(3,t_COMPLEX); y[i]=(long)p1;
                    453:     p1[1] = ladd((GEN)re[i], (i<=R1)?s:s2);
                    454:     p1[2] = lmod((GEN)im[i], pi4);
                    455:   }
                    456:   return gerepile(av,tetpil,y);
                    457: }
                    458:
                    459: #define RELAT 0
                    460: #define LARGE 1
                    461: #define PRECI 2
                    462: static GEN
                    463: not_given(long av, long flun, long reason)
                    464: {
                    465:   if (labs(flun)==2)
                    466:   {
                    467:     char *s;
                    468:     switch(reason)
                    469:     {
                    470:       case RELAT: s = "not enough relations for fundamental units"; break;
                    471:       case LARGE: s = "fundamental units too large"; break;
                    472:       case PRECI: s = "insufficient precision for fundamental units"; break;
                    473:       default: s = "unknown problem with fundamental units";
                    474:     }
                    475:     err(warner,"%s, not given",s);
                    476:   }
                    477:   avma=av; return cgetg(1,t_MAT);
                    478: }
                    479:
                    480: /* check whether exp(x) will get too big */
                    481: static long
                    482: expgexpo(GEN x)
                    483: {
                    484:   long i,j,e, E = -HIGHEXPOBIT;
                    485:   GEN p1;
                    486:
                    487:   for (i=1; i<lg(x); i++)
                    488:     for (j=1; j<lg(x[1]); j++)
                    489:     {
                    490:       p1 = gmael(x,i,j);
                    491:       if (typ(p1)==t_COMPLEX) p1 = (GEN)p1[1];
                    492:       e = gexpo(p1); if (e>E) E=e;
                    493:     }
                    494:   return E;
                    495: }
                    496:
                    497: static GEN
                    498: split_realimag_col(GEN z, long r1, long r2)
                    499: {
                    500:   long i, ru = r1+r2;
                    501:   GEN a, x = cgetg(ru+r2+1,t_COL), y = x + r2;
                    502:   for (i=1; i<=r1; i++) { a = (GEN)z[i]; x[i] = lreal(a); }
                    503:   for (   ; i<=ru; i++) { a = (GEN)z[i]; x[i] = lreal(a); y[i] = limag(a); }
                    504:   return x;
                    505: }
                    506:
                    507: static GEN
                    508: split_realimag(GEN x, long r1, long r2)
                    509: {
                    510:   long i,l; GEN y;
                    511:   if (typ(x) == t_COL) return split_realimag_col(x,r1,r2);
                    512:   l = lg(x); y = cgetg(l, t_MAT);
                    513:   for (i=1; i<l; i++) y[i] = (long)split_realimag_col((GEN)x[i], r1, r2);
                    514:   return y;
                    515: }
                    516:
                    517: /* assume x = (r1+r2) x (r1+2r2) matrix and y compatible vector
                    518:  * r1 first lines of x,y are real. Solve the system obtained by splitting
                    519:  * real and imaginary parts. If x is of nf type, use M instead.
                    520:  */
                    521: static GEN
                    522: gauss_realimag(GEN x, GEN y)
                    523: {
                    524:   GEN M = (typ(x)==t_VEC)? gmael(checknf(x),5,1): x;
                    525:   long l = lg(M), r2 = l - lg(M[1]), r1 = l-1 - 2*r2;
                    526:   M = split_realimag(M,r1,r2);
                    527:   y = split_realimag(y,r1,r2); return gauss(M, y);
                    528: }
                    529:
                    530: static GEN
                    531: getfu(GEN nf,GEN *ptxarch,GEN reg,long flun,long *pte,long prec)
                    532: {
                    533:   long av = avma,e,i,j,R1,RU,N=degpol(nf[1]);
                    534:   GEN p1,p2,u,y,matep,s,xarch,vec;
                    535:   GEN *gptr[2];
                    536:
                    537:   if (DEBUGLEVEL) fprintferr("\n#### Computing fundamental units\n");
                    538:   R1 = itos(gmael(nf,2,1)); RU = (N+R1)>>1;
                    539:   if (RU==1) { *pte=BIGINT; return cgetg(1,t_VEC); }
                    540:
                    541:   *pte = 0; xarch = *ptxarch;
                    542:   if (gexpo(reg) < -8) return not_given(av,flun,RELAT);
                    543:
                    544:   matep = cgetg(RU,t_MAT);
                    545:   for (j=1; j<RU; j++)
                    546:   {
                    547:     s = gzero; for (i=1; i<=RU; i++) s = gadd(s,greal(gcoeff(xarch,i,j)));
                    548:     s = gdivgs(s, -N);
                    549:     p1=cgetg(RU+1,t_COL); matep[j]=(long)p1;
                    550:     for (i=1; i<=R1; i++) p1[i] = ladd(s, gcoeff(xarch,i,j));
                    551:     for (   ; i<=RU; i++) p1[i] = ladd(s, gmul2n(gcoeff(xarch,i,j),-1));
                    552:   }
                    553:   if (prec <= 0) prec = gprecision(xarch);
                    554:   u = lllintern(greal(matep),1,prec);
                    555:   if (!u) return not_given(av,flun,PRECI);
                    556:
                    557:   p1 = gmul(matep,u);
                    558:   if (expgexpo(p1) > 20) { *pte = BIGINT; return not_given(av,flun,LARGE); }
                    559:   matep = gexp(p1,prec);
                    560:   y = grndtoi(gauss_realimag(nf,matep), &e);
                    561:   *pte = -e;
                    562:   if (e>=0) return not_given(av,flun,PRECI);
                    563:   for (j=1; j<RU; j++)
                    564:     if (!gcmp1(idealnorm(nf, (GEN)y[j]))) break;
                    565:   if (j < RU) { *pte = 0; return not_given(av,flun,PRECI); }
                    566:   xarch = gmul(xarch,u);
                    567:
                    568:   /* y[i] are unit generators. Normalize: smallest L2 norm + lead coeff > 0 */
                    569:   y = gmul((GEN)nf[7], y);
                    570:   vec = cgetg(RU+1,t_COL); p2 = mppi(prec);
                    571:   p1 = pureimag(p2);
                    572:   p2 = pureimag(gmul2n(p2,1));
                    573:   for (i=1; i<=R1; i++) vec[i]=(long)p1;
                    574:   for (   ; i<=RU; i++) vec[i]=(long)p2;
                    575:   for (j=1; j<RU; j++)
                    576:   {
                    577:     p1 = (GEN)y[j]; p2 = ginvmod(p1, (GEN)nf[1]);
                    578:     if (gcmp(QuickNormL2(p2,DEFAULTPREC),
                    579:              QuickNormL2(p1,DEFAULTPREC)) < 0)
                    580:     {
                    581:       xarch[j] = lneg((GEN)xarch[j]);
                    582:       p1 = p2;
                    583:     }
                    584:     if (gsigne(leading_term(p1)) < 0)
                    585:     {
                    586:       xarch[j] = ladd((GEN)xarch[j], vec);
                    587:       p1 = gneg(p1);
                    588:     }
                    589:     y[j] = (long)p1;
                    590:   }
                    591:   if (DEBUGLEVEL) msgtimer("getfu");
                    592:   *ptxarch=xarch; gptr[0]=ptxarch; gptr[1]=&y;
                    593:   gerepilemany(av,gptr,2); return y;
                    594: }
                    595: #undef RELAT
                    596: #undef LARGE
                    597: #undef PRECI
                    598:
                    599: GEN
                    600: buchfu(GEN bnf)
                    601: {
                    602:   long av = avma, c;
                    603:   GEN nf,xarch,reg,res, y = cgetg(3,t_VEC);
                    604:
                    605:   bnf = checkbnf(bnf); xarch = (GEN)bnf[3]; nf = (GEN)bnf[7];
                    606:   res = (GEN)bnf[8]; reg = (GEN)res[2];
                    607:   if (lg(res)==7 && lg(res[5])==lg(nf[6])-1)
                    608:   {
                    609:     y[1] = lcopy((GEN)res[5]);
                    610:     y[2] = lcopy((GEN)res[6]); return y;
                    611:   }
                    612:   y[1] = (long)getfu(nf,&xarch,reg,2,&c,0);
                    613:   y[2] = lstoi(c); return gerepilecopy(av, y);
                    614: }
                    615:
                    616: /*******************************************************************/
                    617: /*                                                                 */
                    618: /*           PRINCIPAL IDEAL ALGORITHM (DISCRETE LOG)              */
                    619: /*                                                                 */
                    620: /*******************************************************************/
                    621:
                    622: /* gen: prime ideals, return Norm (product), bound for denominator.
                    623:  * C = possible extra prime (^1) or NULL */
                    624: static GEN
                    625: get_norm_fact_primes(GEN gen, GEN ex, GEN C, GEN *pd)
                    626: {
                    627:   GEN N,d,P,p,e;
                    628:   long i,s,c = lg(ex);
                    629:   d = N = gun;
                    630:   for (i=1; i<c; i++)
                    631:     if ((s = signe(ex[i])))
                    632:     {
                    633:       P = (GEN)gen[i]; e = (GEN)ex[i]; p = (GEN)P[1];
                    634:       N = gmul(N, powgi(p, mulii((GEN)P[4], e)));
                    635:       if (s < 0)
                    636:       {
                    637:         e = gceil(gdiv(negi(e), (GEN)P[3]));
                    638:         d = mulii(d, powgi(p, e));
                    639:       }
                    640:     }
                    641:   if (C)
                    642:   {
                    643:     P = C; p = (GEN)P[1];
                    644:     N = gmul(N, powgi(p, (GEN)P[4]));
                    645:   }
                    646:   *pd = d; return N;
                    647: }
                    648:
                    649: /* gen: HNF ideals */
                    650: static GEN
                    651: get_norm_fact(GEN gen, GEN ex, GEN *pd)
                    652: {
                    653:   long i, c = lg(ex);
                    654:   GEN d,N,I,e,n,ne,de;
                    655:   d = N = gun;
                    656:   for (i=1; i<c; i++)
                    657:     if (signe(ex[i]))
                    658:     {
                    659:       I = (GEN)gen[i]; e = (GEN)ex[i]; n = dethnf_i(I);
                    660:       ne = powgi(n,e);
                    661:       de = egalii(n, gcoeff(I,1,1))? ne: powgi(gcoeff(I,1,1), e);
                    662:       N = mulii(N, ne);
                    663:       d = mulii(d, de);
                    664:     }
                    665:   *pd = d; return N;
                    666: }
                    667:
                    668: /* try to split ideal / (some integer) on FB */
                    669: static long
                    670: factorgensimple(GEN nf,GEN ideal)
                    671: {
                    672:   long N,i,v,av1 = avma,lo, L = lg(vectbase);
                    673:   GEN x;
                    674:   if (typ(ideal) != t_MAT) ideal = (GEN)ideal[1]; /* idele */
                    675:   x = dethnf_i(ideal);
                    676:   N = lg(ideal)-1;
                    677:   if (gcmp1(x)) { avma=av1; primfact[0]=0; return 1; }
                    678:   for (lo=0, i=1; i<L; i++)
                    679:   {
                    680:     GEN q,y, P=(GEN)vectbase[i], p=(GEN)P[1];
                    681:     long vx0, vx, sum_ef, e,f,lo0,i0;
                    682:
                    683:     vx = pvaluation(x,p,&y);
                    684:     if (!vx) continue;
                    685:     /* p | x = Nideal */
                    686:     vx0 = vx; sum_ef = 0; lo0 =lo; i0 = i;
                    687:     for(;;)
                    688:     {
                    689:       e = itos((GEN)P[3]);
                    690:       f = itos((GEN)P[4]); sum_ef += e * f;
                    691:       v = idealval(nf,ideal,P);
                    692:       if (v)
                    693:       {
                    694:         lo++; primfact[lo]=i; expoprimfact[lo]=v;
                    695:         vx -= v * f; if (!vx) break;
                    696:       }
                    697:       i++; if (i == L) break;
                    698:       P = (GEN)vectbase[i]; q = (GEN)P[1];
                    699:       if (!egalii(p,q)) break;
                    700:     }
                    701:     if (vx)
                    702:     { /* divisible by P | p not in FB */
                    703:       long k,l,n;
                    704:       k = N - sum_ef;
                    705:       if (vx % k) break;
                    706:       k = vx / k; /* ideal / p^k may factor on FB */
                    707:       for (l = lo0+1; l <= lo; l++)
                    708:       {
                    709:         P = (GEN)vectbase[primfact[l]];
                    710:         expoprimfact[l] -= k * itos((GEN)P[3]); /* may become 0 */
                    711:       }
                    712:       n = lo0+1;
                    713:       for (l = i0; l < i; l++) /* update exponents for other P | p */
                    714:       {
                    715:         if (n <= lo && primfact[n] == l) { n++; continue; }
                    716:         lo++; primfact[lo] = l; P = (GEN)vectbase[l];
                    717:         expoprimfact[lo] = - k * itos((GEN)P[3]);
                    718:       }
                    719:       /* check that ideal / p^k / (tentative factorisation) is integral */
                    720:       {
                    721:         GEN z = ideal;
                    722:         for (l = lo0+1; l <= lo; l++)
                    723:         {
                    724:           GEN n = stoi(- expoprimfact[l]);
                    725:           z = idealmulpowprime(nf, z, (GEN)vectbase[primfact[l]], n);
                    726:         }
                    727:         z = gdiv(z, gpowgs(p, k));
                    728:         if (!gcmp1(denom(z))) { avma=av1; return 0; }
                    729:         ideal = z;
                    730:       }
                    731:     }
                    732:     if (gcmp1(y)) { avma=av1; primfact[0]=lo; return 1; }
                    733:     x = y;
                    734:   }
                    735:   avma=av1; return 0;
                    736: }
                    737:
                    738: static void
                    739: add_to_fact(long l, long v, long e)
                    740: {
                    741:   long i,lo;
                    742:   if (!e) return;
                    743:   for (i=1; i<=l && primfact[i] < v; i++)/*empty*/;
                    744:   if (i <= l && primfact[i] == v)
                    745:     expoprimfact[i] += e;
                    746:   else
                    747:   {
                    748:     lo = ++primfact[0];
                    749:     primfact[lo] = v;
                    750:     expoprimfact[lo] = e;
                    751:   }
                    752: }
                    753:
                    754: static void
                    755: init_sub(long l, GEN perm, GEN *v, GEN *ex)
                    756: {
                    757:   long i;
                    758:   *v = cgetg(l,t_VECSMALL);
                    759:   *ex= cgetg(l,t_VECSMALL);
                    760:   for (i=1; i<l; i++) (*v)[i] = itos((GEN)perm[i]);
                    761: }
                    762:
                    763: /* factor x = x0[1] on vectbase (modulo principal ideals).
                    764:  * We may have x0[2] = NULL (principal part not wanted), in which case,
                    765:  * don't compute archimedean parts */
                    766: static GEN
                    767: split_ideal(GEN nf, GEN x0, long prec, GEN vperm)
                    768: {
                    769:   GEN p1,vdir,id,z,v,ex,y, x = (GEN)x0[1];
                    770:   long nbtest_lim,nbtest,bou,i,ru, lgsub;
                    771:   int flag = (gexpo(gcoeff(x,1,1)) < 100);
                    772:
                    773:   y = x0;
                    774:   if (flag && factorgensimple(nf,y)) return y;
                    775:
                    776:   y = ideallllred(nf,x0,NULL,prec);
                    777:   if (flag &&  ((!x0[2] && gegal((GEN)y[1], (GEN)x[1]))
                    778:              ||  (x0[2] && gcmp0((GEN)y[2])))) flag = 0; /* y == x0 */
                    779:   if (flag && factorgensimple(nf,y)) return y;
                    780:
                    781:   z = init_idele(nf); ru = lg(z[2]);
                    782:   if (!x0[2]) { z[2] = 0; x0 = x; } /* stop cheating */
                    783:   vdir = cgetg(ru,t_VEC);
                    784:   for (i=2; i<ru; i++) vdir[i]=zero;
                    785:   for (i=1; i<ru; i++)
                    786:   {
                    787:     vdir[i]=lstoi(10);
                    788:     y = ideallllred(nf,x0,vdir,prec);
                    789:     if (factorgensimple(nf,y)) return y;
                    790:     vdir[i]=zero;
                    791:   }
                    792:   nbtest = 0; nbtest_lim = (ru-1) << 2; lgsub = 3;
                    793:   init_sub(lgsub, vperm, &v, &ex);
                    794:   for(;;)
                    795:   {
                    796:     int non0 = 0;
                    797:     id = x0;
                    798:     for (i=1; i<lgsub; i++)
                    799:     {
                    800:       ex[i] = mymyrand() >> randshift;
                    801:       if (ex[i])
                    802:       { /* don't let id become too large as lgsub gets bigger: avoid
                    803:            prec problems */
                    804:         if (non0) id = ideallllred(nf,id,NULL,prec);
                    805:         non0++;
                    806:         z[1]=vectbase[v[i]]; p1=idealpowred(nf,z,stoi(ex[i]),prec);
                    807:         id = idealmulh(nf,id,p1);
                    808:       }
                    809:     }
                    810:     if (id == x0) continue;
                    811:
                    812:     for (i=1; i<ru; i++) vdir[i] = lstoi(mymyrand() >> randshift);
                    813:     for (bou=1; bou<ru; bou++)
                    814:     {
                    815:       if (bou>1)
                    816:       {
                    817:         for (i=1; i<ru; i++) vdir[i]=zero;
                    818:         vdir[bou]=lstoi(10);
                    819:       }
                    820:       nbtest++;
                    821:       y = ideallllred(nf,id,vdir,prec);
                    822:       if (DEBUGLEVEL>2)
                    823:         fprintferr("nbtest = %ld, ideal = %Z\n",nbtest,y[1]);
                    824:       if (factorgensimple(nf,y))
                    825:       {
                    826:         long l = primfact[0];
                    827:         for (i=1; i<lgsub; i++) add_to_fact(l,v[i],-ex[i]);
                    828:         return y;
                    829:       }
                    830:     }
                    831:     if (nbtest > nbtest_lim)
                    832:     {
                    833:       nbtest = 0;
                    834:       if (lgsub < 7)
                    835:       {
                    836:         lgsub++; nbtest_lim <<= 2;
                    837:         init_sub(lgsub, vperm, &v, &ex);
                    838:       }
                    839:       else nbtest_lim = VERYBIGINT; /* don't increase further */
                    840:       if (DEBUGLEVEL)
                    841:         fprintferr("split_ideal: increasing factor base [%ld]\n",lgsub);
                    842:     }
                    843:   }
                    844: }
                    845:
                    846: static void
                    847: get_split_expo(GEN xalpha, GEN yalpha, GEN vperm)
                    848: {
                    849:   long i, colW = lg(xalpha)-1;
                    850:   GEN vinvperm = new_chunk(lg(vectbase));
                    851:   for (i=1; i<lg(vectbase); i++) vinvperm[itos((GEN)vperm[i])]=i;
                    852:   for (i=1; i<=primfact[0]; i++)
                    853:   {
                    854:     long k = vinvperm[primfact[i]];
                    855:     long l = k - colW;
                    856:     if (l <= 0) xalpha[k]=lstoi(expoprimfact[i]);
                    857:     else        yalpha[l]=lstoi(expoprimfact[i]);
                    858:   }
                    859: }
                    860:
                    861: GEN
                    862: init_red_mod_units(GEN bnf, long prec)
                    863: {
                    864:   GEN z, s = gzero, p1,s1,mat, matunit = (GEN)bnf[3];
                    865:   long i,j, RU = lg(matunit);
                    866:
                    867:   if (RU == 1) return NULL;
                    868:   mat = cgetg(RU,t_MAT);
                    869:   for (j=1; j<RU; j++)
                    870:   {
                    871:     p1=cgetg(RU+1,t_COL); mat[j]=(long)p1;
                    872:     s1=gzero;
                    873:     for (i=1; i<RU; i++)
                    874:     {
                    875:       p1[i] = lreal(gcoeff(matunit,i,j));
                    876:       s1 = gadd(s1, gsqr((GEN)p1[i]));
                    877:     }
                    878:     p1[RU]=zero; if (gcmp(s1,s) > 0) s = s1;
                    879:   }
                    880:   s = gsqrt(gmul2n(s,RU),prec);
                    881:   if (gcmpgs(s,100000000) < 0) s = stoi(100000000);
                    882:   z = cgetg(3,t_VEC);
                    883:   z[1] = (long)mat;
                    884:   z[2] = (long)s; return z;
                    885: }
                    886:
                    887: /* z computed above. Return unit exponents that would reduce col (arch) */
                    888: GEN
                    889: red_mod_units(GEN col, GEN z, long prec)
                    890: {
                    891:   long i,RU;
                    892:   GEN x,mat,N2;
                    893:
                    894:   if (!z) return NULL;
                    895:   mat= (GEN)z[1];
                    896:   N2 = (GEN)z[2];
                    897:   RU = lg(mat); x = cgetg(RU+1,t_COL);
                    898:   for (i=1; i<RU; i++) x[i]=lreal((GEN)col[i]);
                    899:   x[RU] = (long)N2;
                    900:   x = lllintern(concatsp(mat,x), 1,prec);
                    901:   if (!x) return NULL;
                    902:   x = (GEN)x[RU];
                    903:   if (signe(x[RU]) < 0) x = gneg_i(x);
                    904:   if (!gcmp1((GEN)x[RU])) err(bugparier,"red_mod_units");
                    905:   setlg(x,RU); return x;
                    906: }
                    907:
                    908: /* clg2 format changed for version 2.0.21 (contained ideals, now archs)
                    909:  * Compatibility mode: old clg2 format */
                    910: static GEN
                    911: get_Garch(GEN nf, GEN gen, GEN clg2, long prec)
                    912: {
                    913:   long i,c;
                    914:   GEN g,z,J,Garch, clorig = (GEN)clg2[3];
                    915:
                    916:   c = lg(gen); Garch = cgetg(c,t_MAT);
                    917:   for (i=1; i<c; i++)
                    918:   {
                    919:     g = (GEN)gen[i];
                    920:     z = (GEN)clorig[i]; J = (GEN)z[1];
                    921:     if (!gegal(g,J))
                    922:     {
                    923:       z = idealinv(nf,z); J = (GEN)z[1];
                    924:       J = gmul(J,denom(J));
                    925:       if (!gegal(g,J))
                    926:       {
                    927:         z = ideallllred(nf,z,NULL,prec); J = (GEN)z[1];
                    928:         if (!gegal(g,J))
                    929:           err(bugparier,"isprincipal (incompatible bnf generators)");
                    930:       }
                    931:     }
                    932:     Garch[i] = z[2];
                    933:   }
                    934:   return Garch;
                    935: }
                    936:
                    937: /* [x] archimedian components, A column vector. return [x] A
                    938:  * x may be a translated GEN (y + k) */
                    939: static GEN
                    940: act_arch(GEN A, GEN x)
                    941: {
                    942:   GEN z, a;
                    943:   long i,l = lg(A);
                    944:   if (typ(A) == t_MAT)
                    945:   {
                    946:     /* assume lg(x) >= l */
                    947:     z = cgetg(l, t_VEC);
                    948:     for (i=1; i<l; i++) z[i] = (long)act_arch((GEN)A[i], x);
                    949:     return z;
                    950:   }
                    951:   /* A a t_COL of t_INT. Assume lg(A)==lg(x) */
                    952:   l = lg(A); z = cgetg(l, t_VEC);
                    953:   if (l==1) return z;
                    954:   a = gmul((GEN)A[1], (GEN)x[1]);
                    955:   for (i=2; i<l; i++)
                    956:     if (signe(A[i])) a = gadd(a, gmul((GEN)A[i], (GEN)x[i]));
                    957:   settyp(a, t_VEC); return a;
                    958: }
                    959:
                    960: static long
                    961: prec_arch(GEN bnf)
                    962: {
                    963:   GEN a = (GEN)bnf[4];
                    964:   long i, l = lg(a), prec;
                    965:
                    966:   for (i=1; i<l; i++)
                    967:     if ( (prec = gprecision((GEN)a[i])) ) return prec;
                    968:   return DEFAULTPREC;
                    969: }
                    970:
                    971: /* col = archimedian components of x, Nx = kNx^e its norm, dx a bound for its
                    972:  * denominator. Return x or NULL (fail) */
                    973: GEN
                    974: isprincipalarch(GEN bnf, GEN col, GEN kNx, GEN e, GEN dx, long *pe)
                    975: {
                    976:   GEN nf, x, matunit, s;
                    977:   long N, R1, RU, i, prec = gprecision(col);
                    978:   bnf = checkbnf(bnf); nf = checknf(bnf);
                    979:   if (!prec) prec = prec_arch(bnf);
                    980:   matunit = (GEN)bnf[3];
                    981:   N = degpol(nf[1]);
                    982:   R1 = itos(gmael(nf,2,1));
                    983:   RU = (N + R1)>>1;
                    984:   col = cleancol(col,N,prec); settyp(col, t_COL);
                    985:   if (RU > 1)
                    986:   { /* reduce mod units */
                    987:     GEN u, z = init_red_mod_units(bnf,prec);
                    988:     u = red_mod_units(col,z,prec);
                    989:     if (!u && z) return NULL;
                    990:     if (u) col = gadd(col, gmul(matunit, u));
                    991:   }
                    992:   s = gdivgs(gmul(e, glog(kNx,prec)), N);
                    993:   for (i=1; i<=R1; i++) col[i] = lexp(gadd(s, (GEN)col[i]),prec);
                    994:   for (   ; i<=RU; i++) col[i] = lexp(gadd(s, gmul2n((GEN)col[i],-1)),prec);
                    995:   /* d.alpha such that x = alpha \prod gj^ej */
                    996:   x = grndtoi(gmul(dx, gauss_realimag(nf,col)), pe);
                    997:   return (*pe > -5)? NULL: gdiv(x, dx);
                    998: }
                    999:
                   1000: /* y = C \prod g[i]^e[i] ? */
                   1001: static int
                   1002: fact_ok(GEN nf, GEN y, GEN C, GEN g, GEN e)
                   1003: {
                   1004:   long i, c = lg(e);
                   1005:   GEN z = C? C: gun;
                   1006:   for (i=1; i<c; i++)
                   1007:     if (signe(e[i])) z = idealmul(nf, z, idealpow(nf, (GEN)g[i], (GEN)e[i]));
                   1008:   if (typ(z) != t_MAT) z = idealhermite(nf,z);
                   1009:   if (typ(y) != t_MAT) y = idealhermite(nf,y);
                   1010:   return gegal(y, z);
                   1011: }
                   1012:
                   1013: /* assume x in HNF. cf class_group_gen for notations */
                   1014: static GEN
                   1015: isprincipalall0(GEN bnf, GEN x, long *ptprec, long flag)
                   1016: {
                   1017:   long i,lW,lB,e,c, prec = *ptprec;
                   1018:   GEN Q,xar,Wex,Bex,U,y,p1,gen,cyc,xc,ex,d,col,A;
                   1019:   GEN W       = (GEN)bnf[1];
                   1020:   GEN B       = (GEN)bnf[2];
                   1021:   GEN WB_C    = (GEN)bnf[4];
                   1022:   GEN vperm   = (GEN)bnf[6];
                   1023:   GEN nf      = (GEN)bnf[7];
                   1024:   GEN clg2    = (GEN)bnf[9];
                   1025:   int old_format = (typ(clg2[2]) == t_MAT);
                   1026:
                   1027:   U = (GEN)clg2[1];
                   1028:   cyc = gmael3(bnf,8,1,2); c = lg(cyc)-1;
                   1029:   gen = gmael3(bnf,8,1,3);
                   1030:
                   1031:   vectbase = (GEN)bnf[5]; /* needed by factorgensimple */
                   1032:
                   1033:   /* factor x */
                   1034:   xc = content(x); if (!gcmp1(xc)) x = gdiv(x,xc);
                   1035:
                   1036:   p1 = init_idele(nf); p1[1] = (long)x;
                   1037:   if (!(flag & nf_GEN)) p1[2] = 0; /* don't compute archimedean part */
                   1038:   xar = split_ideal(nf,p1,prec,vperm);
                   1039:
                   1040:   lW = lg(W)-1; Wex = zerocol(lW);
                   1041:   lB = lg(B)-1; Bex = zerocol(lB); get_split_expo(Wex,Bex,vperm);
                   1042:
                   1043:   /* x = g_W Wex + g_B Bex - [xar]
                   1044:    *   = g_W A - [xar] + [C_B]Bex  since g_W B + g_B = [C_B] */
                   1045:   A = gsub(Wex, gmul(B,Bex));
                   1046:   if (old_format) U = ginv(U);
                   1047:   Q = gmul(U, A);
                   1048:   ex = cgetg(c+1,t_COL);
                   1049:   for (i=1; i<=c; i++)
                   1050:     Q[i] = (long)truedvmdii((GEN)Q[i],(GEN)cyc[i],(GEN*)(ex+i));
                   1051:   if (!(flag & nf_GEN)) return gcopy(ex);
                   1052:
                   1053:   /* compute arch component of the missing principal ideal */
                   1054:   if (old_format)
                   1055:   {
                   1056:     GEN Garch, V = (GEN)clg2[2];
                   1057:     p1 = c? concatsp(gmul(V,Q), Bex): Bex;
                   1058:     col = act_arch(p1, WB_C);
                   1059:     if (c)
                   1060:     {
                   1061:       Garch = get_Garch(nf,gen,clg2,prec);
                   1062:       col = gadd(col, act_arch(ex, Garch));
                   1063:     }
                   1064:   }
                   1065:   else
                   1066:   { /* g A = G Ur A + [ga]A, Ur A = D Q + R as above (R = ex)
                   1067:            = G R + [GD]Q + [ga]A */
                   1068:     GEN ga = (GEN)clg2[2], GD = (GEN)clg2[3];
                   1069:     col = act_arch(Bex, WB_C + lW);
                   1070:     if (lW) col = gadd(col, act_arch(A, ga));
                   1071:     if (c)  col = gadd(col, act_arch(Q, GD));
                   1072:   }
                   1073:   col = gsub(col, (GEN)xar[2]);
                   1074:
                   1075:   /* find coords on Zk; Q = N (x / \prod gj^ej) = N(alpha), denom(alpha) | d */
                   1076:   Q = gdiv(dethnf_i(x), get_norm_fact(gen, ex, &d));
                   1077:   col = isprincipalarch(bnf, col, Q, gun, d, &e);
                   1078:   if (col && !fact_ok(nf,x, col,gen,ex)) col = NULL;
                   1079:   if (!col)
                   1080:   {
                   1081:     *ptprec = prec + (e >> TWOPOTBITS_IN_LONG) + (MEDDEFAULTPREC-2);
                   1082:     if (flag & nf_FORCE)
                   1083:     {
                   1084:       if (DEBUGLEVEL) err(warner,"precision too low for generators, e = %ld",e);
                   1085:       return NULL;
                   1086:     }
                   1087:     err(warner,"precision too low for generators, not given");
                   1088:     e = 0;
                   1089:   }
                   1090:   y = cgetg(4,t_VEC);
                   1091:   y[1] = lcopy(ex);
                   1092:   y[2] = e? lmul(xc,col): lgetg(1,t_COL);
                   1093:   y[3] = lstoi(-e); return y;
                   1094: }
                   1095:
                   1096: static GEN
                   1097: triv_gen(GEN nf, GEN x, long c, long flag)
                   1098: {
                   1099:   GEN y;
                   1100:   if (!(flag & nf_GEN)) return zerocol(c);
                   1101:   y = cgetg(4,t_VEC);
                   1102:   y[1] = (long)zerocol(c);
                   1103:   x = (typ(x) == t_COL)? gcopy(x): algtobasis(nf,x);
                   1104:   y[2] = (long)x;
                   1105:   y[3] = lstoi(BIGINT); return y;
                   1106: }
                   1107:
                   1108: GEN
                   1109: isprincipalall(GEN bnf,GEN x,long flag)
                   1110: {
                   1111:   long av = avma,c,pr, tx = typ(x);
                   1112:   GEN nf;
                   1113:
                   1114:   bnf = checkbnf(bnf); nf = (GEN)bnf[7];
                   1115:   if (tx == t_POLMOD)
                   1116:   {
                   1117:     if (!gegal((GEN)x[1],(GEN)nf[1]))
                   1118:       err(talker,"not the same number field in isprincipal");
                   1119:     x = (GEN)x[2]; tx = t_POL;
                   1120:   }
                   1121:   if (tx == t_POL || tx == t_COL)
                   1122:   {
                   1123:     if (gcmp0(x)) err(talker,"zero ideal in isprincipal");
                   1124:     return triv_gen(nf, x, lg(mael3(bnf,8,1,2))-1, flag);
                   1125:   }
                   1126:   x = idealhermite(nf,x);
                   1127:   if (lg(x)==1) err(talker,"zero ideal in isprincipal");
                   1128:   if (lgef(nf[1])==4)
                   1129:     return gerepileupto(av, triv_gen(nf, gcoeff(x,1,1), 0, flag));
                   1130:
                   1131:   pr = prec_arch(bnf); /* precision of unit matrix */
                   1132:   c = getrand();
                   1133:   for (;;)
                   1134:   {
                   1135:     long av1 = avma;
                   1136:     GEN y = isprincipalall0(bnf,x,&pr,flag);
                   1137:     if (y) return gerepileupto(av,y);
                   1138:
                   1139:     if (DEBUGLEVEL) err(warnprec,"isprincipalall0",pr);
                   1140:     avma = av1; bnf = bnfnewprec(bnf,pr); setrand(c);
                   1141:   }
                   1142: }
                   1143:
                   1144: /* isprincipal for C * \prod P[i]^e[i] (C omitted if NULL) */
                   1145: GEN
                   1146: isprincipalfact(GEN bnf,GEN P, GEN e, GEN C, long flag)
                   1147: {
                   1148:   long av = avma, l = lg(e), i,prec,c;
                   1149:   GEN id,id2, nf = checknf(bnf), z = NULL; /* gcc -Wall */
                   1150:   int gen = flag & (nf_GEN | nf_GENMAT);
                   1151:
                   1152:   prec = prec_arch(bnf);
                   1153:   if (gen)
                   1154:   {
                   1155:     z = cgetg(3,t_VEC);
                   1156:     z[2] = (flag & nf_GENMAT)? lgetg(1, t_MAT): lmodulcp(gun,(GEN)nf[1]);
                   1157:   }
                   1158:   id = C;
                   1159:   for (i=1; i<l; i++) /* compute prod P[i]^e[i] */
                   1160:     if (signe(e[i]))
                   1161:     {
                   1162:       if (gen) z[1] = P[i]; else z = (GEN)P[i];
                   1163:       id2 = idealpowred(bnf,z, (GEN)e[i],prec);
                   1164:       id = id? idealmulred(nf,id,id2,prec): id2;
                   1165:     }
                   1166:   if (id == C)
                   1167:   {
                   1168:     if (!C) id = gun;
                   1169:     return isprincipalall(bnf, id, flag);
                   1170:   }
                   1171:   c = getrand();
                   1172:   for (;;)
                   1173:   {
                   1174:     long av1 = avma;
                   1175:     GEN y = isprincipalall0(bnf, gen? (GEN)id[1]: id,&prec,flag);
                   1176:     if (y)
                   1177:     {
                   1178:       if (gen && typ(y) == t_VEC)
                   1179:       {
                   1180:         GEN u = lift_intern(basistoalg(nf, (GEN)y[2]));
                   1181:         if (flag & nf_GENMAT)
                   1182:           y[2] = (gcmp1(u)&&lg(id[2])>1)? id[2]: (long)arch_mul((GEN)id[2], u);
                   1183:         else
                   1184:           y[2] = (long)algtobasis(nf, gmul((GEN)id[2], u));
                   1185:         y = gcopy(y);
                   1186:       }
                   1187:       return gerepileupto(av,y);
                   1188:     }
                   1189:
                   1190:     if (flag & nf_GIVEPREC)
                   1191:     {
                   1192:       if (DEBUGLEVEL)
                   1193:         err(warner,"insufficient precision for generators, not given");
                   1194:       avma = av; return stoi(prec);
                   1195:     }
                   1196:     if (DEBUGLEVEL) err(warnprec,"isprincipalall0",prec);
                   1197:     avma = av1; bnf = bnfnewprec(bnf,prec); setrand(c);
                   1198:   }
                   1199: }
                   1200:
                   1201: GEN
                   1202: isprincipal(GEN bnf,GEN x)
                   1203: {
                   1204:   return isprincipalall(bnf,x,nf_REGULAR);
                   1205: }
                   1206:
                   1207: GEN
                   1208: isprincipalgen(GEN bnf,GEN x)
                   1209: {
                   1210:   return isprincipalall(bnf,x,nf_GEN);
                   1211: }
                   1212:
                   1213: GEN
                   1214: isprincipalforce(GEN bnf,GEN x)
                   1215: {
                   1216:   return isprincipalall(bnf,x,nf_FORCE);
                   1217: }
                   1218:
                   1219: GEN
                   1220: isprincipalgenforce(GEN bnf,GEN x)
                   1221: {
                   1222:   return isprincipalall(bnf,x,nf_GEN | nf_FORCE);
                   1223: }
                   1224:
                   1225: GEN
                   1226: isunit(GEN bnf,GEN x)
                   1227: {
                   1228:   long av=avma,tetpil,tx = typ(x),i,R1,RU,n;
                   1229:   GEN p1,logunit,y,ex,nf,z,pi2_sur_w,gn,emb;
                   1230:
                   1231:   bnf = checkbnf(bnf); nf=(GEN)bnf[7];
                   1232:   logunit=(GEN)bnf[3]; RU=lg(logunit);
                   1233:   p1 = gmael(bnf,8,4); /* roots of 1 */
                   1234:   gn = (GEN)p1[1]; n = itos(gn);
                   1235:   z  = (GEN)p1[2];
                   1236:   switch(tx)
                   1237:   {
                   1238:     case t_INT: case t_FRAC: case t_FRACN:
                   1239:       if (!gcmp1(x) && !gcmp_1(x)) return cgetg(1,t_COL);
                   1240:       y = zerocol(RU); i = (gsigne(x) > 0)? 0: n>>1;
                   1241:       y[RU] = (long)gmodulss(i, n); return y;
                   1242:
                   1243:     case t_POLMOD:
                   1244:       if (!gegal((GEN)nf[1],(GEN)x[1]))
                   1245:         err(talker,"not the same number field in isunit");
                   1246:       x = (GEN)x[2]; /* fall through */
                   1247:     case t_POL:
                   1248:       p1 = x; x = algtobasis(bnf,x); break;
                   1249:
                   1250:     case t_COL:
                   1251:       if (lgef(nf[1])-2 == lg(x)) { p1 = basistoalg(nf,x); break; }
                   1252:
                   1253:     default:
                   1254:       err(talker,"not an algebraic number in isunit");
                   1255:   }
                   1256:   if (!gcmp1(denom(x))) { avma = av; return cgetg(1,t_COL); }
                   1257:   if (typ(p1) != t_POLMOD) p1 = gmodulcp(p1,(GEN)nf[1]);
                   1258:   p1 = gnorm(p1);
                   1259:   if (!is_pm1(p1)) { avma = av; return cgetg(1,t_COL); }
                   1260:
                   1261:   R1 = itos(gmael(nf,2,1)); p1 = cgetg(RU+1,t_COL);
                   1262:   for (i=1; i<=R1; i++) p1[i] = un;
                   1263:   for (   ; i<=RU; i++) p1[i] = deux;
                   1264:   logunit = concatsp(logunit,p1);
                   1265:   /* ex = fundamental units exponents */
                   1266:   {
                   1267:     GEN rx, rlog = greal(logunit);
                   1268:     long e, prec = nfgetprec(nf);
                   1269:     for (i=1;;)
                   1270:     {
                   1271:       rx = get_arch_real(nf,x,&emb, MEDDEFAULTPREC);
                   1272:       if (rx)
                   1273:       {
                   1274:         ex = grndtoi(gauss(rlog, rx), &e);
                   1275:         if (gcmp0((GEN)ex[RU]) && e < -4) break;
                   1276:       }
                   1277:
                   1278:       if (++i > 4) err(precer,"isunit");
                   1279:       prec = (prec-1)<<1;
                   1280:       if (DEBUGLEVEL) err(warnprec,"isunit",prec);
                   1281:       nf = nfnewprec(nf, prec);
                   1282:     }
                   1283:   }
                   1284:
                   1285:   setlg(ex, RU);
                   1286:   setlg(p1, RU); settyp(p1, t_VEC);
                   1287:   for (i=1; i<RU; i++) p1[i] = coeff(logunit, 1, i);
                   1288:   p1 = gneg(gimag(gmul(p1,ex))); if (!R1) p1 = gmul2n(p1, -1);
                   1289:   p1 = gadd(garg((GEN)emb[1],DEFAULTPREC), p1);
                   1290:   /* p1 = arg(the missing root of 1) */
                   1291:
                   1292:   pi2_sur_w = divrs(mppi(DEFAULTPREC), n>>1);
                   1293:   p1 = ground(gdiv(p1, pi2_sur_w));
                   1294:   if (n > 2)
                   1295:   {
                   1296:     GEN ro = gmael(nf,6,1);
                   1297:     GEN p2 = ground(gdiv(garg(poleval(z,ro), DEFAULTPREC), pi2_sur_w));
                   1298:     p1 = mulii(p1,  mpinvmod(p2, gn));
                   1299:   }
                   1300:
                   1301:   tetpil = avma; y = cgetg(RU+1,t_COL);
                   1302:   for (i=1; i<RU; i++) y[i] = lcopy((GEN)ex[i]);
                   1303:   y[RU] = lmodulcp(p1, gn); return gerepile(av,tetpil,y);
                   1304: }
                   1305:
                   1306: GEN
                   1307: signunits(GEN bnf)
                   1308: {
                   1309:   long av,i,j,R1,RU,mun;
                   1310:   GEN matunit,y,p1,p2,nf,pi;
                   1311:
                   1312:   bnf = checkbnf(bnf); nf = (GEN)bnf[7];
                   1313:   matunit = (GEN)bnf[3]; RU = lg(matunit);
                   1314:   R1=itos(gmael(nf,2,1)); pi=mppi(MEDDEFAULTPREC);
                   1315:   y=cgetg(RU,t_MAT); mun = lnegi(gun);
                   1316:   for (j=1; j<RU; j++)
                   1317:   {
                   1318:     p1=cgetg(R1+1,t_COL); y[j]=(long)p1; av=avma;
                   1319:     for (i=1; i<=R1; i++)
                   1320:     {
                   1321:       p2 = ground(gdiv(gimag(gcoeff(matunit,i,j)),pi));
                   1322:       p1[i] = mpodd(p2)? mun: un;
                   1323:     }
                   1324:     avma=av;
                   1325:   }
                   1326:   return y;
                   1327: }
                   1328:
                   1329: /* LLL-reduce ideal and return T2 | ideal */
                   1330: static GEN
                   1331: red_ideal(GEN *ideal,GEN T2vec,GEN prvec)
                   1332: {
                   1333:   long i;
                   1334:   for (i=1; i<lg(T2vec); i++)
                   1335:   {
                   1336:     GEN p1,base, T2 = (GEN)T2vec[i];
                   1337:     long prec = prvec[i];
                   1338:
                   1339:     p1 = qf_base_change(T2, *ideal, 1);
                   1340:     base = lllgramintern(p1,100,1,prec);
                   1341:     if (base)
                   1342:     {
                   1343:       p1 = sqred1intern(qf_base_change(p1,base,1),1);
                   1344:       if (p1) { *ideal = gmul(*ideal,base); return p1; }
                   1345:     }
                   1346:     if (DEBUGLEVEL) err(warner, "prec too low in red_ideal[%ld]: %ld",i,prec);
                   1347:   }
                   1348:   return NULL;
                   1349: }
                   1350:
                   1351: static double
                   1352: get_minkovski(long N, long R1, GEN D, GEN gborne)
                   1353: {
                   1354:   const long prec = DEFAULTPREC;
                   1355:   GEN p1,p2, pi = mppi(prec);
                   1356:   double bound;
                   1357:
                   1358:   p1 = gsqrt(gmulsg(N,gmul2n(pi,1)),prec);
                   1359:   p1 = gdiv(p1, gexp(stoi(N),prec));
                   1360:   p1 = gmulsg(N, gpui(p1, dbltor(2./(double)N),prec));
                   1361:   p2 = gpui(gdivsg(4,pi), gdivgs(stoi(N-R1),N),prec);
                   1362:   p1 = gmul(p1,p2);
                   1363:   bound = gtodouble(gmul(p1, gpui(absi(D), dbltor(1./(double)N),prec)));
                   1364:   bound *= gtodouble(gborne);
                   1365:   if (DEBUGLEVEL) { fprintferr("Bound for norms = %.0f\n",bound); flusherr(); }
                   1366:   return bound;
                   1367: }
                   1368:
                   1369: static void
                   1370: wr_rel(long *col)
                   1371: {
                   1372:   long i;
                   1373:   fprintferr("\nrel = ");
                   1374:   for (i=1; i<=KC; i++)
                   1375:     if (col[i]) fprintferr("%ld^%ld ",i,col[i]);
                   1376:   fprintferr("\n");
                   1377: }
                   1378:
                   1379: static void
                   1380: set_log_embed(GEN col, GEN x, long R1, long prec)
                   1381: {
                   1382:   long i, l = lg(x);
                   1383:   for (i=1; i<=R1; i++) gaffect(       glog((GEN)x[i],prec)    , (GEN)col[i]);
                   1384:   for (   ; i < l; i++) gaffect(gmul2n(glog((GEN)x[i],prec), 1), (GEN)col[i]);
                   1385: }
                   1386:
                   1387: static void
                   1388: set_fact(GEN c)
                   1389: {
                   1390:   long i;
                   1391:   c[0] = primfact[1]; /* for already_found_relation */
                   1392:   for (i=1; i<=primfact[0]; i++) c[primfact[i]] = expoprimfact[i];
                   1393: }
                   1394:
                   1395: static void
                   1396: unset_fact(GEN c)
                   1397: {
                   1398:   long i;
                   1399:   for (i=1; i<=primfact[0]; i++) c[primfact[i]] = 0;
                   1400: }
                   1401:
                   1402: #define MAXTRY 20
                   1403:
                   1404: /* return -1 in case of precision problems. t = current number of relations */
                   1405: static long
                   1406: small_norm_for_buchall(long cglob,GEN *mat,GEN matarch,long LIMC, long PRECREG,
                   1407:                        GEN nf,GEN gborne,long nbrelpid,GEN invp,GEN L,GEN LLLnf)
                   1408: {
                   1409:   const double eps = 0.000001;
                   1410:   double *y,*z,**q,*v, MINKOVSKI_BOUND,BOUND;
                   1411:   ulong av = avma, av1,av2,limpile;
                   1412:   long i,j,k,noideal, nbrel = lg(mat)-1;
                   1413:   long alldep = 0, nbsmallnorm,nbfact,R1, N = degpol(nf[1]);
                   1414:   GEN x,xembed,M,T2,r,cbase,invcbase,T2vec,prvec;
                   1415:
                   1416:   if (gsigne(gborne)<=0) return cglob;
                   1417:   if (DEBUGLEVEL)
                   1418:     fprintferr("\n#### Looking for %ld relations (small norms)\n",nbrel);
                   1419:   xembed = NULL; /* gcc -Wall */
                   1420:   nbsmallnorm = nbfact = 0;
                   1421:   R1 = itos(gmael(nf,2,1));
                   1422:   T2 = (GEN)LLLnf[1];
                   1423:   M  = (GEN)LLLnf[2];
                   1424:   cbase   =(GEN)LLLnf[3];
                   1425:   invcbase=(GEN)LLLnf[4];
                   1426:
                   1427:   prvec = cgetg(3,t_VECSMALL);
                   1428:   prvec[1] = MEDDEFAULTPREC;
                   1429:   prvec[2] = PRECREG;
                   1430:   T2vec = cgetg(3,t_VEC);
                   1431:   T2vec[1] = (long)gprec_w(T2,prvec[1]);
                   1432:   T2vec[2] = (long)T2;
                   1433:   minim_alloc(N+1, &q, &x, &y, &z, &v);
                   1434:   av1 = avma;
                   1435:   MINKOVSKI_BOUND = get_minkovski(N,R1,(GEN)nf[3],gborne);
                   1436:   for (noideal=KC; noideal; noideal--)
                   1437:   {
                   1438:     long nbrelideal=0, dependent = 0;
                   1439:     GEN IDEAL, ideal = (GEN)vectbase[noideal];
                   1440:     GEN normideal = idealnorm(nf,ideal);
                   1441:
                   1442:     if (alldep > 2*N) break;
                   1443:
                   1444:     if (DEBUGLEVEL>1) fprintferr("\n*** Ideal no %ld: %Z\n", noideal, ideal);
                   1445:     ideal = prime_to_ideal(nf,ideal);
                   1446:     IDEAL = invcbase? gmul(invcbase, ideal): ideal;
                   1447:     IDEAL = gmul(IDEAL, lllint(IDEAL)); /* should be almost T2-reduced */
                   1448:     r = red_ideal(&IDEAL,T2vec,prvec);
                   1449:     if (!r) return -1; /* precision problem */
                   1450:
                   1451:     for (k=1; k<=N; k++)
                   1452:     {
                   1453:       v[k]=gtodouble(gcoeff(r,k,k));
                   1454:       for (j=1; j<k; j++) q[j][k]=gtodouble(gcoeff(r,j,k));
                   1455:       if (DEBUGLEVEL>3) fprintferr("v[%ld]=%.0f ",k,v[k]);
                   1456:     }
                   1457:
                   1458:     BOUND = MINKOVSKI_BOUND * pow(gtodouble(normideal),2./(double)N);
                   1459:     if (DEBUGLEVEL>1)
                   1460:     {
                   1461:       if (DEBUGLEVEL>3) fprintferr("\n");
                   1462:       fprintferr("BOUND = %.0f\n",BOUND); flusherr();
                   1463:     }
                   1464:     BOUND += eps; av2=avma; limpile = stack_lim(av2,1);
                   1465:     k = N; y[N]=z[N]=0; x[N]= (long) sqrt(BOUND/v[N]);
                   1466:     for(;; x[1]--)
                   1467:     {
                   1468:       ulong av3 = avma;
                   1469:       double p;
                   1470:       GEN col;
                   1471:
                   1472:       for(;;) /* looking for primitive element of small norm */
                   1473:       { /* cf minim00 */
                   1474:        if (k>1)
                   1475:        {
                   1476:          long l = k-1;
                   1477:          z[l] = 0;
                   1478:          for (j=k; j<=N; j++) z[l] += q[l][j]*x[j];
                   1479:          p = x[k]+z[k];
                   1480:          y[l] = y[k]+p*p*v[k];
                   1481:          x[l] = (long) floor(sqrt((BOUND-y[l])/v[l])-z[l]);
                   1482:           k = l;
                   1483:        }
                   1484:        for(;;)
                   1485:        {
                   1486:          p = x[k]+z[k];
                   1487:          if (y[k] + p*p*v[k] <= BOUND) break;
                   1488:          k++; x[k]--;
                   1489:        }
                   1490:        if (k==1) /* element complete */
                   1491:        {
                   1492:          if (!x[1] && y[1]<=eps) goto ENDIDEAL;
                   1493:          if (ccontent(x)==1) /* primitive */
                   1494:          {
                   1495:             GEN Nx, gx = gmul_mati_smallvec(IDEAL,x);
                   1496:             long av4;
                   1497:             if (!isnfscalar(gx))
                   1498:             {
                   1499:               xembed = gmul(M,gx); av4 = avma; nbsmallnorm++;
                   1500:               Nx = ground(norm_by_embed(R1,xembed)); setsigne(Nx, 1);
                   1501:               if (factorelt(nf,cbase,gx,Nx,KCZ,LIMC)) { avma = av4; break; }
                   1502:               if (DEBUGLEVEL > 1) { fprintferr("."); flusherr(); }
                   1503:             }
                   1504:            avma = av3;
                   1505:          }
                   1506:          x[1]--;
                   1507:        }
                   1508:       }
                   1509:       cglob++; col = mat[cglob];
                   1510:       set_fact(col);
                   1511:       if (cglob > 1 && cglob <= KC && ! addcolumntomatrix(col,invp,L))
                   1512:       { /* Q-dependent from previous ones: forget it */
                   1513:         cglob--; unset_fact(col);
                   1514:         if (DEBUGLEVEL>1) { fprintferr("*"); flusherr(); }
                   1515:         if (++dependent > MAXTRY) { alldep++; break; }
                   1516:         avma = av3; continue;
                   1517:       }
                   1518:       /* record archimedean part */
                   1519:       set_log_embed((GEN)matarch[cglob], xembed, R1, PRECREG);
                   1520:       alldep = dependent = 0;
                   1521:
                   1522:       if (DEBUGLEVEL)
                   1523:       {
                   1524:         if (DEBUGLEVEL==1) fprintferr("%4ld",cglob);
                   1525:         else { fprintferr("cglob = %ld. ",cglob); wr_rel(mat[cglob]); }
                   1526:         flusherr(); nbfact++;
                   1527:       }
                   1528:       if (cglob >= nbrel) goto END; /* we have enough */
                   1529:       if (++nbrelideal == nbrelpid) break;
                   1530:
                   1531:       if (low_stack(limpile, stack_lim(av2,1)))
                   1532:       {
                   1533:        if(DEBUGMEM>1) err(warnmem,"small_norm");
                   1534:         invp = gerepilecopy(av2, invp);
                   1535:       }
                   1536:     }
                   1537: ENDIDEAL:
                   1538:     invp = gerepilecopy(av1, invp);
                   1539:     if (DEBUGLEVEL>1) msgtimer("for this ideal");
                   1540:   }
                   1541: END:
                   1542:   if (DEBUGLEVEL)
                   1543:   {
                   1544:     fprintferr("\n");
                   1545:     msgtimer("small norm relations");
                   1546:     if (DEBUGLEVEL>1)
                   1547:     {
                   1548:       GEN p1,tmp=cgetg(cglob+1,t_MAT);
                   1549:
                   1550:       fprintferr("Elements of small norm gave %ld relations.\n",cglob);
                   1551:       fprintferr("Computing rank: "); flusherr();
                   1552:       for(j=1;j<=cglob;j++)
                   1553:       {
                   1554:        p1=cgetg(KC+1,t_COL); tmp[j]=(long)p1;
                   1555:        for(i=1;i<=KC;i++) p1[i]=lstoi(mat[j][i]);
                   1556:       }
                   1557:       tmp = (GEN)sindexrank(tmp)[2]; k=lg(tmp)-1;
                   1558:       fprintferr("%ld; independent columns: %Z\n",k,tmp);
                   1559:     }
                   1560:     if(nbsmallnorm)
                   1561:       fprintferr("\nnb. fact./nb. small norm = %ld/%ld = %.3f\n",
                   1562:                   nbfact,nbsmallnorm,((double)nbfact)/nbsmallnorm);
                   1563:     else
                   1564:       fprintferr("\nnb. small norm = 0\n");
                   1565:   }
                   1566:   avma = av; return cglob;
                   1567: }
                   1568: #undef MAXTRY
                   1569:
                   1570: /* I assumed to be integral HNF, T2 a weighted T2 matrix */
                   1571: static GEN
                   1572: ideallllredpart1(GEN I, GEN T2, long prec)
                   1573: {
                   1574:   GEN y,m,idealpro;
                   1575:
                   1576:   y = lllgramintern(qf_base_change(T2,I,1),100,1,prec+1);
                   1577:   if (!y) return NULL;
                   1578:
                   1579:   /* I, m, y integral */
                   1580:   m = gmul(I,(GEN)y[1]);
                   1581:   if (isnfscalar(m)) m = gmul(I,(GEN)y[2]);
                   1582:
                   1583:   idealpro = cgetg(3,t_VEC);
                   1584:   idealpro[1] = (long)I;
                   1585:   idealpro[2] = (long)m; /* irrational element of small T2 norm in I */
                   1586:   if (DEBUGLEVEL>5) fprintferr("\nidealpro = %Z\n",idealpro);
                   1587:   return idealpro;
                   1588: }
                   1589:
                   1590: static void
                   1591: dbg_newrel(long jideal, long jdir, long phase, long cglob, long *col,
                   1592:            GEN colarch, long lim)
                   1593: {
                   1594:   fprintferr("\n++++ cglob = %ld: new relation (need %ld)", cglob, lim);
                   1595:   wr_rel(col);
                   1596:   if (DEBUGLEVEL>3)
                   1597:   {
                   1598:     fprintferr("(jideal=%ld,jdir=%ld,phase=%ld)", jideal,jdir,phase);
                   1599:     msgtimer("for this relation");
                   1600:   }
                   1601:   if (DEBUGLEVEL>6) fprintferr("archimedian part = %Z\n",colarch);
                   1602:   flusherr() ;
                   1603: }
                   1604:
                   1605: static void
                   1606: dbg_cancelrel(long jideal,long jdir,long phase, long *col)
                   1607: {
                   1608:   fprintferr("rel. cancelled. phase %ld: %ld ",phase);
                   1609:   if (DEBUGLEVEL>3) fprintferr("(jideal=%ld,jdir=%ld)",jideal,jdir);
                   1610:   wr_rel(col); flusherr();
                   1611: }
                   1612:
                   1613: static void
                   1614: dbg_outrel(long phase,long cglob, GEN vperm,GEN *mat,GEN maarch)
                   1615: {
                   1616:   long i,j;
                   1617:   GEN p1,p2;
                   1618:
                   1619:   if (phase == 0)
                   1620:   {
                   1621:     ulong av = avma; p2=cgetg(cglob+1,t_MAT);
                   1622:     for (j=1; j<=cglob; j++)
                   1623:     {
                   1624:       p1=cgetg(KC+1,t_COL); p2[j]=(long)p1;
                   1625:       for (i=1; i<=KC; i++) p1[i]=lstoi(mat[j][i]);
                   1626:     }
                   1627:     fprintferr("\nRank = %ld\n", rank(p2));
                   1628:     if (DEBUGLEVEL>3)
                   1629:     {
                   1630:       fprintferr("relations = \n");
                   1631:       for (j=1; j <= cglob; j++) wr_rel(mat[j]);
                   1632:       fprintferr("\nmatarch = %Z\n",maarch);
                   1633:     }
                   1634:     avma = av;
                   1635:   }
                   1636:   else if (DEBUGLEVEL>6)
                   1637:   {
                   1638:     fprintferr("before hnfadd:\nvectbase[vperm[]] = \n");
                   1639:     fprintferr("[");
                   1640:     for (i=1; i<=KC; i++)
                   1641:     {
                   1642:       bruterr((GEN)vectbase[vperm[i]],'g',-1);
                   1643:       if (i<KC) fprintferr(",");
                   1644:     }
                   1645:     fprintferr("]~\n");
                   1646:   }
                   1647:   flusherr();
                   1648: }
                   1649:
                   1650: /* Check if we already have a column mat[l] equal to mat[s]
                   1651:  * General check for colinearity useless since exceedingly rare */
                   1652: static long
                   1653: already_found_relation(GEN *mat,long s)
                   1654: {
                   1655:   GEN coll, cols = mat[s];
                   1656:   long l,bs;
                   1657:
                   1658:   bs = 1; while (bs<=KC && !cols[bs]) bs++;
                   1659:   if (bs > KC) return s; /* zero relation */
                   1660:
                   1661:   for (l=s-1; l; l--)
                   1662:   {
                   1663:     coll = mat[l];
                   1664:     if (bs == coll[0]) /* = index of first non zero elt in coll */
                   1665:     {
                   1666:       long b = bs;
                   1667:       do b++; while (b<=KC && cols[b] == coll[b]);
                   1668:       if (b > KC) return l;
                   1669:     }
                   1670:   }
                   1671:   cols[0] = bs; return 0;
                   1672: }
                   1673:
                   1674: /* I integral ideal in HNF form */
                   1675: static GEN
                   1676: remove_content(GEN I)
                   1677: {
                   1678:   long N = lg(I)-1;
                   1679:   if (!gcmp1(gcoeff(I,N,N))) { GEN y=content(I); if (!gcmp1(y)) I=gdiv(I,y); }
                   1680:   return I;
                   1681: }
                   1682:
                   1683: /* if phase != 1 re-initialize static variables. If <0 return immediately */
                   1684: static long
                   1685: random_relation(long phase,long cglob,long LIMC,long PRECLLL,long PRECREG,
                   1686:                 GEN nf,GEN subFB,GEN vecT2,GEN *mat,GEN matarch,GEN list_jideal)
                   1687: {
                   1688:   static long jideal, jdir;
                   1689:   long lim,i,av,av1,cptzer,nbT2,lgsub,r1, jlist = 1;
                   1690:   GEN arch,col,colarch,ideal,idealpro,P,ex;
                   1691:
                   1692:   if (phase != 1) { jideal=jdir=1; if (phase<0) return 0; }
                   1693:
                   1694:   r1 = nf_get_r1(nf);
                   1695:   lim = lg(mat)-1; /* requested number of relations */
                   1696:   nbT2 = lg(vecT2)-1;
                   1697:   lgsub = lg(subFB); ex = cgetg(lgsub, t_VECSMALL);
                   1698:   cptzer = 0;
                   1699:   if (DEBUGLEVEL && list_jideal)
                   1700:     fprintferr("looking hard for %Z\n",list_jideal);
                   1701:   P = NULL; /* gcc -Wall */
                   1702:   for (av = avma;;)
                   1703:   {
                   1704:     if (list_jideal && jlist < lg(list_jideal) && jdir <= nbT2)
                   1705:       jideal = list_jideal[jlist++];
                   1706:     if (!list_jideal || jdir <= nbT2)
                   1707:     {
                   1708:       avma = av;
                   1709:       P = prime_to_ideal(nf, (GEN)vectbase[jideal]);
                   1710:     }
                   1711:     ideal = P;
                   1712:     do {
                   1713:       for (i=1; i<lgsub; i++)
                   1714:       {
                   1715:         ex[i] = mymyrand()>>randshift;
                   1716:         if (ex[i]) ideal = idealmulh(nf,ideal, gmael3(powsubFB,i,ex[i],1));
                   1717:       }
                   1718:     }
                   1719:     while (ideal == P); /* If ex  = 0, try another */
                   1720:     ideal = remove_content(ideal);
                   1721:
                   1722:     if (phase != 1) jdir = 1; else phase = 2;
                   1723:     for (av1 = avma; jdir <= nbT2; jdir++, avma = av1)
                   1724:     { /* reduce along various directions */
                   1725:       if (DEBUGLEVEL>2)
                   1726:         fprintferr("phase=%ld,jideal=%ld,jdir=%ld,rand=%ld\n",
                   1727:                    phase,jideal,jdir,getrand());
                   1728:       idealpro = ideallllredpart1(ideal,(GEN)vecT2[jdir],PRECLLL);
                   1729:       if (!idealpro) return -2;
                   1730:       if (!factorgen(nf,idealpro,KCZ,LIMC))
                   1731:       {
                   1732:         if (DEBUGLEVEL>1) { fprintferr("."); flusherr(); }
                   1733:         continue;
                   1734:       }
                   1735:       /* can factor ideal, record relation */
                   1736:       cglob++; col = mat[cglob];
                   1737:       set_fact(col); col[jideal]--;
                   1738:       for (i=1; i<lgsub; i++) col[subFB[i]] -= ex[i];
                   1739:       if (already_found_relation(mat, cglob))
                   1740:       { /* Already known: forget it */
                   1741:         if (DEBUGLEVEL>1) dbg_cancelrel(jideal,jdir,phase,col);
                   1742:         cglob--; unset_fact(col); col[jideal] = 0;
                   1743:         for (i=1; i<lgsub; i++) col[subFB[i]] = 0;
                   1744:
                   1745:         if (++cptzer > MAXRELSUP)
                   1746:         {
                   1747:           if (list_jideal) { cptzer -= 10; break; }
                   1748:           return -1;
                   1749:         }
                   1750:         continue;
                   1751:       }
                   1752:
                   1753:       /* Compute and record archimedian part */
                   1754:       cptzer = 0; arch = NULL;
                   1755:       for (i=1; i<lgsub; i++)
                   1756:         if (ex[i])
                   1757:         {
                   1758:           GEN p1 = gmael3(powsubFB,i,ex[i],2);
                   1759:           arch = arch? vecmul(arch, p1): p1;
                   1760:         }
                   1761:       colarch = (GEN)matarch[cglob];
                   1762:       /* arch = archimedean component (MULTIPLICATIVE form) of ideal */
                   1763:       arch = vecdiv(arch, gmul(gmael(nf,5,1), (GEN)idealpro[2]));
                   1764:       set_log_embed(colarch, arch, r1, PRECREG);
                   1765:       if (DEBUGLEVEL) dbg_newrel(jideal,jdir,phase,cglob,col,colarch,lim);
                   1766:
                   1767:       /* Need more, try next P */
                   1768:       if (cglob < lim) break;
                   1769:
                   1770:       /* We have found enough. Return */
                   1771:       if (phase)
                   1772:       {
                   1773:         jdir = 1;
                   1774:         if (jideal == KC) jideal=1; else jideal++;
                   1775:       }
                   1776:       if (DEBUGLEVEL>2)
                   1777:         fprintferr("Upon exit: jideal=%ld,jdir=%ld\n",jideal,jdir);
                   1778:       avma = av; return cglob;
                   1779:     }
                   1780:     if (!list_jideal)
                   1781:     {
                   1782:       if (jideal == KC) jideal=1; else jideal++;
                   1783:     }
                   1784:   }
                   1785: }
                   1786:
                   1787: static long
                   1788: be_honest(GEN nf,GEN subFB,long PRECLLL)
                   1789: {
                   1790:   ulong av;
                   1791:   GEN MC = gmael(nf,5,2), M = gmael(nf,5,1), D = (GEN)nf[3];
                   1792:   long ex,i,j,J,k,iz,nbtest, lgsub = lg(subFB), ru = lg(MC);
                   1793:   GEN P,ideal,idealpro, exu = cgetg(ru, t_VECSMALL), MCtw= cgetg(ru, t_MAT);
                   1794:
                   1795:   if (DEBUGLEVEL)
                   1796:   {
                   1797:     fprintferr("Be honest for primes from %ld to %ld\n", FB[KCZ+1],FB[KCZ2]);
                   1798:     flusherr();
                   1799:   }
                   1800:   av = avma;
                   1801:   for (iz=KCZ+1; iz<=KCZ2; iz++, avma = av)
                   1802:   {
                   1803:     if (DEBUGLEVEL>1) fprintferr("%ld ", FB[iz]);
                   1804:     P = idealbase[numFB[FB[iz]]]; J = lg(P);
                   1805:     /* if unramified, check all but 1 */
                   1806:     if (J > 1 && !divise(D, gmael(P,1,1))) J--;
                   1807:     for (j=1; j<J; j++)
                   1808:     {
                   1809:       GEN ideal0 = prime_to_ideal(nf,(GEN)P[j]);
                   1810:       ulong av2 = avma;
                   1811:       for(nbtest=0;;)
                   1812:       {
                   1813:        ideal = ideal0;
                   1814:        for (i=1; i<lgsub; i++)
                   1815:        {
                   1816:          ex = mymyrand()>>randshift;
                   1817:          if (ex) ideal = idealmulh(nf,ideal,gmael3(powsubFB,i,ex,1));
                   1818:        }
                   1819:         ideal = remove_content(ideal);
                   1820:        for (k=1; k<ru; k++)
                   1821:        {
                   1822:          if (k==1)
                   1823:             for (i=1; i<ru; i++) exu[i] = mymyrand()>>randshift;
                   1824:           else
                   1825:          {
                   1826:            for (i=1; i<ru; i++) exu[i] = 0;
                   1827:             exu[k] = 10;
                   1828:          }
                   1829:           for (i=1; i<ru; i++)
                   1830:             MCtw[i] = exu[i]? lmul2n((GEN)MC[i],exu[i]<<1): MC[i];
                   1831:           idealpro = ideallllredpart1(ideal, mulmat_real(MCtw,M), PRECLLL);
                   1832:           if (idealpro && factorgen(nf,idealpro,iz-1,FB[iz-1])) break;
                   1833:          nbtest++; if (nbtest==200) return 0;
                   1834:        }
                   1835:        avma = av2; if (k < ru) break;
                   1836:       }
                   1837:     }
                   1838:   }
                   1839:   if (DEBUGLEVEL)
                   1840:   {
                   1841:     if (DEBUGLEVEL>1) fprintferr("\n");
                   1842:     msgtimer("be honest");
                   1843:   }
                   1844:   avma = av; return 1;
                   1845: }
                   1846:
                   1847: int
                   1848: trunc_error(GEN x)
                   1849: {
                   1850:   return typ(x)==t_REAL && signe(x)
                   1851:                         && (expo(x)>>TWOPOTBITS_IN_LONG) + 3 > lg(x);
                   1852: }
                   1853:
                   1854: /* xarch = complex logarithmic embeddings of units (u_j) found so far */
                   1855: static GEN
                   1856: compute_multiple_of_R(GEN xarch,long RU,long N,GEN *ptsublambda)
                   1857: {
                   1858:   GEN v,mdet,mdet_t,Im_mdet,kR,sublambda,lambda,xreal;
                   1859:   GEN *gptr[2];
                   1860:   long av = avma, i,j, sreg = lg(xarch)-1, R1 = 2*RU - N;
                   1861:
                   1862:   if (DEBUGLEVEL) { fprintferr("\n#### Computing regulator\n"); flusherr(); }
                   1863:   xreal=greal(xarch); v=cgetg(RU+1,t_COL); /* xreal = (log |sigma_i(u_j)|) */
                   1864:   for (i=1; i<=R1; i++) v[i]=un;
                   1865:   for (   ; i<=RU; i++) v[i]=deux;
                   1866:   mdet=cgetg(sreg+2,t_MAT); mdet[1]=(long)v;
                   1867:   for (j=2; j<=sreg+1; j++) mdet[j]=xreal[j-1]; /* det(Span(mdet)) = N * R */
                   1868:
                   1869:   i = gprecision(mdet); /* truncate to avoid "near dependant" vectors */
                   1870:   mdet_t = (i <= 4)? mdet: gprec_w(mdet,i-1);
                   1871:   v = (GEN)sindexrank(mdet_t)[2]; /* list of independant column indices */
                   1872:   /* check we have full rank for units */
                   1873:   if (lg(v) != RU+1) { avma=av; return NULL; }
                   1874:
                   1875:   Im_mdet = vecextract_p(mdet,v);
                   1876:   /* integral multiple of R: the cols we picked form a Q-basis, they have an
                   1877:    * index in the full lattice */
                   1878:   kR = gdivgs(det2(Im_mdet), N);
                   1879:   /* R > 0.2 uniformly */
                   1880:   if (gexpo(kR) < -3) { avma=av; return NULL; }
                   1881:
                   1882:   kR = mpabs(kR);
                   1883:   sublambda = cgetg(sreg+1,t_MAT);
                   1884:   lambda = gauss(Im_mdet,xreal); /* rational entries */
                   1885:   for (i=1; i<=sreg; i++)
                   1886:   {
                   1887:     GEN p1 = cgetg(RU,t_COL), p2 = (GEN)lambda[i];
                   1888:     sublambda[i] = (long)p1;
                   1889:     for (j=1; j<RU; j++)
                   1890:     {
                   1891:       p1[j] = p2[j+1];
                   1892:       if (trunc_error((GEN)p1[j])) { *ptsublambda = NULL; return gzero; }
                   1893:     }
                   1894:   }
                   1895:   *ptsublambda = sublambda;
                   1896:   gptr[0]=ptsublambda; gptr[1]=&kR;
                   1897:   gerepilemany(av,gptr,2); return kR;
                   1898: }
                   1899:
                   1900: /* Assuming enough relations, c = Rz is close to an even integer, according
                   1901:  * to Dirichlet's formula. Otherwise, close to a multiple.
                   1902:  * Compute a tentative regulator (not a multiple this time) */
                   1903: static GEN
                   1904: compute_check(GEN sublambda, GEN z, GEN *parch, GEN *reg)
                   1905: {
                   1906:   long av = avma, av2, tetpil;
                   1907:   GEN p1,c,den, R = *reg; /* multiple of regulator */
                   1908:
                   1909:   if (DEBUGLEVEL) { fprintferr("\n#### Computing check\n"); flusherr(); }
                   1910:   c = gmul(R,z);
                   1911:   sublambda = bestappr(sublambda,c); den = denom(sublambda);
                   1912:   if (gcmp(den,c) > 0)
                   1913:   {
                   1914:     if (DEBUGLEVEL) fprintferr("c = %Z\nden = %Z\n",c,den);
                   1915:     avma=av; return NULL;
                   1916:   }
                   1917:
                   1918:   p1 = gmul(sublambda,den); tetpil=avma;
                   1919:   *parch = lllint(p1);
                   1920:
                   1921:   av2=avma; p1 = det2(gmul(sublambda,*parch));
                   1922:   affrr(mpabs(gmul(R,p1)), R); avma=av2;
                   1923:
                   1924:   if (DEBUGLEVEL) msgtimer("bestappr/regulator");
                   1925:   *parch = gerepile(av,tetpil,*parch); return gmul(R,z);
                   1926: }
                   1927:
                   1928: /* find the smallest (wrt norm) among I, I^-1 and red(I^-1) */
                   1929: static GEN
                   1930: inverse_if_smaller(GEN nf, GEN I, long prec)
                   1931: {
                   1932:   GEN J, d, dmin, I1;
                   1933:   int inv;
                   1934:   J = (GEN)I[1];
                   1935:   dmin = dethnf_i(J); I1 = idealinv(nf,I);
                   1936:   J = (GEN)I1[1]; J = gmul(J,denom(J)); I1[1] = (long)J;
                   1937:   d = dethnf_i(J);
                   1938:   if (cmpii(d,dmin) < 0) {inv=1; I=I1; dmin=d;}
                   1939:   else                    inv=0;
                   1940:   /* try reducing (often _increases_ the norm) */
                   1941:   I1 = ideallllred(nf,I1,NULL,prec);
                   1942:   J = (GEN)I1[1];
                   1943:   d = dethnf_i(J);
                   1944:   if (cmpii(d,dmin) < 0) {inv=1; I=I1;}
                   1945:   return I;
                   1946: }
                   1947:
                   1948: /* in place */
                   1949: static void
                   1950: neg_row(GEN U, long i)
                   1951: {
                   1952:   GEN c = U + lg(U)-1;
                   1953:   for (; c>U; c--) coeff(c,i,0) = lneg(gcoeff(c,i,0));
                   1954: }
                   1955:
                   1956: static void
                   1957: setlg_col(GEN U, long l)
                   1958: {
                   1959:   GEN c = U + lg(U)-1;
                   1960:   for (; c>U; c--) setlg(*c, l);
                   1961: }
                   1962:
                   1963: /* compute class group (clg1) + data for isprincipal (clg2) */
                   1964: static void
                   1965: class_group_gen(GEN nf,GEN W,GEN C,GEN vperm,GEN *ptclg1,GEN *ptclg2,long prec)
                   1966: {
                   1967:   GEN z,G,Ga,ga,GD,cyc,X,Y,D,U,V,Ur,Ui,Uir,I,J,Vbase;
                   1968:   long i,j,s,lo,lo0;
                   1969:
                   1970:   if (DEBUGLEVEL)
                   1971:     { fprintferr("\n#### Computing class group generators\n"); timer2(); }
                   1972:   z = smith2(W); /* U W V = D, D diagonal, G = g Ui (G=new gens, g=old)  */
                   1973:   U = (GEN)z[1]; Ui = ginv(U);
                   1974:   V = (GEN)z[2];
                   1975:   D = (GEN)z[3];
                   1976:   lo0 = lo = lg(D);
                   1977:  /* we could set lo = lg(cyc) and truncate all matrices below
                   1978:   *   setlg_col(D && U && Y, lo) + setlg(D && V && X && Ui, lo)
                   1979:   * but it's not worth the complication:
                   1980:   * 1) gain is negligible (avoid computing z^0 if lo < lo0)
                   1981:   * 2) when computing ga, the products XU and VY use the original matrices
                   1982:   */
                   1983:   Ur  = reducemodHNF(U, D, &Y);
                   1984:   Uir = reducemodHNF(Ui,W, &X);
                   1985:  /* [x] = logarithmic embedding of x (arch. component)
                   1986:   * NB: z = idealred(I) --> I = y z[1], with [y] = - z[2]
                   1987:   * P invertible diagonal matrix (\pm 1) which is only implicitly defined
                   1988:   * G = g Uir P + [Ga],  Uir = Ui + WX
                   1989:   * g = G P Ur  + [ga],  Ur  = U + DY */
                   1990:   Vbase = cgetg(lo0,t_VEC);
                   1991:   if (typ(vperm) == t_VECSMALL)
                   1992:     for (i=1; i<lo0; i++) Vbase[i] = vectbase[vperm[i]];
                   1993:   else
                   1994:     for (i=1; i<lo0; i++) Vbase[i] = vectbase[itos((GEN)vperm[i])];
                   1995:
                   1996:   G = cgetg(lo,t_VEC);
                   1997:   Ga= cgetg(lo,t_VEC);
                   1998:   z = init_idele(nf);
                   1999:   for (j=1; j<lo; j++)
                   2000:   {
                   2001:     GEN p1 = gcoeff(Uir,1,j);
                   2002:     z[1]=Vbase[1]; I = idealpowred(nf,z,p1,prec);
                   2003:     if (signe(p1)<0) I[1] = lmul((GEN)I[1],denom((GEN)I[1]));
                   2004:     for (i=2; i<lo0; i++)
                   2005:     {
                   2006:       p1 = gcoeff(Uir,i,j); s = signe(p1);
                   2007:       if (s)
                   2008:       {
                   2009:        z[1]=Vbase[i]; J = idealpowred(nf,z,p1,prec);
                   2010:         if (s<0) J[1] = lmul((GEN)J[1],denom((GEN)J[1]));
                   2011:        I = idealmulh(nf,I,J);
                   2012:        I = ideallllred(nf,I,NULL,prec);
                   2013:       }
                   2014:     }
                   2015:     J = inverse_if_smaller(nf, I, prec);
                   2016:     if (J != I)
                   2017:     { /* update wrt P */
                   2018:       neg_row(Y ,j); V[j] = lneg((GEN)V[j]);
                   2019:       neg_row(Ur,j); X[j] = lneg((GEN)X[j]);
                   2020:     }
                   2021:     G[j] = (long)J[1]; /* generator, order cyc[j] */
                   2022:     Ga[j]= (long)J[2];
                   2023:   }
                   2024:   /* at this point Y = PY, Ur = PUr, V = VP, X = XP */
                   2025:
                   2026:   /* G D =: [GD] = g (UiP + W XP) D + [Ga]D = g W (VP + XP D) + [Ga]D
                   2027:    * NB: DP = PD and Ui D = W V. gW is given by (first lo0-1 cols of) C
                   2028:    */
                   2029:   GD = gadd(act_arch(gadd(V, gmul(X,D)), C),
                   2030:             act_arch(D, Ga));
                   2031:   /* -[ga] = [GD]PY + G PU - g = [GD]PY + [Ga] PU + gW XP PU
                   2032:                                = gW (XP PUr + VP PY) + [Ga]PUr */
                   2033:   ga = gadd(act_arch(gadd(gmul(X,Ur), gmul(V,Y)), C),
                   2034:             act_arch(Ur, Ga));
                   2035:   ga = gneg(ga);
                   2036:   /* TODO: could (LLL)reduce ga and GD mod units ? */
                   2037:
                   2038:   cyc = cgetg(lo,t_VEC); /* elementary divisors */
                   2039:   for (j=1; j<lo; j++)
                   2040:   {
                   2041:     cyc[j] = coeff(D,j,j);
                   2042:     if (gcmp1((GEN)cyc[j]))
                   2043:     { /* strip useless components */
                   2044:       lo = j; setlg(cyc,lo); setlg_col(Ur,lo);
                   2045:       setlg(G,lo); setlg(Ga,lo); setlg(GD,lo); break;
                   2046:     }
                   2047:   }
                   2048:   z = cgetg(4,t_VEC); *ptclg1 = z;
                   2049:   z[1]=(long)dethnf_i(W);
                   2050:   z[2]=(long)cyc;
                   2051:   z[3]=(long)G;
                   2052:   z = cgetg(4,t_VEC); *ptclg2 = z;
                   2053:   z[1]=(long)Ur;
                   2054:   z[2]=(long)ga;
                   2055:   z[3]=(long)GD;
                   2056:   if (DEBUGLEVEL) msgtimer("classgroup generators");
                   2057: }
                   2058:
                   2059: /* real(MC * M), where columns a and b of MC have been multiplied by 2^20+1 */
                   2060: static GEN
                   2061: shift_t2(GEN T2, GEN M, GEN MC, long a, long b)
                   2062: {
                   2063:   long i,j,N = lg(T2);
                   2064:   GEN z, t2 = cgetg(N,t_MAT);
                   2065:   for (j=1; j<N; j++)
                   2066:   {
                   2067:     t2[j] = lgetg(N,t_COL);
                   2068:     for (i=1; i<=j; i++)
                   2069:     {
                   2070:       z = mul_real(gcoeff(MC,i,a), gcoeff(M,a,j));
                   2071:       if (a!=b) z = gadd(z, mul_real(gcoeff(MC,i,b), gcoeff(M,b,j)));
                   2072:       coeff(t2,j,i) = coeff(t2,i,j) = ladd(gcoeff(T2,i,j), gmul2n(z,20));
                   2073:     }
                   2074:   }
                   2075:   return t2;
                   2076: }
                   2077:
                   2078: static GEN
                   2079: compute_vecT2(long RU,GEN nf)
                   2080: {
                   2081:   GEN vecT2, M = gmael(nf,5,1), MC = gmael(nf,5,2), T2 = gmael(nf,5,3);
                   2082:   long i,j,n = min(RU,9), ind = 1;
                   2083:
                   2084:   vecT2=cgetg(1 + n*(n+1)/2,t_VEC);
                   2085:   for (j=1; j<=n; j++)
                   2086:     for (i=1; i<=j; i++) vecT2[ind++] = (long)shift_t2(T2,M,MC,i,j);
                   2087:   if (DEBUGLEVEL) msgtimer("weighted T2 matrices");
                   2088:   return vecT2;
                   2089: }
                   2090:
                   2091: /* cf. relationrank()
                   2092:  *
                   2093:  * If V depends linearly from the columns of the matrix, return 0.
                   2094:  * Otherwise, update INVP and L and return 1. No GC.
                   2095:  */
                   2096: int
                   2097: addcolumntomatrix(GEN V, GEN invp, GEN L)
                   2098: {
                   2099:   GEN a = gmul_mat_smallvec(invp,V);
                   2100:   long i,j,k, n = lg(invp);
                   2101:
                   2102:   if (DEBUGLEVEL>6)
                   2103:   {
                   2104:     fprintferr("adding vector = %Z\n",V);
                   2105:     fprintferr("vector in new basis = %Z\n",a);
                   2106:     fprintferr("list = %Z\n",L);
                   2107:     fprintferr("base change matrix =\n"); outerr(invp);
                   2108:   }
                   2109:   k = 1; while (k<n && (L[k] || gcmp0((GEN)a[k]))) k++;
                   2110:   if (k == n) return 0;
                   2111:   L[k] = 1;
                   2112:   for (i=k+1; i<n; i++) a[i] = ldiv(gneg_i((GEN)a[i]),(GEN)a[k]);
                   2113:   for (j=1; j<=k; j++)
                   2114:   {
                   2115:     GEN c = (GEN)invp[j], ck = (GEN)c[k];
                   2116:     if (gcmp0(ck)) continue;
                   2117:     c[k] = ldiv(ck, (GEN)a[k]);
                   2118:     if (j==k)
                   2119:       for (i=k+1; i<n; i++)
                   2120:        c[i] = lmul((GEN)a[i], ck);
                   2121:     else
                   2122:       for (i=k+1; i<n; i++)
                   2123:        c[i] = ladd((GEN)c[i], gmul((GEN)a[i], ck));
                   2124:   }
                   2125:   return 1;
                   2126: }
                   2127:
                   2128: /* compute the rank of A in M_n,r(Z) (C long), where rank(A) = r <= n.
                   2129:  * Starting from the identity (canonical basis of Q^n), we obtain a base
                   2130:  * change matrix P by taking the independant columns of A and vectors from
                   2131:  * the canonical basis. Update invp = 1/P, and L in {0,1}^n, with L[i] = 0
                   2132:  * of P[i] = e_i, and 1 if P[i] = A_i (i-th column of A)
                   2133:  */
                   2134: static GEN
                   2135: relationrank(GEN *A, long r, GEN L)
                   2136: {
                   2137:   long i, n = lg(L)-1, av = avma, lim = stack_lim(av,1);
                   2138:   GEN invp = idmat(n);
                   2139:
                   2140:   if (!r) return invp;
                   2141:   if (r>n) err(talker,"incorrect matrix in relationrank");
                   2142:   for (i=1; i<=r; i++)
                   2143:   {
                   2144:     if (! addcolumntomatrix(A[i],invp,L) && i == r)
                   2145:       err(talker,"not a maximum rank matrix in relationrank");
                   2146:     if (low_stack(lim, stack_lim(av,1)))
                   2147:     {
                   2148:       if(DEBUGMEM>1) err(warnmem,"relationrank");
                   2149:       invp = gerepilecopy(av, invp);
                   2150:     }
                   2151:   }
                   2152:   return gerepilecopy(av, invp);
                   2153: }
                   2154:
                   2155: static GEN
                   2156: codeprime(GEN bnf, GEN pr)
                   2157: {
                   2158:   long j,av=avma,tetpil;
                   2159:   GEN p,al,fa,p1;
                   2160:
                   2161:   p=(GEN)pr[1]; al=(GEN)pr[2]; fa=primedec(bnf,p);
                   2162:   for (j=1; j<lg(fa); j++)
                   2163:     if (gegal(al,gmael(fa,j,2)))
                   2164:     {
                   2165:       p1=mulsi(lg(al)-1,p); tetpil=avma;
                   2166:       return gerepile(av,tetpil,addsi(j-1,p1));
                   2167:     }
                   2168:   err(talker,"bug in codeprime/smallbuchinit");
                   2169:   return NULL; /* not reached */
                   2170: }
                   2171:
                   2172: static GEN
                   2173: decodeprime(GEN nf, GEN co)
                   2174: {
                   2175:   long n,indi,av=avma;
                   2176:   GEN p,rem,p1;
                   2177:
                   2178:   n=lg(nf[7])-1; p=dvmdis(co,n,&rem); indi=itos(rem)+1;
                   2179:   p1=primedec(nf,p);
                   2180:   return gerepilecopy(av,(GEN)p1[indi]);
                   2181: }
                   2182:
                   2183: /* v = bnf[10] */
                   2184: GEN
                   2185: get_matal(GEN v)
                   2186: {
                   2187:   if (typ(v) == t_VEC)
                   2188:   {
                   2189:     GEN ma = (GEN)v[1];
                   2190:     if (typ(ma) != t_INT) return ma;
                   2191:   }
                   2192:   return NULL;
                   2193: }
                   2194:
                   2195: GEN
                   2196: get_cycgen(GEN v)
                   2197: {
                   2198:   if (typ(v) == t_VEC)
                   2199:   {
                   2200:     GEN h = (GEN)v[2];
                   2201:     if (typ(h) == t_VEC) return h;
                   2202:   }
                   2203:   return NULL;
                   2204: }
                   2205:
                   2206: /* compute principal ideals corresponding to (gen[i]^cyc[i]) */
                   2207: static GEN
                   2208: makecycgen(GEN bnf)
                   2209: {
                   2210:   GEN cyc,gen,h,nf,y,GD,D;
                   2211:   long e,i,l;
                   2212:
                   2213:   h = get_cycgen((GEN)bnf[10]);
                   2214:   if (h) return h;
                   2215:
                   2216:   nf = checknf(bnf);
                   2217:   cyc = gmael3(bnf,8,1,2); D = diagonal(cyc);
                   2218:   gen = gmael3(bnf,8,1,3); GD = gmael(bnf,9,3);
                   2219:   l = lg(gen); h = cgetg(l, t_VEC);
                   2220:   for (i=1; i<l; i++)
                   2221:   {
                   2222:     if (cmpis((GEN)cyc[i], 16) < 0)
                   2223:     {
                   2224:       GEN N = dethnf_i((GEN)gen[i]);
                   2225:       y = isprincipalarch(bnf,(GEN)GD[i], N, (GEN)cyc[i], gun, &e);
                   2226:       if (y && !fact_ok(nf,y,NULL,gen,(GEN)D[i])) y = NULL;
                   2227:       if (y) { h[i] = (long)to_famat_all(y,gun); continue; }
                   2228:     }
                   2229:     y = isprincipalfact(bnf, gen, (GEN)D[i], NULL,
                   2230:                         nf_GEN|nf_GENMAT|nf_FORCE|nf_GIVEPREC);
                   2231:     if (typ(y) != t_INT)
                   2232:       h[i] = y[2];
                   2233:     else
                   2234:     {
                   2235:       y = idealpow(nf, (GEN)gen[i], (GEN)cyc[i]);
                   2236:       h[i] = isprincipalgenforce(bnf,y)[2];
                   2237:     }
                   2238:   }
                   2239:   return h;
                   2240: }
                   2241:
                   2242: /* compute principal ideals corresponding to bnf relations */
                   2243: static GEN
                   2244: makematal(GEN bnf)
                   2245: {
                   2246:   GEN W,B,pFB,vp,nf,ma, WB_C;
                   2247:   long lW,lma,j,prec;
                   2248:
                   2249:   ma = get_matal((GEN)bnf[10]);
                   2250:   if (ma) return ma;
                   2251:
                   2252:   W   = (GEN)bnf[1];
                   2253:   B   = (GEN)bnf[2];
                   2254:   WB_C= (GEN)bnf[4];
                   2255:   vp  = (GEN)bnf[6];
                   2256:   nf  = (GEN)bnf[7];
                   2257:   lW=lg(W)-1; lma=lW+lg(B);
                   2258:   pFB=cgetg(lma,t_VEC); ma=(GEN)bnf[5]; /* reorder factor base */
                   2259:   for (j=1; j<lma; j++) pFB[j] = ma[itos((GEN)vp[j])];
                   2260:   ma = cgetg(lma,t_MAT);
                   2261:
                   2262:   prec = prec_arch(bnf);
                   2263:   for (j=1; j<lma; j++)
                   2264:   {
                   2265:     long c = getrand(), e;
                   2266:     GEN ex = (j<=lW)? (GEN)W[j]: (GEN)B[j-lW];
                   2267:     GEN C = (j<=lW)? NULL: (GEN)pFB[j];
                   2268:     GEN dx, Nx = get_norm_fact_primes(pFB, ex, C, &dx);
                   2269:     GEN y = isprincipalarch(bnf,(GEN)WB_C[j], Nx,gun, dx, &e);
                   2270:     if (y && !fact_ok(nf,y,C,pFB,ex)) y = NULL;
                   2271:     if (y)
                   2272:     {
                   2273:       if (DEBUGLEVEL>1) fprintferr("*%ld ",j);
                   2274:       ma[j] = (long)y; continue;
                   2275:     }
                   2276:
                   2277:     if (!y) y = isprincipalfact(bnf,pFB,ex,C, nf_GEN|nf_FORCE|nf_GIVEPREC);
                   2278:     if (typ(y) != t_INT)
                   2279:     {
                   2280:       if (DEBUGLEVEL>1) fprintferr("%ld ",j);
                   2281:       ma[j] = y[2]; continue;
                   2282:     }
                   2283:
                   2284:     prec = itos(y); j--;
                   2285:     if (DEBUGLEVEL) err(warnprec,"makematal",prec);
                   2286:     nf = nfnewprec(nf,prec);
                   2287:     bnf = bnfinit0(nf,1,NULL,prec); setrand(c);
                   2288:   }
                   2289:   if (DEBUGLEVEL>1) fprintferr("\n");
                   2290:   return ma;
                   2291: }
                   2292:
                   2293: /* insert O in bnf at index K
                   2294:  * K = 1: matal
                   2295:  * K = 2: cycgen */
                   2296: static void
                   2297: bnfinsert(GEN bnf, GEN O, long K)
                   2298: {
                   2299:   GEN v = (GEN)bnf[10];
                   2300:   if (typ(v) != t_VEC)
                   2301:   {
                   2302:     GEN w = cgetg(3, t_VEC);
                   2303:     long i;
                   2304:     for (i = 1; i < 3; i++)
                   2305:       w[i] = (i==K)? (long)O: zero;
                   2306:     w = gclone(w);
                   2307:     bnf[10] = (long)w;
                   2308:   }
                   2309:   else
                   2310:     v[K] = lclone(O);
                   2311: }
                   2312:
                   2313: GEN
                   2314: check_and_build_cycgen(GEN bnf)
                   2315: {
                   2316:   GEN cycgen = get_cycgen((GEN)bnf[10]);
                   2317:   if (!cycgen)
                   2318:   {
                   2319:     long av = avma;
                   2320:     if (DEBUGLEVEL) err(warner,"completing bnf (building cycgen)");
                   2321:     bnfinsert(bnf, makecycgen(bnf), 2); avma = av;
                   2322:     cycgen = get_cycgen((GEN)bnf[10]);
                   2323:   }
                   2324:   return cycgen;
                   2325: }
                   2326:
                   2327: GEN
                   2328: check_and_build_matal(GEN bnf)
                   2329: {
                   2330:   GEN matal = get_matal((GEN)bnf[10]);
                   2331:   if (!matal)
                   2332:   {
                   2333:     long av = avma;
                   2334:     if (DEBUGLEVEL) err(warner,"completing bnf (building matal)");
                   2335:     bnfinsert(bnf, makematal(bnf), 1); avma = av;
                   2336:     matal = get_matal((GEN)bnf[10]);
                   2337:   }
                   2338:   return matal;
                   2339: }
                   2340:
                   2341: GEN
                   2342: smallbuchinit(GEN pol,GEN gcbach,GEN gcbach2,GEN gRELSUP,GEN gborne,long nbrelpid,long minsFB,long prec)
                   2343: {
                   2344:   long av=avma,av1,k;
                   2345:   GEN y,bnf,pFB,vp,nf,mas,res,uni,v1,v2,v3;
                   2346:
                   2347:   if (typ(pol)==t_VEC) bnf = checkbnf(pol);
                   2348:   else
                   2349:   {
                   2350:     bnf=buchall(pol,gcbach,gcbach2,gRELSUP,gborne,nbrelpid,minsFB,-3,prec);
                   2351:     bnf = checkbnf_discard(bnf);
                   2352:   }
                   2353:   pFB=(GEN)bnf[5]; vp=(GEN)bnf[6]; nf=(GEN)bnf[7];
                   2354:   mas=(GEN)nf[5]; res=(GEN)bnf[8]; uni=(GEN)res[5];
                   2355:
                   2356:   y=cgetg(13,t_VEC); y[1]=lcopy((GEN)nf[1]); y[2]=lcopy(gmael(nf,2,1));
                   2357:   y[3]=lcopy((GEN)nf[3]); y[4]=lcopy((GEN)nf[7]);
                   2358:   y[5]=lcopy((GEN)nf[6]); y[6]=lcopy((GEN)mas[5]);
                   2359:   y[7]=lcopy((GEN)bnf[1]); y[8]=lcopy((GEN)bnf[2]);
                   2360:   v1=cgetg(lg(pFB),t_VEC); y[9]=(long)v1;
                   2361:   for (k=1; k<lg(pFB); k++)
                   2362:     v1[k]=(long)codeprime(bnf,(GEN)pFB[itos((GEN)vp[k])]);
                   2363:   v2=cgetg(3,t_VEC); y[10]=(long)v2;
                   2364:   v2[1]=lcopy(gmael(res,4,1));
                   2365:   v2[2]=(long)algtobasis(bnf,gmael(res,4,2));
                   2366:   v3=cgetg(lg(uni),t_VEC); y[11]=(long)v3;
                   2367:   for (k=1; k<lg(uni); k++)
                   2368:     v3[k] = (long)algtobasis(bnf,(GEN)uni[k]);
                   2369:   av1 = avma;
                   2370:   y[12] = gcmp0((GEN)bnf[10])? lpilecopy(av1, makematal(bnf))
                   2371:                              : lcopy((GEN)bnf[10]);
                   2372:   return gerepileupto(av,y);
                   2373: }
                   2374:
                   2375: static GEN
                   2376: get_regulator(GEN mun,long prec)
                   2377: {
                   2378:   long av,tetpil;
                   2379:   GEN p1;
                   2380:
                   2381:   if (lg(mun)==1) return gun;
                   2382:   av=avma; p1 = gtrans(greal(mun));
                   2383:   setlg(p1,lg(p1)-1); p1 = det(p1);
                   2384:   tetpil=avma; return gerepile(av,tetpil,gabs(p1,prec));
                   2385: }
                   2386:
                   2387: static GEN
                   2388: log_poleval(GEN P, GEN *ro, long i, GEN nf, long prec0)
                   2389: {
                   2390:   GEN x = poleval(P, (GEN)(*ro)[i]);
                   2391:   long prec = prec0, k = 0;
                   2392:   while (gcmp0(x) || ((k = gprecision(x)) && k < DEFAULTPREC))
                   2393:   {
                   2394:     prec = (prec-2)<<1;
                   2395:     if (DEBUGLEVEL) err(warnprec,"log_poleval",prec);
                   2396:     *ro = get_roots((GEN)nf[1], itos(gmael(nf,2,1)),lg(*ro)-1,prec);
                   2397:     x = poleval(P, (GEN)(*ro)[i]);
                   2398:   }
                   2399:   if (k > prec0) x = gprec_w(x,prec0);
                   2400:   return glog(x, prec0);
                   2401: }
                   2402:
                   2403: /* return corrected archimedian components
                   2404:  * (= log(sigma_i(x)) - log(|Nx|)/[K:Q]) for a (matrix of elements) */
                   2405: static GEN
                   2406: get_arch2_i(GEN nf, GEN a, long prec, int units)
                   2407: {
                   2408:   GEN M,N, ro = dummycopy((GEN)nf[6]);
                   2409:   long j,k, la = lg(a), ru = lg(ro), r1 = nf_get_r1(nf);
                   2410:
                   2411:   M = cgetg(la,t_MAT); if (la == 1) return M;
                   2412:   if (typ(a[1]) == t_COL) a = gmul((GEN)nf[7], a);
                   2413:   if (units) N = NULL; /* no correction necessary */
                   2414:   else
                   2415:   {
                   2416:     GEN pol = (GEN)nf[1];
                   2417:     N = cgetg(la,t_VEC);
                   2418:     for (k=1; k<la; k++) N[k] = (long)gabs(subres(pol,(GEN)a[k]),0);
                   2419:     N = gdivgs(glog(N,prec), - (degpol(pol))); /* - log(|norm|) / [K:Q] */
                   2420:   }
                   2421:   for (k=1; k<la; k++)
                   2422:   {
                   2423:     GEN p, c = cgetg(ru,t_COL); M[k] = (long)c;
                   2424:     for (j=1; j<ru; j++)
                   2425:     {
                   2426:       p = log_poleval((GEN)a[k],&ro,j,nf,prec);
                   2427:       if (N) p = gadd(p, (GEN)N[k]);
                   2428:       c[j]=(j<=r1)? (long) p: lmul2n(p,1);
                   2429:     }
                   2430:   }
                   2431:   return M;
                   2432: }
                   2433:
                   2434: static GEN
                   2435: get_arch2(GEN nf, GEN a, long prec, int units)
                   2436: {
                   2437:   long av = avma;
                   2438:   return gerepilecopy(av, get_arch2_i(nf,a,prec,units));
                   2439: }
                   2440:
                   2441: static void
                   2442: my_class_group_gen(GEN bnf, GEN *ptcl, GEN *ptcl2, long prec)
                   2443: {
                   2444:   GEN W=(GEN)bnf[1], C=(GEN)bnf[4], vperm=(GEN)bnf[6], nf=(GEN)bnf[7], *gptr[2];
                   2445:   long av = avma;
                   2446:
                   2447:   vectbase = (GEN)bnf[5]; /* needed by class_group_gen */
                   2448:   class_group_gen(nf,W,C,vperm,ptcl,ptcl2, prec);
                   2449:   gptr[0]=ptcl; gptr[1]=ptcl2; gerepilemany(av,gptr,2);
                   2450: }
                   2451:
                   2452: GEN
                   2453: bnfnewprec(GEN bnf, long prec)
                   2454: {
                   2455:   GEN nf,ro,res,p1,funits,mun,matal,clgp,clgp2,y;
                   2456:   long r1,r2,ru,pl1,pl2,prec1;
                   2457:
                   2458:   bnf = checkbnf(bnf);
                   2459:   if (prec <= 0) return nfnewprec(checknf(bnf),prec);
                   2460:   y = cgetg(11,t_VEC);
                   2461:   funits = check_units(bnf,"bnfnewprec");
                   2462:   nf = (GEN)bnf[7];
                   2463:   ro = (GEN)nf[6]; ru = lg(ro)-1;
                   2464:   r1 = nf_get_r1(nf);
                   2465:   r2 = (r1 + ru) >> 1;
                   2466:   pl1 = (ru == 1 && r1 == 0)? 0: gexpo(funits);
                   2467:   pl2 = gexpo(ro);
                   2468:   prec1 = prec;
                   2469:   prec += ((ru + r2 - 1) * (pl1 + (ru + r2) * pl2)) >> TWOPOTBITS_IN_LONG;
                   2470:   nf = nfnewprec((GEN)bnf[7],prec);
                   2471:   res = cgetg(7,t_VEC);
                   2472:   ro = (GEN)nf[6];
                   2473:   mun = get_arch2(nf,funits,prec,1);
                   2474:   if (prec != prec1) { mun = gprec_w(mun,prec1); prec = prec1; }
                   2475:   res[2]=(long)get_regulator(mun,prec);
                   2476:   p1 = (GEN)bnf[8];
                   2477:   res[3]=lcopy((GEN)p1[3]);
                   2478:   res[4]=lcopy((GEN)p1[4]);
                   2479:   res[5]=lcopy((GEN)p1[5]);
                   2480:   res[6]=lcopy((GEN)p1[6]);
                   2481:
                   2482:   y[1]=lcopy((GEN)bnf[1]);
                   2483:   y[2]=lcopy((GEN)bnf[2]);
                   2484:   y[3]=(long)mun;
                   2485:   matal = check_and_build_matal(bnf);
                   2486:   y[4]=(long)get_arch2(nf,matal,prec,0);
                   2487:   y[5]=lcopy((GEN)bnf[5]);
                   2488:   y[6]=lcopy((GEN)bnf[6]);
                   2489:   y[7]=(long)nf;
                   2490:   y[8]=(long)res;
                   2491:   my_class_group_gen(y,&clgp,&clgp2,prec);
                   2492:   res[1]=(long)clgp;
                   2493:   y[9]=(long)clgp2;
                   2494:   y[10]=lcopy((GEN)bnf[10]); return y;
                   2495: }
                   2496:
                   2497: GEN
                   2498: bnrnewprec(GEN bnr, long prec)
                   2499: {
                   2500:   GEN y = cgetg(7,t_VEC);
                   2501:   long i;
                   2502:   checkbnr(bnr);
                   2503:   y[1] = (long)bnfnewprec((GEN)bnr[1],prec);
                   2504:   for (i=2; i<7; i++) y[i]=lcopy((GEN)bnr[i]);
                   2505:   return y;
                   2506: }
                   2507:
                   2508: GEN
                   2509: bnfmake(GEN sbnf, long prec)
                   2510: {
                   2511:   long av = avma, j,k,n,r1,r2,ru,lpf;
                   2512:   GEN p1,x,bas,ro,nf,mun,funits,index;
                   2513:   GEN pfc,vp,mc,clgp,clgp2,res,y,W,racu,reg,matal;
                   2514:
                   2515:   if (typ(sbnf)!=t_VEC || lg(sbnf)!=13)
                   2516:     err(talker,"incorrect sbnf in bnfmake");
                   2517:   x=(GEN)sbnf[1]; bas=(GEN)sbnf[4]; n=lg(bas)-1;
                   2518:   r1=itos((GEN)sbnf[2]); r2=(n-r1)>>1; ru=r1+r2;
                   2519:   ro=(GEN)sbnf[5];
                   2520:   if (prec > gprecision(ro)) ro=get_roots(x,r1,ru,prec);
                   2521:   index = gun;
                   2522:   for (j=2; j<=n; j++) index = mulii(index, denom(leading_term(bas[j])));
                   2523:
                   2524:   nf=cgetg(10,t_VEC);
                   2525:   nf[1]=sbnf[1]; p1=cgetg(3,t_VEC); p1[1]=lstoi(r1); p1[2]=lstoi(r2);
                   2526:   nf[2]=(long)p1;
                   2527:   nf[3]=sbnf[3];
                   2528:   nf[4]=(long)index;
                   2529:   nf[6]=(long)ro;
                   2530:   nf[7]=(long)bas;
                   2531:   get_nf_matrices(nf, 0);
                   2532:
                   2533:   funits=cgetg(ru,t_VEC); p1 = (GEN)sbnf[11];
                   2534:   for (k=1; k < lg(p1); k++)
                   2535:     funits[k] = lmul(bas,(GEN)p1[k]);
                   2536:   mun = get_arch2_i(nf,funits,prec,1);
                   2537:
                   2538:   prec=gprecision(ro); if (prec<DEFAULTPREC) prec=DEFAULTPREC;
                   2539:   matal = get_matal((GEN)sbnf[12]);
                   2540:   if (!matal) matal = (GEN)sbnf[12];
                   2541:   mc = get_arch2_i(nf,matal,prec,0);
                   2542:
                   2543:   pfc=(GEN)sbnf[9]; lpf=lg(pfc);
                   2544:   vectbase=cgetg(lpf,t_COL); vp=cgetg(lpf,t_COL);
                   2545:   for (j=1; j<lpf; j++)
                   2546:   {
                   2547:     vp[j]=lstoi(j);
                   2548:     vectbase[j]=(long)decodeprime(nf,(GEN)pfc[j]);
                   2549:   }
                   2550:   W = (GEN)sbnf[7];
                   2551:   class_group_gen(nf,W,mc,vp,&clgp,&clgp2, prec); /* uses vectbase */
                   2552:
                   2553:   reg = get_regulator(mun,prec);
                   2554:   p1=cgetg(3,t_VEC); racu=(GEN)sbnf[10];
                   2555:   p1[1]=racu[1]; p1[2]=lmul(bas,(GEN)racu[2]);
                   2556:   racu=p1;
                   2557:
                   2558:   res=cgetg(7,t_VEC);
                   2559:   res[1]=(long)clgp; res[2]=(long)reg;    res[3]=(long)dbltor(1.0);
                   2560:   res[4]=(long)racu; res[5]=(long)funits; res[6]=lstoi(1000);
                   2561:
                   2562:   y=cgetg(11,t_VEC);
                   2563:   y[1]=(long)W;   y[2]=sbnf[8];        y[3]=(long)mun;
                   2564:   y[4]=(long)mc;  y[5]=(long)vectbase; y[6]=(long)vp;
                   2565:   y[7]=(long)nf;  y[8]=(long)res;      y[9]=(long)clgp2; y[10]=sbnf[12];
                   2566:   return gerepilecopy(av,y);
                   2567: }
                   2568:
                   2569: static GEN
                   2570: classgroupall(GEN P, GEN data, long flag, long prec)
                   2571: {
                   2572:   long court[3],doubl[4];
                   2573:   long av=avma,flun,lx, minsFB=3,nbrelpid=4;
                   2574:   GEN bach=doubl,bach2=doubl,RELSUP=court,borne=gun;
                   2575:
                   2576:   if (!data) lx=1;
                   2577:   else
                   2578:   {
                   2579:     lx = lg(data);
                   2580:     if (typ(data)!=t_VEC || lx > 7)
                   2581:       err(talker,"incorrect parameters in classgroup");
                   2582:   }
                   2583:   court[0]=evaltyp(t_INT) | evallg(3); affsi(5,court);
                   2584:   doubl[0]=evaltyp(t_REAL)| evallg(4); affrr(dbltor(0.3),doubl);
                   2585:   avma=av;
                   2586:   switch(lx)
                   2587:   {
                   2588:     case 7: minsFB  = itos((GEN)data[6]);
                   2589:     case 6: nbrelpid= itos((GEN)data[5]);
                   2590:     case 5: borne  = (GEN)data[4];
                   2591:     case 4: RELSUP = (GEN)data[3];
                   2592:     case 3: bach2 = (GEN)data[2];
                   2593:     case 2: bach  = (GEN)data[1];
                   2594:   }
                   2595:   switch(flag)
                   2596:   {
                   2597:     case 0: flun=-2; break;
                   2598:     case 1: flun=-3; break;
                   2599:     case 2: flun=-1; break;
                   2600:     case 3: return smallbuchinit(P,bach,bach2,RELSUP,borne,nbrelpid,minsFB,prec);
                   2601:     case 4: flun=2; break;
                   2602:     case 5: flun=3; break;
                   2603:     case 6: flun=0; break;
                   2604:     default: err(flagerr,"classgroupall");
                   2605:       return NULL; /* not reached */
                   2606:   }
                   2607:   return buchall(P,bach,bach2,RELSUP,borne,nbrelpid,minsFB,flun,prec);
                   2608: }
                   2609:
                   2610: GEN
                   2611: bnfclassunit0(GEN P, long flag, GEN data, long prec)
                   2612: {
                   2613:   if (typ(P)==t_INT) return quadclassunit0(P,0,data,prec);
                   2614:   if (flag < 0 || flag > 2) err(flagerr,"bnfclassunit");
                   2615:   return classgroupall(P,data,flag+4,prec);
                   2616: }
                   2617:
                   2618: GEN
                   2619: bnfinit0(GEN P, long flag, GEN data, long prec)
                   2620: {
                   2621: #if 0
                   2622:   /* TODO: synchronize quadclassunit output with bnfinit */
                   2623:   if (typ(P)==t_INT)
                   2624:   {
                   2625:     if (flag<4) err(impl,"specific bnfinit for quadratic fields");
                   2626:     return quadclassunit0(P,0,data,prec);
                   2627:   }
                   2628: #endif
                   2629:   if (flag < 0 || flag > 3) err(flagerr,"bnfinit");
                   2630:   return classgroupall(P,data,flag,prec);
                   2631: }
                   2632:
                   2633: GEN
                   2634: classgrouponly(GEN P, GEN data, long prec)
                   2635: {
                   2636:   ulong av = avma;
                   2637:   GEN z;
                   2638:
                   2639:   if (typ(P)==t_INT)
                   2640:   {
                   2641:     z=quadclassunit0(P,0,data,prec); setlg(z,4);
                   2642:     return gerepilecopy(av,z);
                   2643:   }
                   2644:   z=(GEN)classgroupall(P,data,6,prec)[1];
                   2645:   return gerepilecopy(av,(GEN)z[5]);
                   2646: }
                   2647:
                   2648: GEN
                   2649: regulator(GEN P, GEN data, long prec)
                   2650: {
                   2651:   ulong av = avma;
                   2652:   GEN z;
                   2653:
                   2654:   if (typ(P)==t_INT)
                   2655:   {
                   2656:     if (signe(P)>0)
                   2657:     {
                   2658:       z=quadclassunit0(P,0,data,prec);
                   2659:       return gerepilecopy(av,(GEN)z[4]);
                   2660:     }
                   2661:     return gun;
                   2662:   }
                   2663:   z=(GEN)classgroupall(P,data,6,prec)[1];
                   2664:   return gerepilecopy(av,(GEN)z[6]);
                   2665: }
                   2666:
                   2667: #ifdef INLINE
                   2668: INLINE
                   2669: #endif
                   2670: GEN
                   2671: col_0(long n)
                   2672: {
                   2673:    GEN c = (GEN) gpmalloc(sizeof(long)*(n+1));
                   2674:    long i;
                   2675:    for (i=1; i<=n; i++) c[i]=0;
                   2676:    c[0] = evaltyp(t_VECSMALL) | evallg(n);
                   2677:    return c;
                   2678: }
                   2679:
                   2680: GEN
                   2681: cgetc_col(long n, long prec)
                   2682: {
                   2683:   GEN c = cgetg(n+1,t_COL);
                   2684:   long i;
                   2685:   for (i=1; i<=n; i++) c[i] = (long)cgetc(prec);
                   2686:   return c;
                   2687: }
                   2688:
                   2689: static GEN
                   2690: buchall_end(GEN nf,GEN CHANGE,long fl,long k, GEN fu, GEN clg1, GEN clg2,
                   2691:             GEN reg, GEN c_1, GEN zu, GEN W, GEN B,
                   2692:             GEN xarch, GEN matarch, GEN vectbase, GEN vperm)
                   2693: {
                   2694:   long i, l = labs(fl)>1? 11: fl? 9: 8;
                   2695:   GEN p1,z, RES = cgetg(11,t_COL);
                   2696:
                   2697:   setlg(RES,l);
                   2698:   RES[5]=(long)clg1;
                   2699:   RES[6]=(long)reg;
                   2700:   RES[7]=(long)c_1;
                   2701:   RES[8]=(long)zu;
                   2702:   RES[9]=(long)fu;
                   2703:   RES[10]=lstoi(k);
                   2704:   if (fl>=0)
                   2705:   {
                   2706:     RES[1]=nf[1];
                   2707:     RES[2]=nf[2]; p1=cgetg(3,t_VEC); p1[1]=nf[3]; p1[2]=nf[4];
                   2708:     RES[3]=(long)p1;
                   2709:     RES[4]=nf[7];
                   2710:     z=cgetg(2,t_MAT); z[1]=lcopy(RES); return z;
                   2711:   }
                   2712:   z=cgetg(11,t_VEC);
                   2713:   z[1]=(long)W;
                   2714:   z[2]=(long)B;
                   2715:   z[3]=(long)xarch;
                   2716:   z[4]=(long)matarch;
                   2717:   z[5]=(long)vectbase;
                   2718:   for (i=lg(vperm)-1; i>0; i--) vperm[i]=lstoi(vperm[i]);
                   2719:   settyp(vperm, t_VEC);
                   2720:   z[6]=(long)vperm;
                   2721:   z[7]=(long)nf; RES+=4; RES[0]=evaltyp(t_VEC) | evallg(l-4);
                   2722:   z[8]=(long)RES;
                   2723:   z[9]=(long)clg2;
                   2724:   z[10]=zero; /* dummy: we MUST have lg(bnf) != lg(nf) */
                   2725:   if (CHANGE) { p1=cgetg(3,t_VEC); p1[1]=(long)z; p1[2]=(long)CHANGE; z=p1; }
                   2726:   return gcopy(z);
                   2727: }
                   2728:
                   2729: static GEN
                   2730: buchall_for_degree_one_pol(GEN nf, GEN CHANGE, long flun)
                   2731: {
                   2732:   long av = avma, k = EXP220;
                   2733:   GEN W,B,xarch,matarch,vectbase,vperm;
                   2734:   GEN fu=cgetg(1,t_VEC), reg=gun, c_1=gun, zu=cgetg(3,t_VEC);
                   2735:   GEN clg1=cgetg(4,t_VEC), clg2=cgetg(4,t_VEC);
                   2736:
                   2737:   clg1[1]=un; clg1[2]=clg1[3]=clg2[3]=lgetg(1,t_VEC);
                   2738:   clg2[1]=clg2[2]=lgetg(1,t_MAT);
                   2739:   zu[1]=deux; zu[2]=lnegi(gun);
                   2740:   W=B=xarch=matarch=cgetg(1,t_MAT);
                   2741:   vectbase=cgetg(1,t_COL); vperm=cgetg(1,t_VEC);
                   2742:
                   2743:   return gerepileupto(av, buchall_end(nf,CHANGE,flun,k,fu,clg1,clg2,reg,c_1,zu,W,B,xarch,matarch,vectbase,vperm));
                   2744: }
                   2745:
                   2746: static GEN
                   2747: get_LLLnf(GEN nf, long prec)
                   2748: {
                   2749:   GEN M  = gmael(nf,5,1);
                   2750:   GEN T2 = gmael(nf,5,3);
                   2751:   GEN cbase = lllgramintern(T2,100,1,prec);
                   2752:   GEN v = cgetg(5,t_VEC);
                   2753:   if (!cbase) return NULL;
                   2754:   if (gegal(cbase, idmat(lg(T2)-1))) cbase = NULL;
                   2755:   v[1] = (long) (cbase? qf_base_change(T2, cbase, 1): T2);
                   2756:   v[2] = (long) (cbase? gmul(M, cbase): M);
                   2757:   v[3] = (long) cbase;
                   2758:   v[4] = (long) (cbase? ZM_inv(cbase,gun): NULL); return v;
                   2759: }
                   2760:
                   2761: GEN
                   2762: buchall(GEN P,GEN gcbach,GEN gcbach2,GEN gRELSUP,GEN gborne,long nbrelpid,
                   2763:         long minsFB,long flun,long prec)
                   2764: {
                   2765:   ulong av = avma,av0,av1,limpile;
                   2766:   long N,R1,R2,RU,PRECREG,PRECLLL,KCCO,RELSUP,LIMC,LIMC2,lim;
                   2767:   long nlze,sreg,nrelsup,nreldep,phase,matmax,i,j,k,ss,cglob;
                   2768:   long first=1, sfb_increase=0, sfb_trials=0, precdouble=0, precadd=0;
                   2769:   double cbach,cbach2,drc,LOGD2;
                   2770:   GEN p1,vecT2,fu,zu,nf,LLLnf,D,xarch,W,reg,lfun,z,clh,vperm,subFB;
                   2771:   GEN B,C,c1,sublambda,pdep,parch,liste,invp,clg1,clg2, *mat;
                   2772:   GEN CHANGE=NULL, extramat=NULL, extraC=NULL, list_jideal=NULL;
                   2773:   char *precpb = NULL;
                   2774:
                   2775:   if (DEBUGLEVEL) timer2();
                   2776:
                   2777:   if (typ(P)==t_POL) nf = NULL; else { nf = checknf(P); P = (GEN)nf[1]; }
                   2778:   if (typ(gRELSUP) != t_INT) gRELSUP = gtrunc(gRELSUP);
                   2779:   RELSUP = itos(gRELSUP);
                   2780:   if (RELSUP<=0) err(talker,"not enough relations in bnfxxx");
                   2781:
                   2782:   /* Initializations */
                   2783:   fu = NULL; /* gcc -Wall */
                   2784:   N = degpol(P); PRECREG = max(BIGDEFAULTPREC,prec);
                   2785:   if (!nf)
                   2786:   {
                   2787:     nf = initalgall0(P, nf_REGULAR, PRECREG);
                   2788:     /* P was non-monic and nfinit changed it ? */
                   2789:     if (lg(nf)==3) { CHANGE = (GEN)nf[2]; nf = (GEN)nf[1]; }
                   2790:   }
                   2791:   if (N<=1) return buchall_for_degree_one_pol(nf,CHANGE,flun);
                   2792:   zu = rootsof1(nf);
                   2793:   zu[2] = lmul((GEN)nf[7],(GEN)zu[2]);
                   2794:   if (DEBUGLEVEL) msgtimer("initalg & rootsof1");
                   2795:
                   2796:   R1 = itos(gmael(nf,2,1)); R2 = (N-R1)>>1; RU = R1+R2;
                   2797:   D = (GEN)nf[3]; drc = fabs(gtodouble(D));
                   2798:   LOGD2 = log(drc); LOGD2 = LOGD2*LOGD2;
                   2799:   lim = (long) (exp(-(double)N) * sqrt(2*PI*N*drc) * pow(4/PI,(double)R2));
                   2800:   if (lim < 3) lim = 3;
                   2801:   cbach = min(12., gtodouble(gcbach)); cbach /= 2;
                   2802:   cbach2 = gtodouble(gcbach2);
                   2803:   if (DEBUGLEVEL)
                   2804:   {
                   2805:     fprintferr("N = %ld, R1 = %ld, R2 = %ld, RU = %ld\n",N,R1,R2,RU);
                   2806:     fprintferr("D = %Z\n",D);
                   2807:   }
                   2808:   av0 = avma; mat = NULL; FB = NULL;
                   2809:
                   2810: START:
                   2811:   avma = av0;
                   2812:   if (first) first = 0; else desallocate(&mat);
                   2813:   if (precpb)
                   2814:   {
                   2815:     precdouble++;
                   2816:     if (precadd)
                   2817:       PRECREG += precadd;
                   2818:     else
                   2819:       PRECREG = (PRECREG<<1)-2;
                   2820:     if (DEBUGLEVEL)
                   2821:     {
                   2822:       char str[64]; sprintf(str,"buchall (%s)",precpb);
                   2823:       err(warnprec,str,PRECREG);
                   2824:     }
                   2825:     precpb = NULL;
                   2826:     nf = nfnewprec(nf,PRECREG); av0 = avma;
                   2827:   }
                   2828:   else
                   2829:     cbach = check_bach(cbach,12.);
                   2830:   precadd = 0;
                   2831:
                   2832:   /* T2-LLL-reduce nf.zk */
                   2833:   LLLnf = get_LLLnf(nf, PRECREG);
                   2834:   if (!LLLnf) { precpb = "LLLnf"; goto START; }
                   2835:
                   2836:   LIMC = (long)(cbach*LOGD2); if (LIMC < 20) LIMC = 20;
                   2837:   LIMC2= max(3 * N, (long)(cbach2*LOGD2));
                   2838:   if (LIMC2 < LIMC) LIMC2 = LIMC;
                   2839:   if (DEBUGLEVEL) { fprintferr("LIMC = %ld, LIMC2 = %ld\n",LIMC,LIMC2); }
                   2840:
                   2841:   /* initialize FB, [sub]vperm */
                   2842:   lfun = FBgen(nf,LIMC2,LIMC);
                   2843:   if (!lfun) goto START;
                   2844:   vperm = cgetg(lg(vectbase), t_VECSMALL);
                   2845:   sfb_trials = sfb_increase = 0;
                   2846:   subFB = subFBgen(N,min(lim,LIMC2), minsFB, vperm, &ss);
                   2847:   if (!subFB) goto START;
                   2848:   nreldep = nrelsup = 0;
                   2849:
                   2850:   /* PRECLLL = prec for LLL-reductions (idealred)
                   2851:    * PRECREG = prec for archimedean components */
                   2852:   PRECLLL = DEFAULTPREC
                   2853:           + ((expi(D)*(lg(subFB)-2)+((N*N)>>2))>>TWOPOTBITS_IN_LONG);
                   2854:   if (!precdouble) PRECREG = prec+1;
                   2855:   if (PRECREG < PRECLLL) PRECREG = PRECLLL;
                   2856:   KCCO = KC+RU-1 + max(ss,RELSUP); /* expected number of needed relations */
                   2857:   if (DEBUGLEVEL)
                   2858:     fprintferr("relsup = %ld, ss = %ld, KCZ = %ld, KC = %ld, KCCO = %ld\n",
                   2859:                RELSUP,ss,KCZ,KC,KCCO);
                   2860:   matmax = 10*KCCO + MAXRELSUP; /* make room for lots of relations */
                   2861:   mat = (GEN*)gpmalloc(sizeof(GEN)*(matmax + 1));
                   2862:   setlg(mat, KCCO+1);
                   2863:   C = cgetg(KCCO+1,t_MAT);
                   2864:   /* trivial relations (p) = prod P^e */
                   2865:   cglob = 0; z = zerocol(RU);
                   2866:   for (i=1; i<=KCZ; i++)
                   2867:   {
                   2868:     GEN P = idealbase[i];
                   2869:     if (isclone(P))
                   2870:     { /* all prime divisors in FB */
                   2871:       unsetisclone(P); cglob++;
                   2872:       C[cglob] = (long)z; /* 0 */
                   2873:       mat[cglob] = p1 = col_0(KC);
                   2874:       k = numideal[FB[i]];
                   2875:       p1[0] = k+1; /* for already_found_relation */
                   2876:       p1 += k;
                   2877:       for (j=lg(P)-1; j; j--) p1[j] = itos(gmael(P,j,3));
                   2878:     }
                   2879:   }
                   2880:   if (DEBUGLEVEL) fprintferr("After trivial relations, cglob = %ld\n",cglob);
                   2881:   /* initialize for other relations */
                   2882:   for (i=cglob+1; i<=KCCO; i++)
                   2883:   {
                   2884:     mat[i] = col_0(KC);
                   2885:     C[i] = (long)cgetc_col(RU,PRECREG);
                   2886:   }
                   2887:   av1 = avma; liste = cgetg(KC+1,t_VECSMALL);
                   2888:   for (i=1; i<=KC; i++) liste[i] = 0;
                   2889:   invp = relationrank(mat,cglob,liste);
                   2890:
                   2891:   /* relations through elements of small norm */
                   2892:   cglob = small_norm_for_buchall(cglob,mat,C,(long)LIMC,PRECREG,
                   2893:                                  nf,gborne,nbrelpid,invp,liste,LLLnf);
                   2894:   if (cglob < 0) { precpb = "small_norm"; goto START; }
                   2895:   avma = av1; limpile = stack_lim(av1,1);
                   2896:
                   2897:   phase = 0;
                   2898:   nlze = matmax = 0; /* for lint */
                   2899:   vecT2 = NULL;
                   2900:
                   2901:   /* random relations */
                   2902:   if (cglob == KCCO) /* enough rels, but init random_relations just in case */
                   2903:     ((void(*)(long))random_relation)(-1);
                   2904:   else
                   2905:   {
                   2906:     GEN matarch;
                   2907:
                   2908:     if (DEBUGLEVEL) fprintferr("\n#### Looking for random relations\n");
                   2909: MORE:
                   2910:     if (sfb_increase)
                   2911:     {
                   2912:       if (DEBUGLEVEL) fprintferr("*** Increasing sub factor base\n");
                   2913:       sfb_increase = 0;
                   2914:       if (++sfb_trials >= SFB_MAX) goto START;
                   2915:       subFB = subFBgen(N,min(lim,LIMC2), lg(subFB)-1+SFB_STEP,NULL,&ss);
                   2916:       if (!subFB) goto START;
                   2917:       nreldep = nrelsup = 0;
                   2918:     }
                   2919:
                   2920:     if (phase == 0) matarch = C;
                   2921:     else
                   2922:     { /* reduced the relation matrix at least once */
                   2923:       long lgex = max(nlze, MIN_EXTRA); /* number of new relations sought */
                   2924:       long slim; /* total number of relations (including lgex new ones) */
                   2925:       setlg(extraC,  lgex+1);
                   2926:       setlg(extramat,lgex+1); /* were allocated after hnfspec */
                   2927:       slim = cglob+lgex;
                   2928:       if (slim > matmax)
                   2929:       {
                   2930:         mat = (long**)gprealloc(mat, (2*slim+1) * sizeof(long*),
                   2931:                                      (matmax+1) * sizeof(long*));
                   2932:         matmax = 2 * slim;
                   2933:       }
                   2934:       setlg(mat, slim+1);
                   2935:       if (DEBUGLEVEL)
                   2936:        fprintferr("\n(need %ld more relation%s)\n", lgex, (lgex==1)?"":"s");
                   2937:       for (j=cglob+1; j<=slim; j++) mat[j] = col_0(KC);
                   2938:       matarch = extraC - cglob; /* start at 0, the others at cglob */
                   2939:     }
                   2940:     if (!vecT2)
                   2941:     {
                   2942:       vecT2 = compute_vecT2(RU,nf);
                   2943:       av1 = avma;
                   2944:     }
                   2945:     if (!powsubFB)
                   2946:     {
                   2947:       powsubFBgen(nf,subFB,CBUCHG+1,PRECREG);
                   2948:       av1 = avma;
                   2949:     }
                   2950:     ss = random_relation(phase,cglob,(long)LIMC,PRECLLL,PRECREG,
                   2951:                          nf,subFB,vecT2,mat,matarch,list_jideal);
                   2952:     if (ss < 0)
                   2953:     { /* could not find relations */
                   2954:       if (ss != -1) precpb = "random_relation"; /* precision pb */
                   2955:       goto START;
                   2956:     }
                   2957:     if (DEBUGLEVEL > 2) dbg_outrel(phase,cglob,vperm,mat,matarch);
                   2958:     if (phase)
                   2959:       for (j=lg(extramat)-1; j>0; j--)
                   2960:       {
                   2961:        GEN c = mat[cglob+j], *g = (GEN*) extramat[j];
                   2962:        for (k=1; k<=KC; k++) g[k] = stoi(c[vperm[k]]);
                   2963:       }
                   2964:     cglob = ss;
                   2965:   }
                   2966:
                   2967:   /* reduce relation matrices */
                   2968:   if (phase == 0)
                   2969:   { /* never reduced before */
                   2970:     long lgex;
                   2971:     W = hnfspec(mat,vperm,&pdep,&B,&C, lg(subFB)-1);
                   2972:     phase = 1;
                   2973:     nlze = lg(pdep)>1? lg(pdep[1])-1: lg(B[1])-1;
                   2974:     if (nlze)
                   2975:     {
                   2976:       list_jideal = cgetg(nlze+1, t_VECSMALL);
                   2977:       for (i=1; i<=nlze; i++) list_jideal[i] = vperm[i];
                   2978:     }
                   2979:     lgex = max(nlze, MIN_EXTRA); /* set lgex > 0, in case regulator is 0 */
                   2980:     /* allocate now, reduce dimension later (setlg) when lgex goes down */
                   2981:     extramat= cgetg(lgex+1,t_MAT);
                   2982:     extraC  = cgetg(lgex+1,t_MAT);
                   2983:     for (j=1; j<=lgex; j++)
                   2984:     {
                   2985:       extramat[j]=lgetg(KC+1,t_COL);
                   2986:       extraC[j] = (long)cgetc_col(RU,PRECREG);
                   2987:     }
                   2988:   }
                   2989:   else
                   2990:   {
                   2991:     if (low_stack(limpile, stack_lim(av1,1)))
                   2992:     {
                   2993:       GEN *gptr[6];
                   2994:       if(DEBUGMEM>1) err(warnmem,"buchall");
                   2995:       gptr[0]=&W; gptr[1]=&C; gptr[2]=&B; gptr[3]=&pdep;
                   2996:       gptr[4]=&extramat; gptr[5]=&extraC; gerepilemany(av1,gptr,6);
                   2997:     }
                   2998:     list_jideal = NULL;
                   2999:     W = hnfadd(W,vperm,&pdep,&B,&C, extramat,extraC);
                   3000:     nlze = lg(pdep)>1? lg(pdep[1])-1: lg(B[1])-1;
                   3001:     if (nlze && ++nreldep > MAXRELSUP) { sfb_increase=1; goto MORE; }
                   3002:   }
                   3003:   if (nlze) goto MORE; /* dependent rows */
                   3004:
                   3005:   /* first attempt at regulator for the check */
                   3006:   sreg = (lg(mat)-1) - (lg(B)-1) - (lg(W)-1); /* = zc (cf hnffinal) */
                   3007:   xarch = cgetg(sreg+1,t_MAT); /* cols corresponding to units */
                   3008:   for (j=1; j<=sreg; j++) xarch[j] = C[j];
                   3009:   reg = compute_multiple_of_R(xarch,RU,N,&sublambda);
                   3010:   if (!reg)
                   3011:   { /* not full rank for units */
                   3012:     if (DEBUGLEVEL) fprintferr("regulator is zero.\n");
                   3013:     if (++nrelsup > MAXRELSUP) goto START;
                   3014:     nlze = MIN_EXTRA; goto MORE;
                   3015:   }
                   3016:   /* anticipate precision problems */
                   3017:   if (!sublambda) { precpb = "bestappr"; goto START; }
                   3018:
                   3019:   /* class number */
                   3020:   clh = dethnf_i(W);
                   3021:   if (DEBUGLEVEL) fprintferr("\n#### Tentative class number: %Z\n", clh);
                   3022:
                   3023:   /* check */
                   3024:   z = mulrr(lfun,gmul(gmul2n(gpuigs(shiftr(mppi(DEFAULTPREC),1),-R2),-R1),
                   3025:                      gsqrt(absi(D),DEFAULTPREC)));
                   3026:   z = mulri(z,(GEN)zu[1]);
                   3027:   /* z = Res (zeta_K, s = 1) * w D^(1/2) / [ 2^r1 (2pi)^r2 ] = h R */
                   3028:   p1 = gmul2n(divir(clh,z), 1);
                   3029:   /* c1 should be close to 2, and not much smaller */
                   3030:   c1 = compute_check(sublambda,p1,&parch,&reg);
                   3031:   /* precision problems? */
                   3032:   if (!c1 || gcmpgs(gmul2n(c1,1),3) < 0)
                   3033:   { /* has to be a precision problem unless we cheat on Bach constant */
                   3034:     if (!precdouble) precpb = "compute_check";
                   3035:     goto START;
                   3036:   }
                   3037:   if (gcmpgs(c1,3) > 0)
                   3038:   {
                   3039:     if (++nrelsup <= MAXRELSUP)
                   3040:     {
                   3041:       if (DEBUGLEVEL) fprintferr("\n ***** check = %f\n",gtodouble(c1)/2);
                   3042:       nlze = MIN_EXTRA; goto MORE;
                   3043:     }
                   3044:     if (cbach < 11.99) { sfb_increase = 1; goto MORE; }
                   3045:     err(warner,"suspicious check. Try to increase extra relations");
                   3046:   }
                   3047:
                   3048:   if (KCZ2 > KCZ)
                   3049:   { /* "be honest" */
                   3050:     if (!powsubFB) powsubFBgen(nf,subFB,CBUCHG+1,PRECREG);
                   3051:     if (!be_honest(nf,subFB,PRECLLL)) goto START;
                   3052:   }
                   3053:
                   3054:   /* fundamental units */
                   3055:   if (flun < 0 || flun > 1)
                   3056:   {
                   3057:     xarch = cleancol(gmul(xarch,parch),N,PRECREG);
                   3058:     if (DEBUGLEVEL) msgtimer("cleancol");
                   3059:   }
                   3060:   if (labs(flun) > 1)
                   3061:   {
                   3062:     fu = getfu(nf,&xarch,reg,flun,&k,PRECREG);
                   3063:     if (k <= 0 && labs(flun) > 2)
                   3064:     {
                   3065:       if (k < 0)
                   3066:       {
                   3067:         precadd = (DEFAULTPREC-2) + ((-k) >> TWOPOTBITS_IN_LONG);
                   3068:         if (precadd <= 0) precadd = (DEFAULTPREC-2);
                   3069:       }
                   3070:       precpb = "getfu"; goto START;
                   3071:     }
                   3072:   }
                   3073:
                   3074:   /* class group generators */
                   3075:   i = lg(C)-sreg; C += sreg; C[0] = evaltyp(t_MAT)|evallg(i);
                   3076:   C = cleancol(C,N,PRECREG);
                   3077:   class_group_gen(nf,W,C,vperm, &clg1, &clg2, PRECREG);
                   3078:
                   3079:   c1 = gdiv(gmul(reg,clh), z);
                   3080:   desallocate(&mat);
                   3081:
                   3082:   return gerepileupto(av, buchall_end(nf,CHANGE,flun,k,fu,clg1,clg2,reg,c1,zu,W,B,xarch,C,vectbase,vperm));
                   3083: }

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