Annotation of OpenXM_contrib/pari-2.2/src/basemath/buch2.c, Revision 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,®);
! 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>