Annotation of OpenXM_contrib/pari/src/basemath/buch2.c, Revision 1.1
1.1 ! maekawa 1: /*******************************************************************/
! 2: /* */
! 3: /* CLASS GROUP AND REGULATOR (McCURLEY, BUCHMANN) */
! 4: /* GENERAL NUMBER FIELDS */
! 5: /* */
! 6: /*******************************************************************/
! 7: /* $Id: buch2.c,v 1.11 1999/09/24 16:19:25 karim Exp $ */
! 8: #include "pari.h"
! 9: #include "parinf.h"
! 10: long addcolumntomatrix(long *V, long n,long r,GEN *INVP,long *L);
! 11: double check_bach(double cbach, double B);
! 12: GEN get_arch_real(GEN nf,GEN x,GEN *emb,long prec);
! 13: GEN get_arch(GEN nf,GEN x,long prec);
! 14: GEN get_roots(GEN x,long r1,long ru,long prec);
! 15: long ideal_is_zk(GEN ideal,long N);
! 16: GEN idealpowred_prime(GEN nf, GEN vp, GEN n, long prec);
! 17: long int_elt_val(GEN nf, GEN x, GEN p, GEN b, long v);
! 18: GEN make_M(long n,long ru,GEN basis,GEN roo);
! 19: GEN make_MC(long n,long r1,long ru,GEN M);
! 20: GEN make_TI(GEN nf, GEN TI, GEN con);
! 21:
! 22: #define SFB_MAX 2
! 23: #define SFB_STEP 2
! 24: #define MIN_EXTRA 1
! 25:
! 26: #define RANDOM_BITS 4
! 27: static const int CBUCHG = (1<<RANDOM_BITS) - 1;
! 28: static const int randshift = BITS_IN_RANDOM-1 - RANDOM_BITS;
! 29: #undef RANDOM_BITS
! 30:
! 31: static long KC,KCZ,KCZ2,MAXRELSUP;
! 32: static long primfact[500],expoprimfact[500];
! 33: static long *factorbase, *numfactorbase, *numideal;
! 34: static GEN *idealbase, vectbase, powsubfb;
! 35:
! 36: /* factorbase[i] i-th rational prime used in factor base
! 37: * numfactorbase[i] index k such that factorbase[k]=i (0 if i is not prime)
! 38: *
! 39: * vectbase vector of all ideals in factorbase
! 40: * vecbase o subfb = part of factorbase used to build random relations
! 41: * powsubfb array lg(subfb) x (CBUCHG+1) = all powers up to CBUCHG
! 42: *
! 43: * idealbase[i] prime ideals above i in factorbase
! 44: * numideal[i] index k such that idealbase[k] = i.
! 45: *
! 46: * matcopy all relations found (as long integers, not reduced)
! 47: * cmptglob lg(matcopy) = total number of relations found
! 48: *
! 49: * Use only non-inert primes, coprime to discriminant index F:
! 50: * KC = number of prime ideals in factor base (norm < Bach cst)
! 51: * KC2= number of prime ideals assumed to generate class group (>= KC)
! 52: *
! 53: * KCZ = number of rational primes under ideal counted by KC
! 54: * KCZ2= same for KC2le nombre d'ideaux premiers utilises au total.
! 55: */
! 56:
! 57: /* x[0] = length(x) */
! 58: static long
! 59: ccontent(long* x)
! 60: {
! 61: long i, s=labs(x[1]);
! 62: for (i=2; i<=x[0] && s>1; i++) s = cgcd(x[i],s);
! 63: return s;
! 64: }
! 65:
! 66: static void
! 67: desallocate(long **matcopy)
! 68: {
! 69: long i;
! 70: free(numfactorbase); free(factorbase); free(numideal); free(idealbase);
! 71: if (matcopy)
! 72: {
! 73: for (i=lg(matcopy)-1; i; i--) free(matcopy[i]);
! 74: free(matcopy); matcopy = NULL;
! 75: }
! 76: powsubfb = NULL;
! 77: }
! 78:
! 79: /* Return the list of indexes or the primes chosen for the subfactorbase.
! 80: * Fill vperm (if !=0): primes ideals sorted by increasing norm (except the
! 81: * ones in subfactorbase come first [dense rows come first for hnfspec])
! 82: * ss = number of rational primes whose divisors are all in factorbase
! 83: */
! 84: static GEN
! 85: subfactorbasegen(long N,long m,long minsfb,GEN vperm, long *ptss)
! 86: {
! 87: long av = avma,i,j, lv=lg(vectbase),s=0,s1=0,n=0,ss=0,z=0;
! 88: GEN y1,y2,subfb,perm,perm1,P,Q;
! 89: double prod;
! 90:
! 91: (void)new_chunk(lv); /* room for subfb */
! 92: y1 = cgetg(lv,t_COL);
! 93: y2 = cgetg(lv,t_COL);
! 94: for (i=1,P=(GEN)vectbase[i];;P=Q)
! 95: { /* we'll sort ideals by norm (excluded ideals = "zero") */
! 96: long e = itos((GEN)P[3]);
! 97: long ef= e*itos((GEN)P[4]);
! 98:
! 99: s1 += ef;
! 100: y2[i] = (long)powgi((GEN)P[1],(GEN)P[4]);
! 101: /* take only unramified ideals */
! 102: if (e>1) { y1[i]=zero; s=0; z++; } else { y1[i]=y2[i]; s += ef; }
! 103:
! 104: i++; Q = (GEN)vectbase[i];
! 105: if (i == lv || !egalii((GEN)P[1], (GEN)Q[1]))
! 106: { /* don't take all P above a given p (delete the last one) */
! 107: if (s == N) { y1[i-1]=zero; z++; }
! 108: if (s1== N) ss++;
! 109: if (i == lv) break;
! 110: s=0; s1=0;
! 111: }
! 112: }
! 113: if (z+minsfb >= lv) return NULL;
! 114:
! 115: prod = 1.0;
! 116: perm = sindexsort(y1) + z; /* skip "zeroes" (excluded ideals) */
! 117: for(;;)
! 118: {
! 119: if (++n > minsfb && (z+n >= lv || prod > m + 0.5)) break;
! 120: prod *= gtodouble((GEN)y1[perm[n]]);
! 121: }
! 122: if (prod < m) return NULL;
! 123: n--;
! 124:
! 125: /* take the first (non excluded) n ideals (wrt norm), put them first, and
! 126: * sort the rest by increasing norm */
! 127: for (j=1; j<=n; j++) y2[perm[j]] = zero;
! 128: perm1 = sindexsort(y2); avma = av;
! 129:
! 130: subfb = cgetg(n+1, t_VECSMALL);
! 131: if (vperm)
! 132: {
! 133: for (j=1; j<=n; j++) vperm[j] = perm[j];
! 134: for ( ; j<lv; j++) vperm[j] = perm1[j];
! 135: }
! 136: for (j=1; j<=n; j++) subfb[j] = perm[j];
! 137:
! 138: if (DEBUGLEVEL)
! 139: {
! 140: if (DEBUGLEVEL>3)
! 141: {
! 142: fprintferr("\n***** IDEALS IN FACTORBASE *****\n\n");
! 143: for (i=1; i<=KC; i++) fprintferr("no %ld = %Z\n",i,vectbase[i]);
! 144: fprintferr("\n***** IDEALS IN SUB FACTORBASE *****\n\n");
! 145: P=cgetg(n+1,t_COL);
! 146: for (j=1; j<=n; j++) P[j] = vectbase[subfb[j]];
! 147: outerr(P);
! 148: fprintferr("\n***** INITIAL PERMUTATION *****\n\n");
! 149: fprintferr("vperm = %Z\n\n",vperm);
! 150: }
! 151: msgtimer("subfactorbase (%ld elements)",n);
! 152: }
! 153: *ptss = ss;
! 154: return subfb;
! 155: }
! 156:
! 157: static GEN
! 158: mulred(GEN nf,GEN x, GEN I, long prec,long precint)
! 159: {
! 160: long av = avma;
! 161: GEN p1, y = cgetg(3,t_VEC), z = cgetg(4,t_VEC);
! 162:
! 163: y[1] = (long)idealmulh(nf,I,(GEN)x[1]);
! 164: y[2] = x[2];
! 165: y = ideallllredall(nf,y,NULL,prec,precint);
! 166: z[3]=(long)dethnf((GEN)y[1]);
! 167: p1 = ideal_two_elt(nf,(GEN)y[1]);
! 168: z[1]=p1[1];
! 169: z[2]=p1[2]; y[1] = (long)z;
! 170: return gerepileupto(av,gcopy(y));
! 171: }
! 172:
! 173: /* Compute powers of prime ideals (P^0,...,P^a) in subfactorbase (assume a > 1)
! 174: * powsubfb[j][i] contains P_i^j in LLL form + archimedean part
! 175: */
! 176: static void
! 177: powsubfbgen(GEN nf,GEN subfb,long a,long prec,long precint)
! 178: {
! 179: long i,j,n=lg(subfb),N=lgef(nf[1])-3,RU;
! 180: GEN id, *pow;
! 181:
! 182: powsubfb = cgetg(n, t_VEC);
! 183: if (DEBUGLEVEL)
! 184: { fprintferr("Computing powers for sub-factor base:\n"); flusherr(); }
! 185: RU=itos(gmael(nf,2,1)); RU = RU + (N-RU)/2;
! 186: id=cgetg(3,t_VEC);
! 187: id[1] = (long)idmat(N);
! 188: id[2] = (long)zerocol(RU); settyp(id[2],t_VEC);
! 189:
! 190: for (i=1; i<n; i++)
! 191: {
! 192: GEN vp = (GEN)vectbase[subfb[i]];
! 193: GEN z = cgetg(4,t_VEC);
! 194: pow = (GEN*)cgetg(a+1,t_VEC);
! 195: powsubfb[i] = (long)pow; pow[0]=id;
! 196: pow[1]=cgetg(3,t_VEC);
! 197: pow[1][1] = (long)z;
! 198: z[1]=vp[1]; z[2]=vp[2]; z[3]=(long)powgi((GEN)vp[1], (GEN)vp[4]);
! 199: pow[1][2] = id[2];
! 200: vp = prime_to_ideal(nf,vp);
! 201: for (j=2; j<=a; j++)
! 202: {
! 203: pow[j] = mulred(nf,pow[j-1],vp,prec,precint);
! 204: if (DEBUGLEVEL>1) fprintferr(" %ld",j);
! 205: }
! 206: if (DEBUGLEVEL>1) { fprintferr("\n"); flusherr(); }
! 207: }
! 208: if (DEBUGLEVEL)
! 209: {
! 210: if (DEBUGLEVEL>7)
! 211: {
! 212: fprintferr("**** POWERS IN SUB-FACTOR BASE ****\n\n");
! 213: for (i=1; i<n; i++)
! 214: {
! 215: pow = (GEN*)powsubfb[i];
! 216: fprintferr("powsubfb[%ld]:\n",i);
! 217: for (j=0; j<=a; j++) fprintferr("^%ld = %Z\n", j,pow[j]);
! 218: fprintferr("\n");
! 219: }
! 220: }
! 221: msgtimer("powsubfbgen");
! 222: }
! 223: }
! 224:
! 225: /* Compute factorbase, numfactorbase, idealbase, vectbase, numideal.
! 226: * n2: bound for norm of tested prime ideals (includes be_honest())
! 227: * n : bound for prime ideals used to build relations (Bach cst) ( <= n2 )
! 228:
! 229: * Return prod_{p<=n2} (1-1/p) / prod_{Norm(P)<=n2} (1-1/Norm(P)),
! 230: * close to residue of zeta_K at 1 = 2^r1 (2pi)^r2 h R / (w D)
! 231: */
! 232: static GEN
! 233: factorbasegen(GEN nf,long n2,long n)
! 234: {
! 235: byteptr delta=diffptr;
! 236: long KC2,i,j,k,p,lon,ip,nor, N = lgef(nf[1])-3;
! 237: GEN p2,p1,NormP,lfun;
! 238: long prim[] = { evaltyp(t_INT)|m_evallg(3), evalsigne(1)|evallgefint(3),0 };
! 239:
! 240: numfactorbase= (long*)gpmalloc(sizeof(long)*(n2+1));
! 241: factorbase = (long*)gpmalloc(sizeof(long)*(n2+1));
! 242: numideal = (long*)gpmalloc(sizeof(long)*(n2+1));
! 243: idealbase = (GEN *)gpmalloc(sizeof(GEN )*(n2+1));
! 244:
! 245: lfun=realun(DEFAULTPREC);
! 246: p=*delta++; i=0; ip=0; KC=0;
! 247: while (p<=n2)
! 248: {
! 249: long av = avma, av1;
! 250: if (DEBUGLEVEL>=2) { fprintferr(" %ld",p); flusherr(); }
! 251: prim[2] = p; p1 = primedec(nf,prim); lon=lg(p1);
! 252: av1 = avma;
! 253: divrsz(mulsr(p-1,lfun),p,lfun);
! 254: if (itos(gmael(p1,1,4)) == N) /* p inert */
! 255: {
! 256: NormP = gpowgs(prim,N);
! 257: if (!is_bigint(NormP) && (nor=NormP[2]) <= n2)
! 258: divrsz(mulsr(nor,lfun),nor-1, lfun);
! 259: avma = av1;
! 260: }
! 261: else
! 262: {
! 263: numideal[p]=ip;
! 264: i++; numfactorbase[p]=i; factorbase[i]=p;
! 265: for (k=1; k<lon; k++,ip++)
! 266: {
! 267: NormP = powgi(prim,gmael(p1,k,4));
! 268: if (is_bigint(NormP) || (nor=NormP[2]) > n2) break;
! 269:
! 270: divrsz(mulsr(nor,lfun),nor-1, lfun);
! 271: }
! 272: /* keep all ideals with Norm <= n2 */
! 273: avma = av1;
! 274: if (k == lon)
! 275: setisclone(p1); /* flag it: all prime divisors in factorbase */
! 276: else
! 277: { setlg(p1,k); p1 = gerepile(av,av1,gcopy(p1)); }
! 278: idealbase[i] = p1;
! 279: }
! 280: if (!*delta) err(primer1);
! 281: p += *delta++;
! 282: if (KC == 0 && p>n) { KCZ=i; KC=ip; }
! 283: }
! 284: if (!KC) return NULL;
! 285: KCZ2=i; KC2=ip; MAXRELSUP = min(50,4*KC);
! 286:
! 287: vectbase=cgetg(KC+1,t_COL);
! 288: for (i=1; i<=KCZ; i++)
! 289: {
! 290: p1 = idealbase[i]; k=lg(p1);
! 291: p2 = vectbase + numideal[factorbase[i]];
! 292: for (j=1; j<k; j++) p2[j]=p1[j];
! 293: }
! 294: if (DEBUGLEVEL)
! 295: {
! 296: if (DEBUGLEVEL>1) fprintferr("\n");
! 297: if (DEBUGLEVEL>6)
! 298: {
! 299: fprintferr("########## FACTORBASE ##########\n\n");
! 300: fprintferr("KC2=%ld, KC=%ld, KCZ=%ld, KCZ2=%ld, MAXRELSUP=%ld\n",
! 301: KC2, KC, KCZ, KCZ2, MAXRELSUP);
! 302: for (i=1; i<=KCZ; i++)
! 303: fprintferr("++ idealbase[%ld] = %Z",i,idealbase[i]);
! 304: }
! 305: msgtimer("factor base");
! 306: }
! 307: return lfun;
! 308: }
! 309:
! 310: /* can we factor I / m ? (m pseudo minimum, computed in ideallllredpart1) */
! 311: static long
! 312: factorisegen(GEN nf,GEN idealvec,long kcz,long limp)
! 313: {
! 314: long i,j,n1,ip,v,p,k,lo,ifinal;
! 315: GEN x,q,r,P,p1,listexpo;
! 316: GEN I = (GEN)idealvec[1];
! 317: GEN m = (GEN)idealvec[2];
! 318: GEN Nm= (GEN)idealvec[3];
! 319:
! 320: x = divii(Nm, dethnf_i(I)); /* m in I, so NI | Nm */
! 321: if (is_pm1(x)) { primfact[0]=0; return 1; }
! 322: listexpo = new_chunk(kcz+1);
! 323: for (i=1; ; i++)
! 324: {
! 325: p=factorbase[i]; q=dvmdis(x,p,&r);
! 326: for (k=0; !signe(r); k++) { x=q; q=dvmdis(x,p,&r); }
! 327: listexpo[i] = k;
! 328: if (cmpis(q,p)<=0) break;
! 329: if (i==kcz) return 0;
! 330: }
! 331: if (cmpis(x,limp) > 0) return 0;
! 332:
! 333: ifinal = i; lo = 0;
! 334: for (i=1; i<=ifinal; i++)
! 335: {
! 336: k = listexpo[i];
! 337: if (k)
! 338: {
! 339: p = factorbase[i]; p1 = idealbase[numfactorbase[p]];
! 340: n1 = lg(p1); ip = numideal[p];
! 341: for (j=1; j<n1; j++)
! 342: {
! 343: P = (GEN)p1[j];
! 344: v = idealval(nf,I, P) - element_val2(nf,m,Nm, P);
! 345: if (v) /* hence < 0 */
! 346: {
! 347: primfact[++lo]=ip+j; expoprimfact[lo]=v;
! 348: k += v * itos((GEN)P[4]);
! 349: if (!k) break;
! 350: }
! 351: }
! 352: if (k) return 0;
! 353: }
! 354: }
! 355: if (is_pm1(x)) { primfact[0]=lo; return 1; }
! 356:
! 357: p = itos(x); p1 = idealbase[numfactorbase[p]];
! 358: n1 = lg(p1); ip = numideal[p];
! 359: for (k=1,j=1; j<n1; j++)
! 360: {
! 361: P = (GEN)p1[j];
! 362: v = idealval(nf,I, P) - element_val2(nf,m,Nm, P);
! 363: if (v)
! 364: {
! 365: primfact[++lo]=ip+j; expoprimfact[lo]=v;
! 366: k += v*itos((GEN)P[4]);
! 367: if (!k) { primfact[0]=lo; return 1; }
! 368: }
! 369: }
! 370: return 0;
! 371: }
! 372:
! 373: /* can we factor alpha ? */
! 374: static long
! 375: factorisealpha(GEN nf,GEN alpha,long kcz,long limp)
! 376: {
! 377: long i,j,n1,ip,v,p,k,lo,ifinal;
! 378: GEN x,q,r,P,p1,listexpo;
! 379:
! 380: x = absi(subres(gmul((GEN)nf[7],alpha), (GEN)nf[1]));
! 381: if (is_pm1(x)) { primfact[0]=0; return 1; }
! 382: listexpo = new_chunk(kcz+1);
! 383: for (i=1; ; i++)
! 384: {
! 385: p=factorbase[i]; q=dvmdis(x,p,&r);
! 386: for (k=0; !signe(r); k++) { x=q; q=dvmdis(x,p,&r); }
! 387: listexpo[i] = k;
! 388: if (cmpis(q,p)<=0) break;
! 389: if (i==kcz) return 0;
! 390: }
! 391: if (cmpis(x,limp) > 0) return 0;
! 392:
! 393: ifinal=i; lo = 0;
! 394: for (i=1; i<=ifinal; i++)
! 395: {
! 396: k = listexpo[i];
! 397: if (k)
! 398: {
! 399: p = factorbase[i]; p1 = idealbase[numfactorbase[p]];
! 400: n1 = lg(p1); ip = numideal[p];
! 401: for (j=1; j<n1; j++)
! 402: {
! 403: P = (GEN)p1[j];
! 404: v = int_elt_val(nf,alpha,(GEN)P[1],(GEN)P[5], k);
! 405: if (v)
! 406: {
! 407: primfact[++lo]=ip+j; expoprimfact[lo]=v;
! 408: k -= v * itos((GEN)P[4]);
! 409: if (!k) break;
! 410: }
! 411: }
! 412: if (k) return 0;
! 413: }
! 414: }
! 415: if (is_pm1(x)) { primfact[0]=lo; return 1; }
! 416:
! 417: p = itos(x); p1 = idealbase[numfactorbase[p]];
! 418: n1 = lg(p1); ip = numideal[p];
! 419: for (k=1,j=1; j<n1; j++)
! 420: {
! 421: P = (GEN)p1[j];
! 422: v = int_elt_val(nf,alpha,(GEN)P[1],(GEN)P[5], k);
! 423: if (v)
! 424: {
! 425: primfact[++lo]=ip+j; expoprimfact[lo]=v;
! 426: k -= v*itos((GEN)P[4]);
! 427: if (!k) { primfact[0]=lo; return 1; }
! 428: }
! 429: }
! 430: return 0;
! 431: }
! 432:
! 433: static GEN
! 434: cleancol(GEN x,long N,long PRECREG)
! 435: {
! 436: long i,j,av,tetpil,tx=typ(x),R1,RU;
! 437: GEN s,s2,re,p2,im,y;
! 438:
! 439: if (tx==t_MAT)
! 440: {
! 441: y=cgetg(lg(x),tx);
! 442: for (j=1; j<lg(x); j++)
! 443: y[j]=(long)cleancol((GEN)x[j],N,PRECREG);
! 444: return y;
! 445: }
! 446: if (!is_vec_t(tx)) err(talker,"not a vector/matrix in cleancol");
! 447: av = avma; RU=lg(x)-1; R1 = (RU<<1)-N;
! 448: re=greal(x); s=(GEN)re[1]; for (i=2; i<=RU; i++) s=gadd(s,(GEN)re[i]);
! 449: s=gdivgs(s,-N); if (N>R1) s2=gmul2n(s,1);
! 450: p2=gmul2n(mppi(PRECREG),2); im=gimag(x);
! 451: tetpil=avma; y=cgetg(RU+1,tx);
! 452: for (i=1; i<=RU; i++)
! 453: {
! 454: GEN p1=cgetg(3,t_COMPLEX); y[i]=(long)p1;
! 455: p1[1] = ladd((GEN)re[i], (i<=R1)?s:s2);
! 456: p1[2] = lmod((GEN)im[i], p2);
! 457: }
! 458: return gerepile(av,tetpil,y);
! 459: }
! 460:
! 461: #define RELAT 0
! 462: #define LARGE 1
! 463: #define PRECI 2
! 464: static GEN
! 465: not_given(long av, long flun, long reason)
! 466: {
! 467: if (labs(flun)==2)
! 468: {
! 469: char *s=NULL;
! 470: switch(reason)
! 471: {
! 472: case RELAT:
! 473: s = "not enough relations for fundamental units, not given"; break;
! 474: case LARGE:
! 475: s = "fundamental units too large, not given"; break;
! 476: case PRECI:
! 477: s = "insufficient precision for fundamental units, not given"; break;
! 478: }
! 479: err(warner,s);
! 480: }
! 481: avma=av; return cgetg(1,t_MAT);
! 482: }
! 483:
! 484: /* to check whether the exponential will get too big */
! 485: static long
! 486: expgexpo(GEN x)
! 487: {
! 488: long i,j,e, E = -HIGHEXPOBIT;
! 489: GEN p1;
! 490:
! 491: for (i=1; i<lg(x); i++)
! 492: for (j=1; j<lg(x[1]); j++)
! 493: {
! 494: p1 = gmael(x,i,j);
! 495: if (typ(p1)==t_COMPLEX) p1 = (GEN)p1[1];
! 496: e = gexpo(p1); if (e>E) E=e;
! 497: }
! 498: return E;
! 499: }
! 500:
! 501: static GEN
! 502: getfu(GEN nf,GEN *ptxarch,GEN reg,long flun,long *pte,long PRECREG)
! 503: {
! 504: long av=avma,i,j,RU,N=lgef(nf[1])-3,e,R1,R2;
! 505: GEN pol,p1,p2,p3,y,matep,s,xarch,vec;
! 506: GEN *gptr[2];
! 507:
! 508: if (DEBUGLEVEL)
! 509: { fprintferr("\n#### Computing fundamental units\n"); flusherr(); }
! 510: R1=itos(gmael(nf,2,1)); R2=(N-R1)>>1; RU=R1+R2;
! 511: if (RU==1) { *pte=BIGINT; return cgetg(1,t_MAT); }
! 512:
! 513: *pte = 0; xarch=*ptxarch;
! 514: if (gexpo(reg)<-8) return not_given(av,flun,RELAT);
! 515:
! 516: matep=cgetg(RU,t_MAT);
! 517: for (j=1; j<RU; j++)
! 518: {
! 519: s=gzero; for (i=1; i<=RU; i++) s=gadd(s,greal(gcoeff(xarch,i,j)));
! 520: s=gdivgs(s,N);
! 521: p1=cgetg(N+1,t_COL); matep[j]=(long)p1;
! 522: for (i=1; i<=R1; i++)
! 523: p1[i]=lsub(gcoeff(xarch,i,j),s);
! 524: for (i=R1+1; i<=RU; i++)
! 525: {
! 526: p1[i]=lsub(gmul2n(gcoeff(xarch,i,j),-1),s);
! 527: p1[i+R2]=lconj((GEN)p1[i]);
! 528: }
! 529: }
! 530: p1 = lllintern(greal(matep),1,PRECREG);
! 531: if (!p1) return not_given(av,flun,PRECI);
! 532: p2 = gmul(matep,p1);
! 533: if (expgexpo(p2) > 20) return not_given(av,flun,LARGE);
! 534: matep=gexp(p2,PRECREG);
! 535: xarch=gmul(xarch,p1);
! 536:
! 537: p1=gmael(nf,5,1);
! 538: p2=cgetg(N+1,t_MAT);
! 539: for (j=1; j<=N; j++)
! 540: {
! 541: p3=cgetg(N+1,t_COL); p2[j]=(long)p3;
! 542: for (i=1; i<=R1; i++) p3[i]=coeff(p1,i,j);
! 543: for ( ; i<=RU; i++)
! 544: {
! 545: p3[i]=coeff(p1,i,j);
! 546: p3[i+R2]=lconj((GEN)p3[i]);
! 547: }
! 548: }
! 549: y=greal(grndtoi(gauss(p2,matep),&e));
! 550: if (e>=0) return not_given(av,flun,PRECI);
! 551: *pte = -e; pol = (GEN) nf[1];
! 552: p1 = cgetg(3,t_COMPLEX);
! 553: p1[1] = zero; p1[2] = lmppi(PRECREG); /* p1 = i * pi */
! 554: if (R1<RU) p2 = gshift(p1,1);
! 555: vec = cgetg(RU+1,t_COL);
! 556: for (i=1; i<=R1; i++) vec[i]=(long)p1;
! 557: for ( ; i<=RU; i++) vec[i]=(long)p2;
! 558: p3=cgetg(N+1,t_COL);
! 559:
! 560: for (j=1; j<lg(y); j++)
! 561: {
! 562: p1=(GEN)y[j]; p2=ginvmod(gmul((GEN)nf[7],p1), pol);
! 563: for (i=1; i<lgef(p2)-1; i++) p3[i]=p2[i+1];
! 564: for ( ; i<=N; i++) p3[i]=zero;
! 565: p2=gmul((GEN)nf[8],p3);
! 566: if (gcmp(gnorml2(p2),gnorml2(p1))<0)
! 567: {
! 568: p1=p2; xarch[j]=lneg((GEN)xarch[j]);
! 569: }
! 570: i=N; while (i>=1 && gcmp0((GEN)p1[i])) i--;
! 571: if (gsigne((GEN)p1[i])>=0) y[j]=(long)p1;
! 572: else
! 573: {
! 574: y[j]=lneg(p1);
! 575: xarch[j]=ladd((GEN)xarch[j],vec);
! 576: }
! 577: }
! 578: p1=gmul((GEN)nf[7],y);
! 579: for (j=1; j<lg(y); j++)
! 580: if (!gcmp1(gabs(gnorm(gmodulcp((GEN)p1[j],pol)),0)))
! 581: { *pte = 0; return not_given(av,flun,LARGE); }
! 582: if (DEBUGLEVEL) msgtimer("getfu");
! 583: *ptxarch=xarch; gptr[0]=ptxarch; gptr[1]=&y;
! 584: gerepilemany(av,gptr,2); return y;
! 585: }
! 586: #undef RELAT
! 587: #undef LARGE
! 588: #undef PRECI
! 589:
! 590: GEN
! 591: buchfu(GEN bnf)
! 592: {
! 593: GEN nf,xarch,reg,res,fu,y;
! 594: long av=avma,tetpil,c,RU;
! 595:
! 596: bnf = checkbnf(bnf); nf = (GEN)bnf[7];
! 597: RU=itos(gmael(nf,2,1))+itos(gmael(nf,2,2));
! 598: res=(GEN)bnf[8];
! 599: if (lg(res)==7 && lg(res[5])==RU)
! 600: {
! 601: y=cgetg(3,t_VEC); y[1]=lcopy((GEN)res[5]);
! 602: y[2]=lcopy((GEN)res[6]); return y;
! 603: }
! 604:
! 605: xarch=(GEN)bnf[3]; reg=(GEN)res[2];
! 606: fu=getfu(nf,&xarch,reg,2,&c,gprecision(xarch));
! 607: tetpil=avma; y=cgetg(3,t_VEC);
! 608: y[1]=c?lmul((GEN)nf[7],fu):lcopy(fu); y[2]=lstoi(c);
! 609: return gerepile(av,tetpil,y);
! 610: }
! 611:
! 612: static long
! 613: factorgensimple(GEN nf,GEN ideal)
! 614: {
! 615: long i,v,av1 = avma,lo;
! 616: GEN x = dethnf_i(ideal);
! 617:
! 618: if (gcmp1(x)) { avma=av1; primfact[0]=0; return 1; }
! 619: for (lo=0, i=1; i<lg(vectbase); i++)
! 620: {
! 621: GEN p1=(GEN)vectbase[i], p=(GEN)p1[1];
! 622: if (!smodis(x,itos(p))) /* if p | x */
! 623: {
! 624: v=idealval(nf,ideal,p1);
! 625: if (v)
! 626: {
! 627: lo++; primfact[lo]=i; expoprimfact[lo]=v;
! 628: x = divii(x, gpuigs(p, v * itos((GEN)p1[4])));
! 629: if (gcmp1(x)) { avma=av1; primfact[0]=lo; return 1; }
! 630: }
! 631: }
! 632: }
! 633: avma=av1; primfact[0]=lo; return 0;
! 634: }
! 635:
! 636: static void
! 637: add_to_fact(long l, long v, long e)
! 638: {
! 639: long i,lo;
! 640: if (!e) return;
! 641: for (i=1; i<=l && primfact[i] < v; i++)/*empty*/;
! 642: if (i <= l && primfact[i] == v)
! 643: expoprimfact[i] += e;
! 644: else
! 645: {
! 646: lo = ++primfact[0];
! 647: primfact[lo] = v;
! 648: expoprimfact[lo] = e;
! 649: }
! 650: }
! 651:
! 652: /* factor x on vectbase (modulo principal ideals) */
! 653: static GEN
! 654: split_ideal(GEN nf, GEN x, GEN xar, long prec, GEN vperm)
! 655: {
! 656: GEN id,vdir,x0,y,p1;
! 657: long v1,v2,nbtest,bou,i, ru = lg(xar);
! 658: int flag = (gexpo(gcoeff(x,1,1)) < 100);
! 659:
! 660: if (flag && factorgensimple(nf,x)) return xar;
! 661:
! 662: x0 = cgetg(3,t_VEC);
! 663: x = gmul(x, lllintpartial(x));
! 664: x0[1]=(long)x; x0[2]=(long)xar;
! 665: y = ideallllred(nf,x0,NULL,prec);
! 666: if (gcmp0((GEN)y[2])) flag = !flag;
! 667: else
! 668: {
! 669: flag = 1; x=(GEN)y[1];
! 670: x = hnfmod(x, detint(x));
! 671: }
! 672: if (flag && factorgensimple(nf,x)) return (GEN)y[2];
! 673:
! 674: vdir = cgetg(ru,t_VEC);
! 675: for (i=2; i<ru; i++) vdir[i]=zero;
! 676: for (i=1; i<ru; i++)
! 677: {
! 678: vdir[i]=lstoi(10);
! 679: y = ideallllred(nf,x0,vdir,prec); x=(GEN)y[1];
! 680: if (factorgensimple(nf,x)) return (GEN)y[2];
! 681: vdir[i]=zero;
! 682: }
! 683: v1=itos((GEN)vperm[1]);
! 684: v2=itos((GEN)vperm[2]);
! 685: for(nbtest = 0;;)
! 686: {
! 687: long ex1 = mymyrand() >> randshift;
! 688: long ex2 = mymyrand() >> randshift;
! 689: id=idealpowred_prime(nf,(GEN)vectbase[v1],stoi(ex1),prec);
! 690: p1=idealpowred_prime(nf,(GEN)vectbase[v2],stoi(ex2),prec);
! 691: id = idealmulh(nf,idealmul(nf,x0,id),p1);
! 692: for (i=1; i<ru; i++) vdir[i] = lstoi(mymyrand() >> randshift);
! 693: for (bou=1; bou<ru; bou++)
! 694: {
! 695: if (bou>1)
! 696: {
! 697: for (i=1; i<ru; i++) vdir[i]=zero;
! 698: vdir[bou]=lstoi(10);
! 699: }
! 700: nbtest++;
! 701: y = ideallllred(nf,id,vdir,prec); x=(GEN)y[1];
! 702: if (DEBUGLEVEL>2)
! 703: fprintferr("nbtest = %ld, ideal = %Z\n",nbtest,(long)x);
! 704: if (factorgensimple(nf,x))
! 705: {
! 706: long l = primfact[0];
! 707: add_to_fact(l,v1,-ex1);
! 708: add_to_fact(l,v2,-ex2); return (GEN)y[2];
! 709: }
! 710: }
! 711: }
! 712: }
! 713:
! 714: static void
! 715: get_split_expo(GEN xalpha, GEN yalpha, GEN vperm)
! 716: {
! 717: long i, colW = lg(xalpha)-1;
! 718: GEN vinvperm = new_chunk(lg(vectbase));
! 719: for (i=1; i<lg(vectbase); i++) vinvperm[itos((GEN)vperm[i])]=i;
! 720: for (i=1; i<=primfact[0]; i++)
! 721: {
! 722: long k = vinvperm[primfact[i]];
! 723: long l = k - colW;
! 724: if (l <= 0) xalpha[k]=lstoi(expoprimfact[i]);
! 725: else yalpha[l]=lstoi(expoprimfact[i]);
! 726: }
! 727: }
! 728:
! 729: static GEN
! 730: isprincipalall0(GEN bnf, GEN x, long prec, long flall)
! 731: {
! 732: long i,j,colW,colB,N,R1,R2,RU,e,c;
! 733: GEN xalpha,yalpha,u2,y,p1,p2,p3,p4,xar,gen,cyc,u1inv,xc,ex;
! 734: GEN W = (GEN)bnf[1];
! 735: GEN B = (GEN)bnf[2];
! 736: GEN matunit = (GEN)bnf[3];
! 737: GEN vperm = (GEN)bnf[6];
! 738: GEN nf = (GEN)bnf[7];
! 739: GEN RES = (GEN)bnf[8];
! 740: GEN clg2 = (GEN)bnf[9];
! 741:
! 742: vectbase = (GEN)bnf[5]; /* needed by factorgensimple */
! 743:
! 744: N=lgef(nf[1])-3;
! 745: R1=itos(gmael(nf,2,1)); R2=(N-R1)>>1; RU=R1+R2;
! 746: xc = content(x); if (!gcmp1(xc)) x=gdiv(x,xc);
! 747:
! 748: colW=lg(W)-1; colB=lg(B)-1;
! 749: xar=cgetg(RU+1,t_VEC); for (i=1; i<=RU; i++) xar[i]=zero;
! 750: p1 = split_ideal(nf,x,xar,prec,vperm);
! 751: if (p1 != xar) xar = cleancol(p1,N,prec);
! 752:
! 753: xalpha=cgetg(colW+1,t_COL); for (i=1; i<=colW; i++) xalpha[i]=zero;
! 754: yalpha=cgetg(colB+1,t_COL); for (i=1; i<=colB; i++) yalpha[i]=zero;
! 755: get_split_expo(xalpha,yalpha,vperm);
! 756:
! 757: u1inv= (GEN)clg2[1]; /* 1/u1, we have u1*W*u2=diag(cyc_i) */
! 758: u2 = (GEN)clg2[2];
! 759: cyc = gmael(RES,1,2);
! 760: gen = gmael(RES,1,3);
! 761:
! 762: p1 = gauss(u1inv, gsub(xalpha, gmul(B,yalpha)));
! 763: p4 = cgetg(colW+colB+1,t_COL); c = lg(cyc)-1;
! 764: ex = cgetg(c+1,t_COL);
! 765: for (i=1; i<=c; i++)
! 766: p4[i] = (long)truedvmdii((GEN)p1[i],(GEN)cyc[i],(GEN*)(ex+i));
! 767: if (!(flall & nf_GEN)) return gcopy(ex);
! 768:
! 769: {
! 770: GEN col, baseclorig = (GEN)clg2[3];
! 771: GEN M=gmael(nf,5,1), M2,s,s2;
! 772: GEN Bc = dummycopy((GEN)bnf[4]);
! 773:
! 774: for (; i<=colW; i++) p4[i]=p1[i];
! 775: for (; i<=colW+colB; i++) p4[i]=yalpha[i-colW];
! 776: p2=cgetg(colW+1,t_MAT);
! 777: for (i=1; i<=colW; i++) p2[i]=Bc[i];
! 778: p3=gmul(p2,u2);
! 779: for (i=1; i<=colW; i++) Bc[i]=p3[i];
! 780: settyp(xar,t_COL); col=gsub(gmul(Bc,p4),xar);
! 781: p4=cgetg(c+1,t_MAT);
! 782: for (j=1; j<=c; j++)
! 783: {
! 784: GEN dmin,pmin,d;
! 785: pmin = p2 = (GEN)baseclorig[j];
! 786: dmin = dethnf((GEN)p2[1]);
! 787: p1 = idealinv(nf,p2);
! 788: p1[1]=(long)numer((GEN)p1[1]);
! 789:
! 790: d=dethnf((GEN)p1[1]);
! 791: if (mpcmp(d,dmin) < 0) { pmin=p1; dmin=d; }
! 792: p1 = ideallllred(nf,p1,NULL,prec);
! 793: d = dethnf((GEN)p1[1]);
! 794: if (mpcmp(d,dmin) < 0) pmin = p1;
! 795:
! 796: if (!gegal((GEN)pmin[1], (GEN)gen[j]))
! 797: err(bugparier,"isprincipal(1)");
! 798: p4[j]=lneg((GEN)pmin[2]); settyp(p4[j],t_COL);
! 799: }
! 800: if (c) col = gadd(col,gmul(p4,ex));
! 801: col = cleancol(col,N,prec);
! 802:
! 803: if (RU > 1)
! 804: {
! 805: s=gzero; p4=cgetg(RU+1,t_MAT);
! 806: for (j=1; j<RU; j++)
! 807: {
! 808: p2=cgetg(RU+1,t_COL); p4[j]=(long)p2;
! 809: p1=gzero;
! 810: for (i=1; i<RU; i++)
! 811: {
! 812: p2[i] = lreal(gcoeff(matunit,i,j));
! 813: p1 = gadd(p1, gsqr((GEN)p2[i]));
! 814: }
! 815: p2[RU]=zero; if (gcmp(p1,s)>0) s=p1;
! 816: }
! 817: p2=cgetg(RU+1,t_COL); p4[RU]=(long)p2;
! 818: for (i=1; i<RU; i++) p2[i]=lreal((GEN)col[i]);
! 819: s=gsqrt(gmul2n(s,RU+1),prec);
! 820: if (gcmpgs(s,100000000)<0) s=stoi(100000000);
! 821: p2[RU]=(long)s;
! 822:
! 823: p4=(GEN)lll(p4,prec)[RU];
! 824: if (signe(p4[RU]) < 0) p4 = gneg_i(p4);
! 825: if (!gcmp1((GEN)p4[RU])) err(bugparier,"isprincipal(2)");
! 826: setlg(p4,RU);
! 827: col = gadd(col, gmul(matunit,p4));
! 828: }
! 829:
! 830: s2 = gun;
! 831: for (j=1; j<=c; j++)
! 832: if (signe(ex[j]))
! 833: s2 = mulii(s2, powgi(dethnf_i((GEN)gen[j]), (GEN)ex[j]));
! 834: s = gdivgs(glog(gdiv(dethnf_i(x),s2),prec), N);
! 835: p4 = cgetg(N+1,t_COL);
! 836: for (i=1; i<=R1; i++) p4[i]=lexp(gadd(s,(GEN)col[i]),prec);
! 837: for ( ; i<=RU; i++)
! 838: {
! 839: p4[i]=lexp(gadd(s,gmul2n((GEN)col[i],-1)),prec); ;
! 840: p4[i+R2]=lconj((GEN)p4[i]);
! 841: }
! 842: M2=cgetg(N+1,t_MAT);
! 843: for (j=1; j<=N; j++)
! 844: {
! 845: p1=cgetg(N+1,t_COL); M2[j]=(long)p1;
! 846: for (i=1; i<=R1; i++) p1[i]=coeff(M,i,j);
! 847: for ( ; i<=RU; i++)
! 848: {
! 849: p1[i]=coeff(M,i,j);
! 850: p1[i+R2]=lconj((GEN)p1[i]);
! 851: }
! 852: }
! 853: p1 = gdiv(grndtoi(gmul(s2,greal(gauss(M2,p4))),&e), s2);
! 854: if (e < -5)
! 855: {
! 856: p3 = p1;
! 857: if (!c) p3=idealhermite(nf,p3);
! 858: else
! 859: for (j=1; j<=c; j++)
! 860: p3 = idealmul(nf,p3,idealpow(nf,(GEN)gen[j],(GEN)ex[j]));
! 861: if (!gegal(x,p3)) e=0;
! 862: }
! 863: y=cgetg(4,t_VEC); y[1]=lcopy(ex);
! 864: if (e < -5) { y[2]=lmul(xc,p1); y[3]=lstoi(-e); }
! 865: else
! 866: {
! 867: if (flall & nf_FORCE)
! 868: {
! 869: if (DEBUGLEVEL)
! 870: err(warner,"precision too low for generators, e = %ld",e);
! 871: prec += (e >> TWOPOTBITS_IN_LONG) + (MEDDEFAULTPREC-2);
! 872: return stoi(prec);
! 873: }
! 874: err(warner,"insufficient precision for generators, not given");
! 875: y[2]=lgetg(1,t_COL); y[3]=zero;
! 876: }
! 877: }
! 878: return y;
! 879: }
! 880:
! 881: static GEN
! 882: triv_gen(GEN nf, GEN x, long c, long flag)
! 883: {
! 884: GEN y;
! 885: if (!(flag & nf_GEN)) return cgetg(1,t_COL);
! 886: y = cgetg(4,t_VEC);
! 887: y[1] = (long)zerocol(c);
! 888: y[2] = (long)algtobasis(nf,x);
! 889: y[3] = lstoi(BIGINT); return y;
! 890: }
! 891:
! 892: GEN
! 893: isprincipalall(GEN bnf,GEN x,long flag)
! 894: {
! 895: long av = avma,c,pr, tx = typ(x);
! 896: GEN nf;
! 897:
! 898: bnf = checkbnf(bnf); nf = (GEN)bnf[7];
! 899: if (tx == t_POLMOD)
! 900: {
! 901: if (!gegal((GEN)x[1],(GEN)nf[1]))
! 902: err(talker,"not the same number field in isprincipal");
! 903: x = (GEN)x[2]; tx = t_POL;
! 904: }
! 905: if (tx == t_POL)
! 906: {
! 907: if (gcmp0(x)) err(talker,"zero ideal in isprincipal");
! 908: return triv_gen(nf, x, lg(mael3(bnf,8,1,2))-1, flag);
! 909: }
! 910: x = idealhermite(nf,x);
! 911: if (lg(x)==1) err(talker,"zero ideal in isprincipal");
! 912: if (lgef(nf[1])==4)
! 913: return gerepileupto(av, triv_gen(nf, gcoeff(x,1,1), 0, flag));
! 914:
! 915: pr = gprecision(gmael(bnf,4,1)); /* precision of unit matrix */
! 916: c = getrand();
! 917: for (;;)
! 918: {
! 919: long av1 = avma;
! 920: GEN y = isprincipalall0(bnf,x,pr,flag);
! 921: if (typ(y) != t_INT) return gerepileupto(av,y);
! 922:
! 923: pr = itos(y); avma = av1;
! 924: if (DEBUGLEVEL) err(warnprec,"isprincipalall0",pr);
! 925: bnf = bnfnewprec(bnf,pr); setrand(c);
! 926: }
! 927: }
! 928:
! 929: GEN
! 930: isprincipal(GEN bnf,GEN x)
! 931: {
! 932: return isprincipalall(bnf,x,nf_REGULAR);
! 933: }
! 934:
! 935: GEN
! 936: isprincipalgen(GEN bnf,GEN x)
! 937: {
! 938: return isprincipalall(bnf,x,nf_GEN);
! 939: }
! 940:
! 941: GEN
! 942: isprincipalforce(GEN bnf,GEN x)
! 943: {
! 944: return isprincipalall(bnf,x,nf_FORCE);
! 945: }
! 946:
! 947: GEN
! 948: isprincipalgenforce(GEN bnf,GEN x)
! 949: {
! 950: return isprincipalall(bnf,x,nf_GEN | nf_FORCE);
! 951: }
! 952:
! 953: GEN
! 954: isunit(GEN bnf,GEN x)
! 955: {
! 956: long av=avma,tetpil,tx = typ(x),i,R1,RU,n;
! 957: GEN p1,logunit,y,ex,nf,z,pi2_sur_w,gn,emb;
! 958:
! 959: bnf = checkbnf(bnf); nf=(GEN)bnf[7];
! 960: logunit=(GEN)bnf[3]; RU=lg(logunit);
! 961: p1 = gmael(bnf,8,4); /* roots of 1 */
! 962: gn = (GEN)p1[1]; n = itos(gn);
! 963: z = (GEN)p1[2];
! 964: switch(tx)
! 965: {
! 966: case t_INT: case t_FRAC: case t_FRACN:
! 967: if (!gcmp1(x) && !gcmp_1(x)) return cgetg(1,t_COL);
! 968: y = zerocol(RU); i = (gsigne(x) > 0)? 0: n>>1;
! 969: y[RU] = (long)gmodulss(i, n); return y;
! 970:
! 971: case t_POLMOD:
! 972: if (!gegal((GEN)nf[1],(GEN)x[1]))
! 973: err(talker,"not the same number field in isunit");
! 974: x = (GEN)x[2]; /* fall through */
! 975: case t_POL:
! 976: p1 = x; x = algtobasis(bnf,x); break;
! 977:
! 978: case t_COL:
! 979: if (lgef(nf[1])-2 == lg(x)) { p1 = basistoalg(nf,x); break; }
! 980:
! 981: default:
! 982: err(talker,"not an algebraic number in isunit");
! 983: }
! 984: if (!gcmp1(denom(x))) { avma = av; return cgetg(1,t_COL); }
! 985: if (typ(p1) != t_POLMOD) p1 = gmodulcp(p1,(GEN)nf[1]);
! 986: p1 = gnorm(p1);
! 987: if (!is_pm1(p1)) { avma = av; return cgetg(1,t_COL); }
! 988:
! 989: R1 = itos(gmael(nf,2,1)); p1 = cgetg(RU+1,t_COL);
! 990: for (i=1; i<=R1; i++) p1[i] = un;
! 991: for ( ; i<=RU; i++) p1[i] = deux;
! 992: logunit = concatsp(logunit,p1);
! 993: /* ex = fundamental units exponents */
! 994: ex = ground(gauss(greal(logunit), get_arch_real(nf,x,&emb, MEDDEFAULTPREC)));
! 995: if (!gcmp0((GEN)ex[RU]))
! 996: err(talker,"insufficient precision in isunit");
! 997:
! 998: setlg(ex, RU);
! 999: setlg(p1, RU); settyp(p1, t_VEC);
! 1000: for (i=1; i<RU; i++) p1[i] = coeff(logunit, 1, i);
! 1001: p1 = gneg(gimag(gmul(p1,ex))); if (!R1) p1 = gmul2n(p1, -1);
! 1002: p1 = gadd(garg((GEN)emb[1],DEFAULTPREC), p1);
! 1003: /* p1 = arg(the missing root of 1) */
! 1004:
! 1005: pi2_sur_w = divrs(mppi(DEFAULTPREC), n>>1);
! 1006: p1 = ground(gdiv(p1, pi2_sur_w));
! 1007: if (n > 2)
! 1008: {
! 1009: GEN ro = gmael(nf,6,1);
! 1010: GEN p2 = ground(gdiv(garg(poleval(z,ro), DEFAULTPREC), pi2_sur_w));
! 1011: p1 = mulii(p1, mpinvmod(p2, gn));
! 1012: }
! 1013:
! 1014: tetpil = avma; y = cgetg(RU+1,t_COL);
! 1015: for (i=1; i<RU; i++) y[i] = lcopy((GEN)ex[i]);
! 1016: y[RU] = lmodulcp(p1, gn); return gerepile(av,tetpil,y);
! 1017: }
! 1018:
! 1019: GEN
! 1020: signunits(GEN bnf)
! 1021: {
! 1022: long av,i,j,R1,RU,mun;
! 1023: GEN matunit,y,p1,p2,nf,pi;
! 1024:
! 1025: bnf = checkbnf(bnf); nf = (GEN)bnf[7];
! 1026: matunit = (GEN)bnf[3]; RU = lg(matunit);
! 1027: R1=itos(gmael(nf,2,1)); pi=mppi(MEDDEFAULTPREC);
! 1028: y=cgetg(RU,t_MAT); mun = lnegi(gun);
! 1029: for (j=1; j<RU; j++)
! 1030: {
! 1031: p1=cgetg(R1+1,t_COL); y[j]=(long)p1; av=avma;
! 1032: for (i=1; i<=R1; i++)
! 1033: {
! 1034: p2 = ground(gdiv(gimag(gcoeff(matunit,i,j)),pi));
! 1035: p1[i] = mpodd(p2)? mun: un;
! 1036: }
! 1037: avma=av;
! 1038: }
! 1039: return y;
! 1040: }
! 1041:
! 1042: static GEN
! 1043: quad_form(GEN *cbase,GEN ideal,GEN T2vec,GEN prvec)
! 1044: {
! 1045: long i;
! 1046: for (i=1; i<lg(T2vec); i++)
! 1047: {
! 1048: long prec = prvec[i];
! 1049: GEN p1,T2 = (GEN)T2vec[i];
! 1050:
! 1051: p1 = qf_base_change(T2,gmul(ideal,realun(prec)), 0);
! 1052: if ((*cbase=lllgramintern(p1,100,1,prec)) == NULL)
! 1053: {
! 1054: if (DEBUGLEVEL) err(warner, "prec too low in quad_form(1): %ld",prec);
! 1055: continue;
! 1056: }
! 1057: if (DEBUGLEVEL>6)
! 1058: {
! 1059: fprintferr(" input matrix for lllgram: %Z\n",(long)p1);
! 1060: fprintferr(" lllgram output (prec = %ld): %Z\n",prec,(long)*cbase);
! 1061: }
! 1062: p1 = sqred1intern(qf_base_change(p1,*cbase,1),1);
! 1063: if (p1) return p1;
! 1064: if (DEBUGLEVEL) err(warner, "prec too low in quad_form(2): %ld",prec);
! 1065: }
! 1066: return NULL;
! 1067: }
! 1068:
! 1069: /* y is a vector of LONG, of length ly. x is a hx x ly matrix */
! 1070: GEN
! 1071: gmul_mat_smallvec(GEN x, GEN y, long hx, long ly)
! 1072: {
! 1073: GEN z=cgetg(hx+1,t_COL), p1,p2;
! 1074: long i,j,av,tetpil;
! 1075:
! 1076: for (i=1; i<=hx; i++)
! 1077: {
! 1078: p1=gzero; av=avma;
! 1079: for (j=1; j<=ly; j++)
! 1080: {
! 1081: p2=gmulgs(gcoeff(x,i,j),y[j]);
! 1082: tetpil=avma; p1=gadd(p1,p2);
! 1083: }
! 1084: z[i]=lpile(av,tetpil,p1);
! 1085: }
! 1086: return z;
! 1087: }
! 1088:
! 1089: static double
! 1090: get_minkovski(long prec, long N, long R1, GEN D, GEN gborne)
! 1091: {
! 1092: GEN p1,p2, pi = mppi(prec);
! 1093: double bound;
! 1094:
! 1095: p1 = gsqrt(gmulsg(N,gmul2n(pi,1)),prec);
! 1096: p1 = gdiv(p1, gexp(stoi(N),prec));
! 1097: p1 = gmulsg(N, gpui(p1, dbltor(2./(double)N),prec));
! 1098: p2 = gpui(gdivsg(4,pi), gdivgs(stoi(N-R1),N),prec);
! 1099: p1 = gmul(p1,p2);
! 1100: bound = gtodouble(gmul(p1, gpui(absi(D), dbltor(1./(double)N),prec)));
! 1101: bound = bound*gtodouble(gborne);
! 1102: if (DEBUGLEVEL)
! 1103: {
! 1104: fprintferr("Bound for norms = %.0f\n",bound); flusherr();
! 1105: }
! 1106: return bound;
! 1107: }
! 1108:
! 1109: static void
! 1110: wr_rel(long *col)
! 1111: {
! 1112: long i;
! 1113: fprintferr("\nrel = ");
! 1114: for (i=1; i<=KC; i++)
! 1115: if (col[i]) fprintferr("%ld^%ld ",i,col[i]);
! 1116: fprintferr("\n");
! 1117: }
! 1118:
! 1119: static long
! 1120: small_norm_for_buchall(long t,long **mat,GEN matarch,long nbrel,long LIMC,
! 1121: long PRECREG,GEN nf,GEN gborne,long nbrelpid,GEN invp,
! 1122: long *L)
! 1123: {
! 1124: long av=avma,av1,av2,av3,tetpil,limpile, *x,i,j,k,noideal,ran,keep_old_invp;
! 1125: long nbsmallnorm,nbsmallfact,R1,RU, N = lgef(nf[1])-3;
! 1126: double *y,*zz,**qq,*vv, MINKOVSKI_BOUND,IDEAL_BOUND,normideal,eps;
! 1127: GEN D,V,alpha,T2,ideal,rrr,cbase,T2vec,prvec;
! 1128:
! 1129: if (gsigne(gborne)<=0) return t;
! 1130: if (DEBUGLEVEL)
! 1131: {
! 1132: fprintferr("\n#### Looking for %ld relations (small norms)\n",nbrel);
! 1133: nbsmallnorm = nbsmallfact = 0; flusherr();
! 1134: }
! 1135: R1=itos(gmael(nf,2,1)); RU = R1 + itos(gmael(nf,2,2));
! 1136: D=(GEN)nf[3]; j=N+1; T2=gmael(nf,5,3);
! 1137: prvec=cgetg(3,t_VECSMALL);
! 1138: prvec[1]=(PRECREG>BIGDEFAULTPREC)? (PRECREG>>1)+1: DEFAULTPREC;
! 1139: prvec[2]=PRECREG;
! 1140: T2vec=cgetg(3,t_VEC);
! 1141: T2vec[1]=(long)gprec_w(T2,prvec[1]);
! 1142: T2vec[2]=(long)T2;
! 1143: x=(long*)gpmalloc(j*sizeof(long));
! 1144: y=(double*)gpmalloc(j*sizeof(double));
! 1145: zz=(double*)gpmalloc(j*sizeof(double));
! 1146: vv=(double*)gpmalloc(j*sizeof(double));
! 1147: qq=(double**)gpmalloc(j*sizeof(double*));
! 1148: for (k=1; k<=N; k++) qq[k]=(double*)gpmalloc(j*sizeof(double));
! 1149:
! 1150: V=new_chunk(KC+1); av1=avma;
! 1151: MINKOVSKI_BOUND = get_minkovski(DEFAULTPREC,N,R1,D,gborne);
! 1152: eps = 0.000001;
! 1153: for (noideal=1; noideal<=KC; noideal++)
! 1154: {
! 1155: long flbreak = 0, nbrelideal=0;
! 1156:
! 1157: ideal=(GEN)vectbase[KC+1-noideal];
! 1158: if (DEBUGLEVEL>1)
! 1159: {
! 1160: fprintferr("\n*** Ideal no %ld: S = %ld, ",noideal,t);
! 1161: fprintferr("prime = %ld, ",itos((GEN)ideal[1]));
! 1162: fprintferr("ideal = "); outerr(ideal);
! 1163: }
! 1164: normideal = gtodouble(powgi((GEN)ideal[1],(GEN)ideal[4]));
! 1165: IDEAL_BOUND = MINKOVSKI_BOUND*pow(normideal,2./(double)N);
! 1166: ideal = prime_to_ideal(nf,ideal);
! 1167: if ((rrr = quad_form(&cbase,ideal,T2vec,prvec)) == NULL)
! 1168: return -1; /* precision problem */
! 1169:
! 1170: for (k=1; k<=N; k++)
! 1171: {
! 1172: vv[k]=gtodouble(gcoeff(rrr,k,k));
! 1173: for (j=1; j<k; j++) qq[j][k]=gtodouble(gcoeff(rrr,j,k));
! 1174: if (DEBUGLEVEL>3) fprintferr("vv[%ld]=%.0f ",k,vv[k]);
! 1175: }
! 1176: if (DEBUGLEVEL>1)
! 1177: {
! 1178: if (DEBUGLEVEL>3) fprintferr("\n");
! 1179: fprintferr("IDEAL_BOUND = %.0f\n",IDEAL_BOUND); flusherr();
! 1180: }
! 1181: IDEAL_BOUND += eps; av2=avma; limpile = stack_lim(av2,1);
! 1182: x[0]=k=N; y[N]=zz[N]=0; x[N]= (long) sqrt(IDEAL_BOUND/vv[N]);
! 1183: for(;; x[1]--)
! 1184: {
! 1185: for(;;) /* looking for primitive element of small norm */
! 1186: {
! 1187: double p;
! 1188:
! 1189: if (k>1)
! 1190: {
! 1191: /* We need to define `l' for NeXTgcc 2.5.8 */
! 1192: long l=k-1;
! 1193: zz[l]=0;
! 1194: for (j=k; j<=N; j++) zz[l] += qq[l][j]*x[j];
! 1195: p=x[k]+zz[k];
! 1196: y[l]=y[k]+p*p*vv[k];
! 1197: x[l]=(long) floor(sqrt((IDEAL_BOUND-y[l])/vv[l])-zz[l]);
! 1198: k=l;
! 1199: }
! 1200: for(;;)
! 1201: {
! 1202: p=x[k]+zz[k];
! 1203: if (y[k] + vv[k]*p*p <= IDEAL_BOUND) break;
! 1204: k++; x[k]--;
! 1205: }
! 1206: if (k==1) /* element complete */
! 1207: {
! 1208: if (!x[1] && y[1]<=eps) { flbreak=1; break; }
! 1209: if (ccontent(x)==1) /* primitive */
! 1210: {
! 1211: if (DEBUGLEVEL>4)
! 1212: {
! 1213: fprintferr("** Found one element: AVMA = %ld\n",avma);
! 1214: flusherr();
! 1215: }
! 1216: av3=avma; alpha=gmul(ideal,gmul_mat_smallvec(cbase,x,N,N));
! 1217: j=N; while (j>=2 && !signe(alpha[j])) --j;
! 1218: if (j!=1)
! 1219: {
! 1220: if (DEBUGLEVEL)
! 1221: {
! 1222: if (DEBUGLEVEL>1)
! 1223: {
! 1224: fprintferr(".");
! 1225: if (DEBUGLEVEL>7)
! 1226: {
! 1227: GEN bq = gzero, cq;
! 1228: outerr(gdiv(idealnorm(nf,alpha), idealnorm(nf,ideal)));
! 1229: for (j=1; j<=N; j++)
! 1230: {
! 1231: cq=gzero;
! 1232: for (i=j+1; i<=N; i++)
! 1233: cq=gadd(cq,gmulgs(gcoeff(rrr,j,i),x[i]));
! 1234: cq=gaddgs(cq,x[j]);
! 1235: bq=gadd(bq,gmul(gsqr(cq),gcoeff(rrr,j,j)));
! 1236: }
! 1237: outerr(bq);
! 1238: }
! 1239: }
! 1240: nbsmallnorm++; flusherr();
! 1241: }
! 1242: if (factorisealpha(nf,alpha,KCZ,LIMC)) break; /* can factor it */
! 1243: }
! 1244: avma=av3;
! 1245: }
! 1246: x[1]--;
! 1247: }
! 1248: }
! 1249: if (flbreak) { flbreak=0; break; }
! 1250:
! 1251: if (t && t<KC) /* matrix empty or maximal rank */
! 1252: {
! 1253: for (i=1; i<=KC; i++) V[i]=0;
! 1254: for (i=1; i<=primfact[0]; i++) V[primfact[i]] = expoprimfact[i];
! 1255: keep_old_invp=0; ran=addcolumntomatrix(V,KC,t,&invp,L);
! 1256: }
! 1257: else { keep_old_invp=1; ran=t+1; }
! 1258: if (ran==t)
! 1259: { if (DEBUGLEVEL>1) { fprintferr("*"); flusherr(); } }
! 1260: else
! 1261: {
! 1262: GEN p1, *newcol; /* record the new relation */
! 1263: long *colt;
! 1264:
! 1265: t=ran; newcol=(GEN*)matarch[t]; colt=mat[t];
! 1266: colt[0] = primfact[1]; /* for already_found_relation */
! 1267: for (j=1; j<=primfact[0]; j++)
! 1268: colt[primfact[j]] = expoprimfact[j];
! 1269:
! 1270: p1=gmul(gmael(nf,5,1),alpha);
! 1271: for (j=1; j<=R1; j++)
! 1272: gaffect(glog((GEN)p1[j],PRECREG), newcol[j]);
! 1273: for ( ; j<=RU; j++)
! 1274: gaffect(gmul2n(glog((GEN)p1[j],PRECREG),1), newcol[j]);
! 1275:
! 1276: if (DEBUGLEVEL)
! 1277: {
! 1278: if (DEBUGLEVEL==1) fprintferr("%4ld",t);
! 1279: else
! 1280: {
! 1281: fprintferr("t = %ld. ",t);
! 1282: if (DEBUGLEVEL>2) outerr(alpha);
! 1283: wr_rel(colt);
! 1284: }
! 1285: flusherr(); nbsmallfact++;
! 1286: }
! 1287: if (t>=nbrel) { flbreak=1; break; }
! 1288: nbrelideal++; if (nbrelideal==nbrelpid) break;
! 1289: }
! 1290: if (keep_old_invp)
! 1291: avma=av3;
! 1292: else if (low_stack(limpile, stack_lim(av2,1)))
! 1293: {
! 1294: if(DEBUGMEM>1) err(warnmem,"small_norm");
! 1295: tetpil=avma; invp=gerepile(av2,tetpil,gcopy(invp));
! 1296: }
! 1297: if (DEBUGLEVEL>4)
! 1298: { fprintferr("** Found one element: AVMA = %ld\n",avma); flusherr(); }
! 1299: }
! 1300: if (flbreak) break;
! 1301: tetpil=avma; invp=gerepile(av1,tetpil,gcopy(invp));
! 1302: if (DEBUGLEVEL>1) msgtimer("for this ideal");
! 1303: }
! 1304: if (DEBUGLEVEL)
! 1305: {
! 1306: fprintferr("\n");
! 1307: msgtimer("small norm relations");
! 1308: if (DEBUGLEVEL>1)
! 1309: {
! 1310: GEN p1,tmp=cgetg(t+1,t_MAT);
! 1311:
! 1312: fprintferr("Elements of small norm gave %ld relations.\n",t);
! 1313: fprintferr("Computing rank :"); flusherr();
! 1314: for(j=1;j<=t;j++)
! 1315: {
! 1316: p1=cgetg(KC+1,t_COL); tmp[j]=(long)p1;
! 1317: for(i=1;i<=KC;i++) p1[i]=lstoi(mat[j][i]);
! 1318: }
! 1319: tmp = (GEN)indexrank(tmp)[2]; k=lg(tmp)-1;
! 1320: fprintferr("rank = %ld; independent columns:\n",k);
! 1321: for (i=1; i<=k; i++) fprintferr("%4ld",itos((GEN)tmp[i]));
! 1322: fprintferr("\n");
! 1323: }
! 1324: if(nbsmallnorm)
! 1325: fprintferr("\nnb. fact./nb. small norm = %ld/%ld = %f\n",
! 1326: nbsmallfact,nbsmallnorm,((double)nbsmallfact)/nbsmallnorm);
! 1327: else
! 1328: fprintferr("\nnb. small norm = 0\n");
! 1329: }
! 1330: for (j=1; j<=N; j++) free(qq[j]);
! 1331: free(qq); free(x); free(y); free(zz); free(vv);
! 1332: avma=av; return t;
! 1333: }
! 1334:
! 1335: /* I assumed to be integral HNF */
! 1336: static GEN
! 1337: ideallllredpart1(GEN nf, GEN I, GEN matt2, long N, long PRECREGINT)
! 1338: {
! 1339: GEN y,m,idealpro;
! 1340:
! 1341: if (!gcmp1(gcoeff(I,N,N))) { y=content(I); if (!gcmp1(y)) I=gdiv(I,y); }
! 1342: y = lllgramintern(qf_base_change(matt2,I,1),100,1,PRECREGINT+1);
! 1343: if (!y) return NULL;
! 1344:
! 1345: /* I, m, y integral */
! 1346: m = gmul(I,(GEN)y[1]);
! 1347: if (isnfscalar(m)) m = gmul(I,(GEN)y[2]);
! 1348:
! 1349: idealpro = cgetg(4,t_VEC);
! 1350: idealpro[1] = (long)I;
! 1351: idealpro[2] = (long)m; /* elt of small (weighted) T2 norm in I */
! 1352: idealpro[3] = labsi( subres(gmul((GEN)nf[7],m), (GEN)nf[1]) ); /* |Nm| */
! 1353: if (DEBUGLEVEL>5) fprintferr("\nidealpro = %Z\n");
! 1354: return idealpro;
! 1355: }
! 1356:
! 1357: static void
! 1358: ideallllredpart2(GEN colarch, GEN nf, GEN arch, GEN gamma, long prec)
! 1359: {
! 1360: GEN v = get_arch(nf,gamma,prec);
! 1361: long i;
! 1362: for (i=lg(v)-1; i; i--)
! 1363: gaffect(gadd((GEN)arch[i],gneg((GEN)v[i])), (GEN)colarch[i]);
! 1364: }
! 1365:
! 1366: static void
! 1367: dbg_newrel(long jideal, long jdir, long phase, long cmptglob, long *col,
! 1368: GEN colarch, long lim)
! 1369: {
! 1370: fprintferr("\n++++ cmptglob = %ld: new relation (need %ld)", cmptglob, lim);
! 1371: wr_rel(col);
! 1372: if (DEBUGLEVEL>3)
! 1373: {
! 1374: fprintferr("(jideal=%ld,jdir=%ld,phase=%ld)", jideal,jdir,phase);
! 1375: msgtimer("for this relation");
! 1376: }
! 1377: if (DEBUGLEVEL>6) fprintferr("archimedian part = %Z\n",colarch);
! 1378: flusherr() ;
! 1379: }
! 1380:
! 1381: static void
! 1382: dbg_cancelrel(long i,long jideal,long jdir,long phase, long *col)
! 1383: {
! 1384: fprintferr("rel. cancelled. phase %ld: %ld ",phase,i);
! 1385: if (DEBUGLEVEL>3) fprintferr("(jideal=%ld,jdir=%ld)",jideal,jdir);
! 1386: wr_rel(col); flusherr();
! 1387: }
! 1388:
! 1389: static void
! 1390: dbg_outrel(long phase,long cmptglob, GEN vperm,long **ma,GEN maarch)
! 1391: {
! 1392: long av,i,j;
! 1393: GEN p1,p2;
! 1394:
! 1395: if (phase == 0)
! 1396: {
! 1397: av=avma; p2=cgetg(cmptglob+1,t_MAT);
! 1398: for (j=1; j<=cmptglob; j++)
! 1399: {
! 1400: p1=cgetg(KC+1,t_COL); p2[j]=(long)p1;
! 1401: for (i=1; i<=KC; i++) p1[i]=lstoi(ma[j][i]);
! 1402: }
! 1403: fprintferr("\nRank = %ld, time = %ld\n",rank(p2),timer2());
! 1404: if (DEBUGLEVEL>3)
! 1405: {
! 1406: fprintferr("relations = \n");
! 1407: for (j=1; j <= cmptglob; j++) wr_rel(ma[j]);
! 1408: fprintferr("\nmatarch = %Z\n",maarch);
! 1409: }
! 1410: avma=av;
! 1411: }
! 1412: else if (DEBUGLEVEL>6)
! 1413: {
! 1414: fprintferr("before hnfadd:\nvectbase[vperm[]] = \n");
! 1415: fprintferr("[");
! 1416: for (i=1; i<=KC; i++)
! 1417: {
! 1418: bruterr((GEN)vectbase[vperm[i]],'g',-1);
! 1419: if (i<KC) fprintferr(",");
! 1420: }
! 1421: fprintferr("]~\n");
! 1422: }
! 1423: flusherr();
! 1424: }
! 1425:
! 1426: /* check if we already have a column mat[l] equal to mat[s] */
! 1427: static long
! 1428: already_found_relation(long **mat,long s)
! 1429: {
! 1430: long l,bs,cl,*coll,*cols = mat[s];
! 1431:
! 1432: bs=1; while (bs<=KC && !cols[bs]) bs++;
! 1433: if (bs>KC) return s; /* zero relation */
! 1434:
! 1435: #if 0
! 1436: /* Could check for colinearity and replace by gcd. Useless in practice */
! 1437: cs=cols[bs];
! 1438: for (l=s-1; l; l--)
! 1439: {
! 1440: coll=mat[l]; cl=coll[0]; /* = index of first non zero elt in coll */
! 1441: if (cl==bs)
! 1442: {
! 1443: long b=bs;
! 1444: cl=coll[cl];
! 1445: do b++; while (b<=KC && cl*cols[b] == cs*coll[b]);
! 1446: if (b>KC) return l;
! 1447: }
! 1448: }
! 1449: #endif
! 1450: for (l=s-1; l; l--)
! 1451: {
! 1452: coll=mat[l]; cl=coll[0]; /* = index of first non zero elt in coll */
! 1453: if (cl==bs)
! 1454: {
! 1455: long b=bs;
! 1456: do b++; while (b<=KC && cols[b] == coll[b]);
! 1457: if (b>KC) return l;
! 1458: }
! 1459: }
! 1460: cols[0]=bs; return 0;
! 1461: }
! 1462:
! 1463: /* if phase != 1 re-initialize static variables. If <0 return immediately */
! 1464: static long
! 1465: random_relation(long phase,long cmptglob,long lim,long LIMC,long N,long RU,
! 1466: long PRECREG,long PRECREGINT,GEN nf,GEN subfb,GEN lmatt2,
! 1467: long **ma,GEN maarch,long *ex,GEN list_jideal)
! 1468: {
! 1469: static long jideal, jdir;
! 1470: long i,av,av1,cptzer,nbmatt2,lgsub, jlist = 1, *col;
! 1471: GEN colarch,ideal,idealpro,P;
! 1472:
! 1473: if (phase != 1) { jideal=jdir=1; if (phase<0) return 0; }
! 1474: nbmatt2 = lg(lmatt2)-1;
! 1475: lgsub = lg(subfb);
! 1476: cptzer = 0;
! 1477: if (DEBUGLEVEL && list_jideal)
! 1478: fprintferr("looking hard for %Z\n",list_jideal);
! 1479: for (av = avma;;)
! 1480: {
! 1481: if (list_jideal && jlist < lg(list_jideal) && jdir <= nbmatt2)
! 1482: jideal = list_jideal[jlist++];
! 1483: if (!list_jideal || jdir <= nbmatt2)
! 1484: {
! 1485: avma = av;
! 1486: P = prime_to_ideal(nf, (GEN)vectbase[jideal]);
! 1487: }
! 1488: ideal = P;
! 1489: do {
! 1490: for (i=1; i<lgsub; i++)
! 1491: {
! 1492: ex[i] = mymyrand()>>randshift;
! 1493: if (ex[i])
! 1494: ideal = idealmulh(nf,ideal, gmael(powsubfb,i,ex[i]));
! 1495: }
! 1496: }
! 1497: while (typ(ideal)==t_MAT); /* If ex = 0, try another */
! 1498:
! 1499: if (phase != 1) jdir = 1; else phase = 2;
! 1500: for (av1 = avma; jdir <= nbmatt2; jdir++, avma = av1)
! 1501: { /* reduce along various directions */
! 1502: if (DEBUGLEVEL>2)
! 1503: fprintferr("phase=%ld,jideal=%ld,jdir=%ld,rand=%ld\n",
! 1504: phase,jideal,jdir,getrand());
! 1505: idealpro = ideallllredpart1(nf,(GEN)ideal[1], (GEN)lmatt2[jdir],
! 1506: N, PRECREGINT);
! 1507: if (!idealpro) return -2;
! 1508: if (!factorisegen(nf,idealpro,KCZ,LIMC))
! 1509: {
! 1510: if (DEBUGLEVEL>1) { fprintferr("."); flusherr(); }
! 1511: continue;
! 1512: }
! 1513: /* can factor ideal, record relation */
! 1514: col = ma[++cmptglob];
! 1515: for (i=1; i<lgsub; i++) col[subfb[i]] = -ex[i];
! 1516: for (i=1; i<=primfact[0]; i++) col[primfact[i]] += expoprimfact[i];
! 1517: col[jideal]--;
! 1518: i = already_found_relation(ma,cmptglob);
! 1519: if (i)
! 1520: { /* already known. Forget it */
! 1521: if (DEBUGLEVEL>1) dbg_cancelrel(i,jideal,jdir,phase,col);
! 1522: cmptglob--; for (i=1; i<=KC; i++) col[i]=0;
! 1523: if (++cptzer > MAXRELSUP)
! 1524: {
! 1525: if (list_jideal) { cptzer -= 10; break; }
! 1526: return -1;
! 1527: }
! 1528: continue;
! 1529: }
! 1530:
! 1531: /* Record archimedian part */
! 1532: cptzer=0; colarch = (GEN)maarch[cmptglob];
! 1533: ideallllredpart2(colarch,nf,(GEN)ideal[2],(GEN)idealpro[2],PRECREG);
! 1534: if (DEBUGLEVEL)
! 1535: dbg_newrel(jideal,jdir,phase,cmptglob,col,colarch,lim);
! 1536:
! 1537: /* Need more, try next P */
! 1538: if (cmptglob < lim) break;
! 1539:
! 1540: /* We have found enough. Return */
! 1541: if (phase)
! 1542: {
! 1543: jdir = 1;
! 1544: if (jideal == KC) jideal=1; else jideal++;
! 1545: }
! 1546: else if (DEBUGLEVEL>2)
! 1547: fprintferr("Upon exit: jideal=%ld,jdir=%ld\n",jideal,jdir);
! 1548: avma = av; return cmptglob;
! 1549: }
! 1550: if (!list_jideal)
! 1551: {
! 1552: if (jideal == KC) jideal=1; else jideal++;
! 1553: }
! 1554: }
! 1555: }
! 1556:
! 1557: static long
! 1558: be_honest(GEN nf,GEN subfb,long RU,long PRECREGINT)
! 1559: {
! 1560: long av,ex,i,j,k,iz,nbtest, N = lgef(nf[1])-3, lgsub = lg(subfb);
! 1561: GEN exu=new_chunk(RU+1), MCtw = cgetg(RU+1,t_MAT);
! 1562: GEN p1,p2,ideal,idealpro, MC = gmael(nf,5,2), M = gmael(nf,5,1);
! 1563:
! 1564: if (DEBUGLEVEL)
! 1565: {
! 1566: fprintferr("Be honest for primes from %ld to %ld\n",
! 1567: factorbase[KCZ+1],factorbase[KCZ2]);
! 1568: flusherr();
! 1569: }
! 1570: av=avma;
! 1571: for (iz=KCZ+1; iz<=KCZ2; iz++)
! 1572: {
! 1573: p1=idealbase[numfactorbase[factorbase[iz]]];
! 1574: if (DEBUGLEVEL>1) fprintferr("%ld ", factorbase[iz]);
! 1575: for (j=1; j<lg(p1); j++)
! 1576: for(nbtest=0;;)
! 1577: {
! 1578: ideal = prime_to_ideal(nf,(GEN)p1[j]);
! 1579: for (i=1; i<lgsub; i++)
! 1580: {
! 1581: ex = mymyrand()>>randshift;
! 1582: if (ex) ideal = idealmulh(nf,ideal,gmael3(powsubfb,i,ex,1));
! 1583: }
! 1584: for (k=1; k<=RU; k++)
! 1585: {
! 1586: if (k==1)
! 1587: for (i=1; i<=RU; i++) exu[i] = mymyrand()>>randshift;
! 1588: else
! 1589: {
! 1590: for (i=1; i<=RU; i++) exu[i] = 0;
! 1591: exu[k] = 10;
! 1592: }
! 1593: for (i=1; i<=RU; i++)
! 1594: MCtw[i] = exu[i]? lmul2n((GEN)MC[i],exu[i]<<1): MC[i];
! 1595: p2 = mulmat_real(MCtw,M);
! 1596: idealpro = ideallllredpart1(nf,ideal,p2,N,PRECREGINT);
! 1597: if (idealpro &&
! 1598: factorisegen(nf,idealpro,iz-1,factorbase[iz-1])) break;
! 1599: nbtest++; if (nbtest==20) return 0;
! 1600: }
! 1601: avma=av; if (k <= RU) break;
! 1602: }
! 1603: }
! 1604: if (DEBUGLEVEL)
! 1605: {
! 1606: if (DEBUGLEVEL>1) fprintferr("\n");
! 1607: msgtimer("be honest");
! 1608: }
! 1609: avma=av; return 1;
! 1610: }
! 1611:
! 1612: int
! 1613: trunc_error(GEN x)
! 1614: {
! 1615: return typ(x)==t_REAL && signe(x)
! 1616: && (expo(x)>>TWOPOTBITS_IN_LONG) + 3 > lg(x);
! 1617: }
! 1618:
! 1619: /* xarch = complex logarithmic embeddings of units (u_j) found so far */
! 1620: static GEN
! 1621: compute_multiple_of_R(GEN xarch,long RU,long N,long PRECREG, GEN *ptsublambda)
! 1622: {
! 1623: GEN v,mdet,Im_mdet,kR,sublambda,lambda,xreal;
! 1624: GEN *gptr[2];
! 1625: long av = avma, i,j, sreg = lg(xarch)-1, R1 = 2*RU - N;
! 1626:
! 1627: if (DEBUGLEVEL) { fprintferr("\n#### Computing regulator\n"); flusherr(); }
! 1628: /* xreal = (log |sigma_i(u_j)|) */
! 1629: xreal=greal(xarch); v=cgetg(RU+1,t_COL);
! 1630: for (i=1; i<=R1; i++) v[i]=un;
! 1631: for ( ; i<=RU; i++) v[i]=deux;
! 1632: mdet=cgetg(sreg+2,t_MAT); mdet[1]=(long)v;
! 1633: for (j=2; j<=sreg+1; j++) mdet[j]=xreal[j-1];
! 1634: /* det(Span(mdet)) = N * R */
! 1635: Im_mdet = imagereel(mdet,PRECREG);
! 1636: if (DEBUGLEVEL) msgtimer("imagereel");
! 1637:
! 1638: /* check we have full rank for units */
! 1639: if (lg(Im_mdet) != RU+1) { avma=av; return NULL; }
! 1640: /* integral multiple of R: the cols we picked form a Q-basis, they have an
! 1641: * index in the full lattice */
! 1642: kR = gdivgs(det2(Im_mdet), N);
! 1643: if (DEBUGLEVEL) msgtimer("detreel");
! 1644: /* R > 0.2 uniformly */
! 1645: if (gexpo(kR) < -3) { avma=av; return NULL; }
! 1646:
! 1647: kR = mpabs(kR);
! 1648: sublambda = cgetg(sreg+1,t_MAT);
! 1649: lambda = gauss(Im_mdet,xreal); /* rational entries */
! 1650: for (i=1; i<=sreg; i++)
! 1651: {
! 1652: GEN p1 = cgetg(RU,t_COL), p2 = (GEN)lambda[i];
! 1653: sublambda[i] = (long)p1;
! 1654: for (j=1; j<RU; j++)
! 1655: {
! 1656: p1[j] = p2[j+1];
! 1657: if (trunc_error((GEN)p1[j])) { *ptsublambda = NULL; return gzero; }
! 1658: }
! 1659: }
! 1660: if (DEBUGLEVEL) msgtimer("gauss & lambda");
! 1661: *ptsublambda = sublambda;
! 1662: gptr[0]=ptsublambda; gptr[1]=&kR;
! 1663: gerepilemany(av,gptr,2); return kR;
! 1664: }
! 1665:
! 1666: /* Assuming enough relations, c = Rz is close to an even integer, according
! 1667: * to Dirichlet's formula. Otherwise, close to a multiple.
! 1668: * Compute a tentative regulator (not a multiple this time) */
! 1669: static GEN
! 1670: compute_check(GEN sublambda, GEN z, GEN *parch, GEN *reg)
! 1671: {
! 1672: long av = avma, av2, tetpil;
! 1673: GEN p1,c,den, R = *reg; /* multiple of regulator */
! 1674:
! 1675: if (DEBUGLEVEL) { fprintferr("\n#### Computing check\n"); flusherr(); }
! 1676: c = gmul(R,z);
! 1677: sublambda = bestappr(sublambda,c); den = denom(sublambda);
! 1678: if (gcmp(den,c) > 0)
! 1679: {
! 1680: if (DEBUGLEVEL) fprintferr("c = %Z\nden = %Z\n",c,den);
! 1681: avma=av; return NULL;
! 1682: }
! 1683:
! 1684: p1 = gmul(sublambda,den); tetpil=avma;
! 1685: *parch = lllint(p1);
! 1686:
! 1687: av2=avma; p1 = det2(gmul(sublambda,*parch));
! 1688: affrr(mpabs(gmul(R,p1)), R); avma=av2;
! 1689:
! 1690: if (DEBUGLEVEL) msgtimer("bestappr/regulator");
! 1691: *parch = gerepile(av,tetpil,*parch); return gmul(R,z);
! 1692: }
! 1693:
! 1694: /* U W V = D, Ui = U^(-1) */
! 1695: GEN
! 1696: compute_class_number(GEN W, GEN *D,GEN *Ui,GEN *V)
! 1697: {
! 1698: GEN S = smith2(W);
! 1699:
! 1700: if (DEBUGLEVEL) { fprintferr("#### Computing class number\n"); flusherr(); }
! 1701: *Ui= ginv((GEN)S[1]);
! 1702: *V = (GEN)S[2];
! 1703: *D = (GEN)S[3];
! 1704: if (DEBUGLEVEL>=4) msgtimer("smith/class group");
! 1705: return dethnf_i(*D);
! 1706: }
! 1707:
! 1708: static void
! 1709: class_group_gen(GEN nf,GEN cyc,GEN clh,GEN u1,GEN u2,GEN vperm,
! 1710: GEN *ptclg1,GEN *ptclg2, long prec)
! 1711: {
! 1712: GEN basecl,baseclorig,I,J,p1,dmin,d, Vbase = vectbase;
! 1713: long i,j,s,inv, lo = lg(cyc), lo0 = lo;
! 1714:
! 1715: if (DEBUGLEVEL)
! 1716: { fprintferr("#### Computing class group generators\n"); flusherr(); }
! 1717: if (vperm)
! 1718: {
! 1719: s = lg(Vbase); Vbase = cgetg(s,t_VEC);
! 1720: for (i=1; i<s; i++) Vbase[i] = vectbase[vperm[i]];
! 1721: }
! 1722: if (typ(cyc) == t_MAT)
! 1723: { /* diagonal matrix */
! 1724: p1 = cgetg(lo,t_VEC);
! 1725: for (j=1; j<lo; j++)
! 1726: {
! 1727: p1[j] = coeff(cyc,j,j);
! 1728: if (gcmp1((GEN)p1[j])) break;
! 1729: }
! 1730: lo0 = lo; lo = j;
! 1731: cyc = p1; setlg(cyc, lo);
! 1732: }
! 1733: baseclorig = cgetg(lo,t_VEC); /* generators = Vbase * u1 (LLL-reduced) */
! 1734: basecl = cgetg(lo,t_VEC);
! 1735: for (j=1; j<lo; j++)
! 1736: {
! 1737: p1 = gcoeff(u1,1,j);
! 1738: I = idealpowred_prime(nf,(GEN)Vbase[1],p1,prec);
! 1739: if (signe(p1)<0) I[1] = lmul((GEN)I[1],denom((GEN)I[1]));
! 1740: for (i=2; i<lo0; i++)
! 1741: {
! 1742: p1=gcoeff(u1,i,j); s=signe(p1);
! 1743: if (s)
! 1744: {
! 1745: J = idealpowred_prime(nf,(GEN)Vbase[i],p1,prec);
! 1746: if (s<0) J[1] = lmul((GEN)J[1],denom((GEN)J[1]));
! 1747: I = idealmulh(nf,I,J);
! 1748: I = ideallllred(nf,I,NULL,prec);
! 1749: }
! 1750: }
! 1751: baseclorig[j]=(long)I; I=(GEN)I[1]; /* I = a generator, order cyc[j] */
! 1752: dmin = dethnf_i(I); J = idealinv(nf,I);
! 1753: J = gmul(J,denom(J));
! 1754: d = dethnf_i(J);
! 1755: /* check if J = denom * I^(-1) has smaller norm */
! 1756: if (cmpii(d,dmin) < 0) { inv=1; I=J; dmin=d; }
! 1757: else { inv=0; }
! 1758: /* try reducing (may _increase_ the norm) */
! 1759: J = ideallllred(nf,J,NULL,prec);
! 1760: d = dethnf_i(J);
! 1761: if (cmpii(d,dmin) < 0) { inv=1; I=J; }
! 1762: basecl[j] = (long)I;
! 1763: if (inv)
! 1764: {
! 1765: u1[j] = lneg((GEN)u1[j]);
! 1766: u2[j] = lneg((GEN)u2[j]);
! 1767: }
! 1768: }
! 1769: p1 = cgetg(4,t_VEC);
! 1770: p1[1]=(long)clh;
! 1771: p1[2]=(long)cyc;
! 1772: p1[3]=(long)basecl; *ptclg1 = p1;
! 1773: /* W*u2 = u1*diag(cyc) */
! 1774: p1 = cgetg(4,t_VEC);
! 1775: p1[1]=(long)u1;
! 1776: p1[2]=(long)u2;
! 1777: p1[3]=(long)baseclorig; *ptclg2 = p1;
! 1778: if (DEBUGLEVEL) msgtimer("classgroup generators");
! 1779: }
! 1780:
! 1781: static GEN
! 1782: compute_matt2(long RU,GEN nf)
! 1783: {
! 1784: GEN matt2, MCcopy, MCshif, M = gmael(nf,5,1), MC = gmael(nf,5,2);
! 1785: long i,j,k,n = min(RU,9), N = n*(n+1)/2, ind = 1;
! 1786:
! 1787: MCcopy=cgetg(RU+1,t_MAT); MCshif=cgetg(n+1,t_MAT);
! 1788: for (k=1; k<=RU; k++) MCcopy[k]=MC[k];
! 1789: for (k=1; k<=n; k++) MCshif[k]=lmul2n((GEN)MC[k],20);
! 1790: matt2=cgetg(N+1,t_VEC);
! 1791: for (j=1; j<=n; j++)
! 1792: {
! 1793: MCcopy[j]=MCshif[j];
! 1794: for (i=1; i<=j; i++)
! 1795: {
! 1796: MCcopy[i]=MCshif[i];
! 1797: matt2[ind++] = (long)mulmat_real(MCcopy,M);
! 1798: MCcopy[i]=MC[i];
! 1799: }
! 1800: MCcopy[j]=MC[j];
! 1801: }
! 1802: if (DEBUGLEVEL) msgtimer("weighted T2 matrices");
! 1803: return matt2;
! 1804: }
! 1805:
! 1806: /* no garbage collecting. destroys y */
! 1807: static GEN
! 1808: relationrank_partial(GEN ptinvp, GEN y, long k, long n)
! 1809: {
! 1810: long i,j;
! 1811: GEN res=cgetg(n+1,t_MAT), p1;
! 1812:
! 1813: for (i=k+1; i<=n; i++) y[i] = ldiv(gneg_i((GEN)y[i]),(GEN)y[k]);
! 1814: for (j=1; j<=k; j++)
! 1815: {
! 1816: p1=cgetg(n+1,t_COL); res[j]=(long)p1;
! 1817: for (i=1; i<j; i++) p1[i]=zero;
! 1818: for ( ; i<k; i++) p1[i]=coeff(ptinvp,i,j);
! 1819: p1[k]=ldiv(gcoeff(ptinvp,k,j),(GEN)y[k]);
! 1820: if (j==k)
! 1821: for (i=k+1; i<=n; i++)
! 1822: p1[i]=lmul((GEN)y[i],gcoeff(ptinvp,k,k));
! 1823: else
! 1824: for (i=k+1; i<=n; i++)
! 1825: p1[i]=ladd(gcoeff(ptinvp,i,j), gmul((GEN)y[i], gcoeff(ptinvp,k,j)));
! 1826: }
! 1827: for ( ; j<=n; j++) res[j]=ptinvp[j];
! 1828: return res;
! 1829: }
! 1830:
! 1831: /* Programmes de calcul du rang d'une matrice A de M_{ n,r }(Q) avec rang(A)=
! 1832: * r <= n On transforme peu a peu la matrice I dont les colonnes sont les
! 1833: * vecteurs de la base canonique de Q^n en une matrice de changement de base
! 1834: * P obtenue en prenant comme base les colonnes de A independantes et des
! 1835: * vecteurs de la base canonique. On rend P^(-1), L un vecteur ligne a n
! 1836: * composantes valant 0 ou 1 selon que le le vecteur correspondant de P est
! 1837: * e_i ou x_i (e_i vecteur de la base canonique, x_i i-eme colonne de A)
! 1838: */
! 1839: static GEN
! 1840: relationrank(long **mat,long n,long r,long *L)
! 1841: {
! 1842: long av = avma,tetpil,i,j,lim;
! 1843: GEN ptinvp,y;
! 1844:
! 1845: if (r>n) err(talker,"incorrect matrix in relationrank");
! 1846: if (DEBUGLEVEL)
! 1847: {
! 1848: fprintferr("After trivial relations, cmptglob = %ld\n",r);
! 1849: msgtimer("mat & matarch");
! 1850: }
! 1851: lim=stack_lim(av,1); ptinvp=idmat(n);
! 1852: for (i=1; i<=r; i++)
! 1853: {
! 1854: j=1; y = gmul_mat_smallvec(ptinvp,mat[i],n,n);
! 1855: while (j<=n && (gcmp0((GEN)y[j]) || L[j])) j++;
! 1856: if (j>n && i==r) err(talker,"not a maximum rank matrix in relationrank");
! 1857: ptinvp = relationrank_partial(ptinvp,y,j,n); L[j]=1;
! 1858: if (low_stack(lim, stack_lim(av,1)))
! 1859: {
! 1860: if(DEBUGMEM>1) err(warnmem,"relationrank");
! 1861: tetpil=avma; ptinvp=gerepile(av,tetpil,gcopy(ptinvp));
! 1862: }
! 1863: }
! 1864: tetpil=avma; ptinvp=gerepile(av,tetpil,gcopy(ptinvp));
! 1865: if (DEBUGLEVEL>1)
! 1866: { fprintferr("\nRank of trivial relations matrix: %ld\n",r); flusherr(); }
! 1867: return ptinvp;
! 1868: }
! 1869:
! 1870: /* Etant donnes une matrice dans M_{ n,r }(Q), de rang maximum r < n, un
! 1871: * vecteur colonne V a n lignes, la matrice *INVP et le vecteur ligne *L
! 1872: * donnes par le programme relationrank() ci-dessus, on teste si le vecteur V
! 1873: * est lineairement independant des colonnes de la matrice; si la reponse est
! 1874: * non, on rend le rang de la matrice; si la reponse est oui, on rend le rang
! 1875: * de la matrice + 1, on met dans *INVP l'inverse de la nouvelle matrice
! 1876: * *INVP et dans *L le nouveau vecteur ligne *L
! 1877: */
! 1878: long
! 1879: addcolumntomatrix(long *V, long n,long r,GEN *INVP,long *L)
! 1880: {
! 1881: long av = avma,i,k;
! 1882: GEN ptinvp,y;
! 1883:
! 1884: if (DEBUGLEVEL>4)
! 1885: {
! 1886: fprintferr("\n*** Entering addcolumntomatrix(). AVMA = %ld\n",avma);
! 1887: flusherr();
! 1888: }
! 1889: ptinvp=*INVP; y=gmul_mat_smallvec(ptinvp,V,n,n);
! 1890: if (DEBUGLEVEL>6)
! 1891: {
! 1892: fprintferr("vector = [\n");
! 1893: for (i=1; i<n; i++) fprintferr("%ld,",V[i]);
! 1894: fprintferr("%ld]~\n",V[n]); flusherr();
! 1895: fprintferr("vector in new basis = \n"); outerr(y);
! 1896: fprintferr("base change matrix = \n"); outerr(ptinvp);
! 1897: fprintferr("list = [");
! 1898: for (i=1; i<=n-1; i++) fprintferr("%ld,",L[i]);
! 1899: fprintferr("%ld]\n",L[n]); flusherr();
! 1900: }
! 1901: k=1; while (k<=n && (gcmp0((GEN)y[k]) || L[k])) k++;
! 1902: if (k>n) avma=av;
! 1903: else
! 1904: {
! 1905: *INVP = relationrank_partial(ptinvp,y,k,n);
! 1906: L[k]=1; r++;
! 1907: }
! 1908: if (DEBUGLEVEL>4)
! 1909: {
! 1910: fprintferr("*** Leaving addcolumntomatrix(). AVMA = %ld\n",avma);
! 1911: flusherr();
! 1912: }
! 1913: return r;
! 1914: }
! 1915:
! 1916: /* a usage special: uniquement pour passer du format smallbnf au format bnf
! 1917: * Ici, vectbase est deja permute, donc pas de vperm. A l'effet de
! 1918: * compute_class_number() suivi de class_group_gen().
! 1919: */
! 1920: static void
! 1921: classintern(GEN nf,GEN W,GEN *ptcl, GEN *ptcl2)
! 1922: {
! 1923: long prec = (long)nfnewprec(nf,-1);
! 1924: GEN met,u1,u2, clh = compute_class_number(W,&met,&u1,&u2);
! 1925: class_group_gen(nf,met,clh,u1,u2,NULL,ptcl,ptcl2, prec);
! 1926: }
! 1927:
! 1928: static GEN
! 1929: codeprime(GEN bnf, GEN pr)
! 1930: {
! 1931: long j,av=avma,tetpil;
! 1932: GEN p,al,fa,p1;
! 1933:
! 1934: p=(GEN)pr[1]; al=(GEN)pr[2]; fa=primedec(bnf,p);
! 1935: for (j=1; j<lg(fa); j++)
! 1936: if (gegal(al,gmael(fa,j,2)))
! 1937: {
! 1938: p1=mulsi(lg(al)-1,p); tetpil=avma;
! 1939: return gerepile(av,tetpil,addsi(j-1,p1));
! 1940: }
! 1941: err(talker,"bug in codeprime/smallbuchinit");
! 1942: return NULL; /* not reached */
! 1943: }
! 1944:
! 1945: static GEN
! 1946: decodeprime(GEN nf, GEN co)
! 1947: {
! 1948: long n,indi,av=avma,tetpil;
! 1949: GEN p,rem,p1;
! 1950:
! 1951: n=lg(nf[7])-1; p=dvmdis(co,n,&rem); indi=itos(rem)+1;
! 1952: p1=primedec(nf,p); tetpil=avma;
! 1953: return gerepile(av,tetpil,gcopy((GEN)p1[indi]));
! 1954: }
! 1955:
! 1956: static GEN
! 1957: makematal(GEN bnf)
! 1958: {
! 1959: GEN W,B,pfb,vp,nf,ma,pr;
! 1960: long lm,lma,av=avma,tetpil,j,k;
! 1961:
! 1962: if (!gcmp0((GEN)bnf[10])) return (GEN)bnf[10];
! 1963: W=(GEN)bnf[1]; B=(GEN)bnf[2];
! 1964: pfb=(GEN)bnf[5]; vp=(GEN)bnf[6]; nf=(GEN)bnf[7];
! 1965: lm=(lg(W)>1)?lg(W[1])-1:0; lma=lm+lg(B);
! 1966: ma=cgetg(lma,t_MAT);
! 1967: for (j=1; j<lma; j++)
! 1968: {
! 1969: GEN ex = (j<=lm)? (GEN)W[j]: (GEN)B[j-lm];
! 1970: GEN id = (j<=lm)? gun: (GEN)pfb[itos((GEN)vp[j])];
! 1971: for (k=1; k<=lm; k++)
! 1972: {
! 1973: pr=(GEN)pfb[itos((GEN)vp[k])];
! 1974: id=idealmul(nf,id,idealpow(nf,pr,(GEN)ex[k]));
! 1975: }
! 1976: ma[j]=isprincipalgen(bnf,id)[2];
! 1977: if (lg(ma[j])==1)
! 1978: err(talker,"bnf not accurate enough to create a sbnf (makematal)");
! 1979: }
! 1980: tetpil=avma; return gerepile(av,tetpil,gcopy(ma));
! 1981: }
! 1982:
! 1983: GEN
! 1984: smallbuchinit(GEN pol,GEN gcbach,GEN gcbach2,GEN gRELSUP,GEN gborne,long nbrelpid,long minsfb,long prec)
! 1985: {
! 1986: long av=avma,tetpil,k;
! 1987: GEN y,bnf,pfb,vp,nf,mas,res,uni,v1,v2,v3;
! 1988:
! 1989: if (typ(pol)==t_VEC) bnf = checkbnf(pol);
! 1990: else
! 1991: {
! 1992: bnf=buchall(pol,gcbach,gcbach2,gRELSUP,gborne,nbrelpid,minsfb,-3,prec);
! 1993: if (checkbnf(bnf) != bnf)
! 1994: {
! 1995: err(warner,"non-monic polynomial. Change of variables discarded");
! 1996: bnf = (GEN)bnf[1];
! 1997: }
! 1998: }
! 1999: pfb=(GEN)bnf[5]; vp=(GEN)bnf[6]; nf=(GEN)bnf[7];
! 2000: mas=(GEN)nf[5]; res=(GEN)bnf[8]; uni=(GEN)res[5];
! 2001:
! 2002: tetpil=avma;
! 2003: y=cgetg(13,t_VEC); y[1]=lcopy((GEN)nf[1]); y[2]=lcopy(gmael(nf,2,1));
! 2004: y[3]=lcopy((GEN)nf[3]); y[4]=lcopy((GEN)nf[7]);
! 2005: y[5]=lcopy((GEN)nf[6]); y[6]=lcopy((GEN)mas[5]);
! 2006: y[7]=lcopy((GEN)bnf[1]); y[8]=lcopy((GEN)bnf[2]);
! 2007: v1=cgetg(lg(pfb),t_VEC); y[9]=(long)v1;
! 2008: for (k=1; k<lg(pfb); k++)
! 2009: v1[k]=(long)codeprime(bnf,(GEN)pfb[itos((GEN)vp[k])]);
! 2010: v2=cgetg(3,t_VEC); y[10]=(long)v2;
! 2011: v2[1]=lcopy(gmael(res,4,1));
! 2012: v2[2]=(long)algtobasis(bnf,gmael(res,4,2));
! 2013: v3=cgetg(lg(uni),t_VEC); y[11]=(long)v3;
! 2014: for (k=1; k<lg(uni); k++)
! 2015: v3[k]=(long)algtobasis(bnf,(GEN)uni[k]);
! 2016: y[12]=gcmp0((GEN)bnf[10])? (long)makematal(bnf): lcopy((GEN)bnf[10]);
! 2017: return gerepile(av,tetpil,y);
! 2018: }
! 2019:
! 2020: static GEN
! 2021: get_regulator(GEN mun,long prec)
! 2022: {
! 2023: long av,tetpil;
! 2024: GEN p1;
! 2025:
! 2026: if (lg(mun)==1) return gun;
! 2027: av=avma; p1 = gtrans(greal(mun));
! 2028: setlg(p1,lg(p1)-1); p1 = det(p1);
! 2029: tetpil=avma; return gerepile(av,tetpil,gabs(p1,prec));
! 2030: }
! 2031:
! 2032: static GEN
! 2033: get_mun(GEN funits, GEN ro, long ru, long r1, long prec)
! 2034: {
! 2035: long j,k,av=avma,tetpil;
! 2036: GEN p1,p2, mun = cgetg(ru,t_MAT);
! 2037:
! 2038: for (k=1; k<ru; k++)
! 2039: {
! 2040: p1=cgetg(ru+1,t_COL); mun[k]=(long)p1;
! 2041: for (j=1; j<=ru; j++)
! 2042: {
! 2043: p2 = glog(poleval((GEN)funits[k],(GEN)ro[j]),prec);
! 2044: p1[j]=(j<=r1)? (long)p2: lmul2n(p2,1);
! 2045: }
! 2046: }
! 2047: tetpil=avma; return gerepile(av,tetpil,gcopy(mun));
! 2048: }
! 2049:
! 2050: static GEN
! 2051: get_mc(GEN nf, GEN alphs, long prec)
! 2052: {
! 2053: GEN mc,p1,p2,p3,p4, bas = (GEN)nf[7], pol = (GEN)nf[1], ro = (GEN)nf[6];
! 2054: long ru = lg(ro), n = lgef(pol)-3, r1 = itos(gmael(nf,2,1));
! 2055: long j,k, la = lg(alphs);
! 2056:
! 2057: mc = cgetg(la,t_MAT);
! 2058: for (k=1; k<la; k++)
! 2059: {
! 2060: p4 = gmul(bas,(GEN)alphs[k]);
! 2061: p3 = gdivgs(glog(gabs(subres(pol,p4),prec),prec), n);
! 2062: p1 = cgetg(ru,t_COL); mc[k] = (long)p1;
! 2063: for (j=1; j<ru; j++)
! 2064: {
! 2065: p2 = gsub(glog(poleval(p4,(GEN)ro[j]),prec), p3);
! 2066: p1[j]=(j<=r1)? (long) p2: lmul2n(p2,1);
! 2067: }
! 2068: }
! 2069: return mc;
! 2070: }
! 2071:
! 2072: static void
! 2073: my_class_group_gen(GEN bnf, GEN *ptcl, GEN *ptcl2)
! 2074: {
! 2075: GEN nf=(GEN)bnf[7], Vbase=(GEN)bnf[5], vperm=(GEN)bnf[6], *gptr[2];
! 2076: long av = avma, i, lv = lg(Vbase);
! 2077:
! 2078: vectbase = cgetg(lv, t_VEC);
! 2079: for (i=1; i<lv; i++) vectbase[i] = Vbase[itos((GEN)vperm[i])];
! 2080: classintern(nf,(GEN)bnf[1],ptcl,ptcl2);
! 2081: gptr[0]=ptcl; gptr[1]=ptcl2; gerepilemany(av,gptr,2);
! 2082: }
! 2083:
! 2084: GEN
! 2085: bnfnewprec(GEN bnf, long prec)
! 2086: {
! 2087: GEN nf,ro,res,p1,funits,mun,matal,clgp,clgp2, y = cgetg(11,t_VEC);
! 2088: long r1,r2,ru,av;
! 2089:
! 2090: bnf = checkbnf(bnf); nf = nfnewprec((GEN)bnf[7],prec);
! 2091: if (prec <= 0) return nf;
! 2092: r1=itos(gmael(nf,2,1)); r2=itos(gmael(nf,2,2));
! 2093: ru = r1+r2;
! 2094: res=cgetg(7,t_VEC); p1=(GEN)bnf[8];
! 2095: funits = check_units(bnf,"bnfnewprec");
! 2096: ro=(GEN)nf[6];
! 2097: mun = get_mun(funits,ro,ru,r1,prec);
! 2098: res[2]=(long)get_regulator(mun,prec);
! 2099: res[3]=lcopy((GEN)p1[3]);
! 2100: res[4]=lcopy((GEN)p1[4]);
! 2101: res[5]=lcopy((GEN)p1[5]);
! 2102: res[6]=lcopy((GEN)p1[6]);
! 2103:
! 2104: y[1]=lcopy((GEN)bnf[1]);
! 2105: y[2]=lcopy((GEN)bnf[2]);
! 2106: y[3]=(long)mun;
! 2107: av = avma;
! 2108: matal = (GEN)bnf[10];
! 2109: if (gcmp0(matal))
! 2110: {
! 2111: if (DEBUGLEVEL) err(warner,"building matal and completing bnf");
! 2112: matal = gclone(makematal(bnf)); bnf[10] = (long)matal;
! 2113: }
! 2114: avma = av;
! 2115: y[4]=lpileupto(av, gcopy(get_mc(nf,matal,prec)));
! 2116: y[5]=lcopy((GEN)bnf[5]);
! 2117: y[6]=lcopy((GEN)bnf[6]);
! 2118: y[7]=(long)nf;
! 2119: y[8]=(long)res;
! 2120: my_class_group_gen(y,&clgp,&clgp2);
! 2121: res[1]=(long)clgp;
! 2122: y[9]=(long)clgp2;
! 2123: y[10]=(long)matal; return y;
! 2124: }
! 2125:
! 2126: GEN
! 2127: bnfmake(GEN sbnf, long prec)
! 2128: {
! 2129: long av = avma, j,k,n,r1,r2,ru,lpf;
! 2130: GEN p1,p2,pol,bas,ro,m,mul,pok,M,MC,T2,mas,T,TI,nf,mun,funits;
! 2131: GEN pfc,vp,mc,clgp,clgp2,res,y,W,mata,racu,reg;
! 2132:
! 2133: if (typ(sbnf)!=t_VEC || lg(sbnf)!=13)
! 2134: err(talker,"incorrect sbnf in bnfmake");
! 2135: pol=(GEN)sbnf[1]; bas=(GEN)sbnf[4]; n=lg(bas)-1;
! 2136: r1=itos((GEN)sbnf[2]); r2=(n-r1)/2; ru=r1+r2;
! 2137: ro=(GEN)sbnf[5];
! 2138: if (prec > gprecision(ro)) ro=get_roots(pol,r1,ru,prec);
! 2139:
! 2140: m=cgetg(n+1,t_MAT);
! 2141: for (k=1; k<=n; k++)
! 2142: {
! 2143: p1=cgetg(n+1,t_COL); m[k]=(long)p1; p2=(GEN)bas[k];
! 2144: for (j=1; j<=n; j++) p1[j]=(long)truecoeff(p2,j-1);
! 2145: }
! 2146: m=invmat(m);
! 2147: mul=cgetg(n*n+1,t_MAT);
! 2148: for (k=1; k<=n*n; k++)
! 2149: {
! 2150: pok = gres(gmul((GEN)bas[(k-1)%n+1], (GEN)bas[(long)((k-1)/n)+1]), pol);
! 2151: p1=cgetg(n+1,t_COL); mul[k]=(long)p1;
! 2152: for (j=1; j<=n; j++) p1[j]=(long)truecoeff(pok,j-1);
! 2153: }
! 2154: mul=gmul(m,mul);
! 2155:
! 2156: M = make_M(n,ru,bas,ro);
! 2157: MC = make_MC(n,r1,ru,M);
! 2158: T2 = mulmat_real(MC,M);
! 2159: p1=mulmat_real(gconj(MC),M); T=ground(p1);
! 2160: if (gexpo(gnorml2(gsub(p1,T))) > -30)
! 2161: err(talker,"insufficient precision in bnfmake");
! 2162: TI=gmul((GEN)sbnf[3],invmat(T));
! 2163:
! 2164: mas=cgetg(8,t_VEC);
! 2165: nf=cgetg(10,t_VEC);
! 2166: p1=cgetg(3,t_VEC); p1[1]=lstoi(r1); p1[2]=lstoi(r2);
! 2167: nf[1]=sbnf[1] ; nf[2]=(long)p1; nf[3]=sbnf[3];
! 2168: nf[4]=ldet(m) ; nf[5]=(long)mas; nf[6]=(long)ro;
! 2169: nf[7]=(long)bas; nf[8]=(long)m; nf[9]=(long)mul;
! 2170:
! 2171: mas[1]=(long)M; mas[2]=(long)MC; mas[3]=(long)T2;
! 2172: mas[4]=(long)T; mas[5]=sbnf[6]; mas[6]=(long)TI;
! 2173: mas[7]=(long)make_TI(nf,TI,gun);
! 2174:
! 2175: funits=cgetg(ru,t_VEC); p1 = (GEN)sbnf[11];
! 2176: for (k=1; k < lg(p1); k++)
! 2177: funits[k] = lmul(bas,(GEN)p1[k]);
! 2178: mun = get_mun(funits,ro,ru,r1,prec);
! 2179:
! 2180: prec=gprecision(ro); if (prec<DEFAULTPREC) prec=DEFAULTPREC;
! 2181: mc = get_mc(nf, (GEN)sbnf[12], prec);
! 2182:
! 2183: pfc=(GEN)sbnf[9]; lpf=lg(pfc);
! 2184: vectbase=cgetg(lpf,t_COL); vp=cgetg(lpf,t_COL);
! 2185: for (j=1; j<lpf; j++)
! 2186: {
! 2187: vp[j]=lstoi(j);
! 2188: vectbase[j]=(long)decodeprime(nf,(GEN)pfc[j]);
! 2189: }
! 2190: classintern(nf,(GEN)sbnf[7], &clgp, &clgp2); /* uses vectbase */
! 2191:
! 2192: reg = get_regulator(mun,prec);
! 2193: p1=cgetg(3,t_VEC); racu=(GEN)sbnf[10];
! 2194: p1[1]=racu[1]; p1[2]=lmul(bas,(GEN)racu[2]);
! 2195: racu=p1;
! 2196:
! 2197: res=cgetg(7,t_VEC);
! 2198: res[1]=(long)clgp; res[2]=(long)reg; res[3]=(long)dbltor(1.0);
! 2199: res[4]=(long)racu; res[5]=(long)funits; res[6]=lstoi(1000);
! 2200:
! 2201: if (lg(sbnf[7])>1) { W=(GEN)sbnf[7]; mata=(GEN)sbnf[8]; }
! 2202: else
! 2203: {
! 2204: long la = lg(sbnf[12]);
! 2205: W=cgetg(1,t_MAT); mata=cgetg(la,t_MAT);
! 2206: for (k=1; k<la; k++) mata[k]=lgetg(1,t_COL);
! 2207: }
! 2208: y=cgetg(11,t_VEC);
! 2209: y[1]=(long)W; y[2]=(long)mata; y[3]=(long)mun;
! 2210: y[4]=(long)mc; y[5]=(long)vectbase; y[6]=(long)vp;
! 2211: y[7]=(long)nf; y[8]=(long)res; y[9]=(long)clgp2; y[10]=zero;
! 2212: return gerepileupto(av,gcopy(y));
! 2213: }
! 2214:
! 2215: static GEN
! 2216: classgroupall(GEN P, GEN data, long flag, long prec)
! 2217: {
! 2218: long court[3],doubl[4];
! 2219: long av=avma,flun,lx, minsfb=3,nbrelpid=4;
! 2220: GEN bach=doubl,bach2=doubl,RELSUP=court,borne=gun;
! 2221:
! 2222: if (!data) lx=1;
! 2223: else
! 2224: {
! 2225: lx = lg(data);
! 2226: if (typ(data)!=t_VEC || lx > 7)
! 2227: err(talker,"incorrect parameters in classgroup");
! 2228: }
! 2229: court[0]=evaltyp(t_INT) | evallg(3); affsi(5,court);
! 2230: doubl[0]=evaltyp(t_REAL)| evallg(4); affrr(dbltor(0.3),doubl);
! 2231: avma=av;
! 2232: switch(lx)
! 2233: {
! 2234: case 7: minsfb = itos((GEN)data[6]);
! 2235: case 6: nbrelpid= itos((GEN)data[5]);
! 2236: case 5: borne = (GEN)data[4];
! 2237: case 4: RELSUP = (GEN)data[3];
! 2238: case 3: bach2 = (GEN)data[2];
! 2239: case 2: bach = (GEN)data[1];
! 2240: }
! 2241: switch(flag)
! 2242: {
! 2243: case 0: flun=-2; break;
! 2244: case 1: flun=-3; break;
! 2245: case 2: flun=-1; break;
! 2246: case 3: return smallbuchinit(P,bach,bach2,RELSUP,borne,nbrelpid,minsfb,prec);
! 2247: case 4: flun=2; break;
! 2248: case 5: flun=3; break;
! 2249: case 6: flun=0; break;
! 2250: }
! 2251: return buchall(P,bach,bach2,RELSUP,borne,nbrelpid,minsfb,flun,prec);
! 2252: }
! 2253:
! 2254: GEN
! 2255: bnfclassunit0(GEN P, long flag, GEN data, long prec)
! 2256: {
! 2257: if (typ(P)==t_INT) return quadclassunit0(P,0,data,prec);
! 2258: if (flag < 0 || flag > 2) err(flagerr,"bnfclassunit");
! 2259: return classgroupall(P,data,flag+4,prec);
! 2260: }
! 2261:
! 2262: GEN
! 2263: bnfinit0(GEN P, long flag, GEN data, long prec)
! 2264: {
! 2265: #if 0
! 2266: THIS SHOULD BE DONE...
! 2267:
! 2268: if (typ(P)==t_INT)
! 2269: {
! 2270: if (flag<4) err(impl,"specific bnfinit for quadratic fields");
! 2271: return quadclassunit0(P,0,data,prec);
! 2272: }
! 2273: #endif
! 2274: if (flag < 0 || flag > 3) err(flagerr,"bnfinit");
! 2275: return classgroupall(P,data,flag,prec);
! 2276: }
! 2277:
! 2278: GEN
! 2279: classgrouponly(GEN P, GEN data, long prec)
! 2280: {
! 2281: GEN y,z;
! 2282: long av=avma,tetpil,i;
! 2283:
! 2284: if (typ(P)==t_INT)
! 2285: {
! 2286: z=quadclassunit0(P,0,data,prec); tetpil=avma;
! 2287: y=cgetg(4,t_VEC); for (i=1; i<=3; i++) y[i]=lcopy((GEN)z[i]);
! 2288: return gerepile(av,tetpil,y);
! 2289: }
! 2290: z=(GEN)classgroupall(P,data,6,prec)[1]; tetpil=avma;
! 2291: return gerepile(av,tetpil,gcopy((GEN)z[5]));
! 2292: }
! 2293:
! 2294: GEN
! 2295: regulator(GEN P, GEN data, long prec)
! 2296: {
! 2297: GEN z;
! 2298: long av=avma,tetpil;
! 2299:
! 2300: if (typ(P)==t_INT)
! 2301: {
! 2302: if (signe(P)>0)
! 2303: {
! 2304: z=quadclassunit0(P,0,data,prec); tetpil=avma;
! 2305: return gerepile(av,tetpil,gcopy((GEN)z[4]));
! 2306: }
! 2307: return gun;
! 2308: }
! 2309: z=(GEN)classgroupall(P,data,6,prec)[1]; tetpil=avma;
! 2310: return gerepile(av,tetpil,gcopy((GEN)z[6]));
! 2311: }
! 2312:
! 2313: #ifdef INLINE
! 2314: INLINE
! 2315: #endif
! 2316: GEN
! 2317: col_dup(long n, GEN col)
! 2318: {
! 2319: GEN c = (GEN) gpmalloc(sizeof(long)*(n+1));
! 2320: memcpy(c,col,(n+1)*sizeof(long));
! 2321: return c;
! 2322: }
! 2323:
! 2324: #ifdef INLINE
! 2325: INLINE
! 2326: #endif
! 2327: GEN
! 2328: col_0(long n)
! 2329: {
! 2330: GEN c = (GEN) gpmalloc(sizeof(long)*(n+1));
! 2331: long i;
! 2332: for (i=1; i<=n; i++) c[i]=0;
! 2333: return c;
! 2334: }
! 2335:
! 2336: static GEN
! 2337: buchall_end(GEN nf,GEN CHANGE,long fl,long k, GEN fu, GEN clg1, GEN clg2,
! 2338: GEN reg, GEN c_1, GEN zu, GEN W, GEN B,
! 2339: GEN xarch, GEN matarch, GEN vectbase, GEN vperm)
! 2340: {
! 2341: long l = labs(fl)>1? 11: fl? 9: 8;
! 2342: GEN p1,z, RES = cgetg(11,t_COL);
! 2343:
! 2344: setlg(RES,l);
! 2345: RES[5]=(long)clg1;
! 2346: RES[6]=(long)reg;
! 2347: RES[7]=(long)c_1;
! 2348: RES[8]=(long)zu;
! 2349: RES[9]=(long)fu;
! 2350: RES[10]=lstoi(k);
! 2351: if (fl>=0)
! 2352: {
! 2353: RES[1]=nf[1];
! 2354: RES[2]=nf[2]; p1=cgetg(3,t_VEC); p1[1]=nf[3]; p1[2]=nf[4];
! 2355: RES[3]=(long)p1;
! 2356: RES[4]=nf[7];
! 2357: z=cgetg(2,t_MAT); z[1]=lcopy(RES); return z;
! 2358: }
! 2359: z=cgetg(11,t_VEC);
! 2360: z[1]=(long)W;
! 2361: z[2]=(long)B;
! 2362: z[3]=(long)xarch;
! 2363: z[4]=(long)matarch;
! 2364: z[5]=(long)vectbase;
! 2365: z[6]=(long)vperm;
! 2366: z[7]=(long)nf; RES+=4; RES[0]=evaltyp(t_VEC) | evallg(l-4);
! 2367: z[8]=(long)RES;
! 2368: z[9]=(long)clg2;
! 2369: z[10]=zero; /* dummy: we MUST have lg(bnf) != lg(nf) */
! 2370: if (CHANGE) { p1=cgetg(3,t_VEC); p1[1]=(long)z; p1[2]=(long)CHANGE; z=p1; }
! 2371: return gcopy(z);
! 2372: }
! 2373:
! 2374: static GEN
! 2375: buchall_for_degree_one_pol(GEN nf, GEN CHANGE, long flun)
! 2376: {
! 2377: long av = avma, k = EXP220;
! 2378: GEN W,B,xarch,matarch,vectbase,vperm;
! 2379: GEN fu=cgetg(1,t_VEC), reg=gun, c_1=gun, zu=cgetg(3,t_VEC);
! 2380: GEN clg1=cgetg(4,t_VEC), clg2=cgetg(4,t_VEC);
! 2381:
! 2382: clg1[1]=un; clg1[2]=clg1[3]=clg2[3]=lgetg(1,t_VEC);
! 2383: clg2[1]=clg2[2]=lgetg(1,t_MAT);
! 2384: zu[1]=deux; zu[2]=lnegi(gun);
! 2385: W=B=xarch=matarch=cgetg(1,t_MAT);
! 2386: vectbase=cgetg(1,t_COL); vperm=cgetg(1,t_VEC);
! 2387:
! 2388: return gerepileupto(av, buchall_end(nf,CHANGE,flun,k,fu,clg1,clg2,reg,c_1,zu,W,B,xarch,matarch,vectbase,vperm));
! 2389: }
! 2390:
! 2391: GEN
! 2392: buchall(GEN P,GEN gcbach,GEN gcbach2,GEN gRELSUP,GEN gborne,long nbrelpid,
! 2393: long minsfb,long flun,long prec)
! 2394: {
! 2395: long av = avma,av0,av1,limpile,i,j,k,ss,cmptglob,lgsub;
! 2396: long N,R1,R2,RU,PRECREG,PRECREGINT,KCCO,KCCOPRO,RELSUP;
! 2397: long extrarel,nlze,sreg,nrelsup,nreldep,phase,slim,matcopymax;
! 2398: long first = 1, sfb_increase = 0, sfb_trials = 0;
! 2399: long **mat,**matcopy,*ex;
! 2400: double cbach,cbach2,drc,LOGD2,lim,LIMC,LIMC2;
! 2401: GEN p1,p2,lmatt2,fu,zu,nf,D,xarch,met,W,reg,lfun,z,clh,vperm,subfb;
! 2402: GEN B,C,u1,u2,c1,sublambda,pdep,parch,liste,invp,clg1,clg2;
! 2403: GEN CHANGE=NULL, extramat=NULL, extraC=NULL, list_jideal = NULL;
! 2404:
! 2405: if (DEBUGLEVEL) timer2();
! 2406:
! 2407: if (typ(P)==t_POL) nf = NULL;
! 2408: else
! 2409: {
! 2410: nf=checknf(P); P=(GEN)nf[1];
! 2411: }
! 2412: if (typ(gRELSUP)!=t_INT) gRELSUP=gtrunc(gRELSUP);
! 2413: RELSUP = itos(gRELSUP);
! 2414: if (RELSUP<=0) err(talker,"not enough relations in bnfxxx");
! 2415:
! 2416: /* Initializations */
! 2417: N=lgef(P)-3;
! 2418: if (!nf)
! 2419: {
! 2420: nf=initalgall0(P, flun>=0? nf_REGULAR: nf_DIFFERENT,
! 2421: max(BIGDEFAULTPREC,prec));
! 2422: if (lg(nf)==3) /* P was a non-monic polynomial, nfinit changed it */
! 2423: {
! 2424: CHANGE=(GEN)nf[2]; nf=(GEN)nf[1];
! 2425: }
! 2426: if (DEBUGLEVEL) msgtimer("initalg");
! 2427: }
! 2428: if (N<=1) return buchall_for_degree_one_pol(nf,CHANGE,flun);
! 2429: zu=rootsof1(nf);
! 2430: zu[2] = lmul((GEN)nf[7],(GEN)zu[2]);
! 2431: if (DEBUGLEVEL) msgtimer("rootsof1");
! 2432:
! 2433: R1=itos(gmael(nf,2,1)); R2=(N-R1)>>1; RU=R1+R2;
! 2434: D=(GEN)nf[3]; drc=fabs(gtodouble(D));
! 2435: LOGD2=log(drc); LOGD2 = LOGD2*LOGD2;
! 2436: lim = exp(-(double)N) * sqrt(2*PI*N*drc) * pow(4/PI,(double)R2);
! 2437: if (lim < 3.) lim = 3.;
! 2438: cbach = min(12., gtodouble(gcbach)); cbach /= 2;
! 2439: cbach2 = gtodouble(gcbach2);
! 2440: if (DEBUGLEVEL)
! 2441: {
! 2442: fprintferr("N = %ld, R1 = %ld, R2 = %ld, RU = %ld\n",N,R1,R2,RU);
! 2443: fprintferr("D = %Z\n",D);
! 2444: }
! 2445: av0 = avma;
! 2446: matcopy = NULL;
! 2447: powsubfb = NULL;
! 2448:
! 2449: INCREASEGEN:
! 2450: if (first) first = 0; else { desallocate(matcopy); avma = av0; }
! 2451: sfb_trials = sfb_increase = 0;
! 2452: cbach = check_bach(cbach,12.);
! 2453: nreldep = nrelsup = 0;
! 2454: LIMC = cbach*LOGD2; if (LIMC < 20.) LIMC = 20.;
! 2455: LIMC2=max(3. * N, max(cbach,cbach2)*LOGD2);
! 2456: if (LIMC2 < LIMC) LIMC2=LIMC;
! 2457: if (DEBUGLEVEL) { fprintferr("LIMC = %.1f, LIMC2 = %.1f\n",LIMC,LIMC2); }
! 2458:
! 2459: /* initialize factorbase, [sub]vperm */
! 2460: lfun = factorbasegen(nf,(long)LIMC2,(long)LIMC);
! 2461: if (!lfun) goto INCREASEGEN;
! 2462:
! 2463: vperm = cgetg(lg(vectbase), t_VECSMALL);
! 2464: subfb = subfactorbasegen(N,(long)min(lim,LIMC2), minsfb, vperm, &ss);
! 2465: if (!subfb) goto INCREASEGEN;
! 2466: lgsub = lg(subfb);
! 2467: ex = cgetg(lgsub,t_VECSMALL);
! 2468:
! 2469: PRECREGINT = DEFAULTPREC
! 2470: + ((expi(D)*(lgsub-2)+((N*N)>>2))>>TWOPOTBITS_IN_LONG);
! 2471: PRECREG = max(prec+1,PRECREGINT);
! 2472: KCCO = KC+RU-1 + max(ss,RELSUP);
! 2473: if (DEBUGLEVEL)
! 2474: {
! 2475: fprintferr("nbrelsup = %ld, ss = %ld, ",RELSUP,ss);
! 2476: fprintferr("KCZ = %ld, KC = %ld, KCCO = %ld \n",KCZ,KC,KCCO); flusherr();
! 2477: }
! 2478: mat=(long**)gpmalloc(sizeof(long*)*(KCCO+1));
! 2479: setlg(mat, KCCO+1);
! 2480: C = cgetg(KCCO+1,t_MAT);
! 2481: cmptglob=0;
! 2482: /* trivial relations */
! 2483: for (i=1; i<=KCZ; i++)
! 2484: {
! 2485: GEN P = idealbase[i];
! 2486: if (isclone(P))
! 2487: { /* all prime divisors in factorbase */
! 2488: unsetisclone(P); cmptglob++;
! 2489: mat[cmptglob] = p1 = col_0(KC);
! 2490: C[cmptglob] = (long)(p2 = cgetg(RU+1,t_COL));
! 2491: k = numideal[factorbase[i]];
! 2492: p1[0] = k+1; p1 += k; /* for already_found_relation */
! 2493: k = lg(P);
! 2494: for (j=1; j<k; j++) p1[j] = itos(gmael(P,j,3));
! 2495: for (j=1; j<=RU; j++) p2[j] = zero;
! 2496: }
! 2497: }
! 2498: /* initialize for other relations */
! 2499: for (i=cmptglob+1; i<=KCCO; i++)
! 2500: {
! 2501: mat[i] = col_0(KC);
! 2502: C[i] = (long) (p1 = cgetg(RU+1,t_COL));
! 2503: for (j=1; j<=RU; j++)
! 2504: {
! 2505: p2=cgetg(3,t_COMPLEX);
! 2506: p2[1]=lgetr(PRECREG);
! 2507: p2[2]=lgetr(PRECREG); p1[j]=(long)p2;
! 2508: }
! 2509: }
! 2510: av1 = avma; liste = new_chunk(KC+1);
! 2511: for (i=1; i<=KC; i++) liste[i]=0;
! 2512: invp = cmptglob? relationrank(mat,KC,cmptglob,liste): idmat(KC);
! 2513:
! 2514: /* relations through elements of small norm */
! 2515: cmptglob = small_norm_for_buchall(cmptglob,mat,C,KCCO,(long)LIMC,
! 2516: PRECREG,nf,gborne,nbrelpid,invp,liste);
! 2517: if (cmptglob < 0)
! 2518: {
! 2519: for (j=1; j<=KCCO; j++) free(mat[j]); free(mat);
! 2520: prec=(PRECREG<<1)-2;
! 2521: if (DEBUGLEVEL) err(warnprec,"buchall (small_norm)",prec);
! 2522: avma = av0; nf = nfnewprec(nf,prec); av0 = avma;
! 2523: cbach /= 2;
! 2524: goto INCREASEGEN;
! 2525: }
! 2526: avma = av1; limpile=stack_lim(av1,1);
! 2527:
! 2528: slim = KCCO; phase = 0;
! 2529: nlze = matcopymax = 0; /* for lint */
! 2530: lmatt2 = NULL;
! 2531:
! 2532: /* random relations */
! 2533: if (cmptglob == KCCO) /* enough relations, initialize nevertheless */
! 2534: ((void(*)(long))random_relation)(-1);
! 2535: else
! 2536: {
! 2537: GEN maarch;
! 2538: long **ma;
! 2539:
! 2540: if (DEBUGLEVEL)
! 2541: { fprintferr("\n#### Looking for random relations\n"); flusherr(); }
! 2542: LABELINT:
! 2543: if (sfb_increase)
! 2544: { /* increase subfactorbase */
! 2545: sfb_increase = 0;
! 2546: if (++sfb_trials >= SFB_MAX) goto INCREASEGEN;
! 2547: subfb = subfactorbasegen(N, (long)min(lim,LIMC2),
! 2548: lgsub-1+SFB_STEP, NULL, &ss);
! 2549: if (!subfb) goto INCREASEGEN;
! 2550: if (DEBUGLEVEL) fprintferr("*** Increasing subfactorbase\n");
! 2551: powsubfb = NULL;
! 2552: nreldep = nrelsup = 0;
! 2553: lgsub = lg(subfb);
! 2554: }
! 2555:
! 2556: if (phase == 0) { ma = mat; maarch = C; }
! 2557: else /* reduced the relation matrix at least once */
! 2558: {
! 2559: extrarel = nlze;
! 2560: if (extrarel < MIN_EXTRA) extrarel = MIN_EXTRA;
! 2561: slim = cmptglob+extrarel;
! 2562: setlg(extraC,extrarel+1);
! 2563: setlg(extramat,extrarel+1);
! 2564: if (slim > matcopymax)
! 2565: {
! 2566: matcopy = (long**)gprealloc(matcopy, (2*slim+1) * sizeof(long*),
! 2567: (matcopymax+1) * sizeof(long*));
! 2568: matcopymax = 2 * slim;
! 2569: }
! 2570: setlg(matcopy,slim+1);
! 2571: if (DEBUGLEVEL)
! 2572: fprintferr("\n(need %ld more relation%s)\n",
! 2573: extrarel, (extrarel==1)?"":"s");
! 2574: for (j=cmptglob+1; j<=slim; j++) matcopy[j] = col_0(KC);
! 2575: maarch = extraC - cmptglob; /* start at 0, the others at cmptglob */
! 2576: ma = matcopy;
! 2577: }
! 2578: if (!lmatt2)
! 2579: {
! 2580: lmatt2 = compute_matt2(RU,nf);
! 2581: av1 = avma;
! 2582: }
! 2583: if (!powsubfb)
! 2584: {
! 2585: powsubfbgen(nf,subfb,CBUCHG+1,PRECREG,PRECREGINT);
! 2586: av1 = avma;
! 2587: }
! 2588: ss = random_relation(phase,cmptglob,slim,(long)LIMC,N,RU,PRECREG,
! 2589: PRECREGINT,nf,subfb,lmatt2,ma,maarch,ex,list_jideal);
! 2590: if (ss < 0) /* could not find relations */
! 2591: {
! 2592: if (phase == 0) { for (j=1; j<=KCCO; j++) free(mat[j]); free(mat); }
! 2593: if (ss != -1)
! 2594: { /* precision problems */
! 2595: prec=(PRECREG<<1)-2;
! 2596: if (DEBUGLEVEL) err(warnprec,"buchall (random_relation)",prec);
! 2597: avma = av0; nf = nfnewprec(nf,prec);
! 2598: av0 = avma; cbach /= 2;
! 2599: }
! 2600: goto INCREASEGEN;
! 2601: }
! 2602: if (DEBUGLEVEL > 2) dbg_outrel(phase,cmptglob,vperm,ma,maarch);
! 2603: if (phase)
! 2604: for (j=1; j<=extrarel; j++)
! 2605: {
! 2606: long *c = matcopy[cmptglob+j];
! 2607: GEN *g = (GEN*) extramat[j];
! 2608: for (k=1; k<=KC; k++) g[k] = stoi(c[vperm[k]]);
! 2609: }
! 2610: cmptglob = ss;
! 2611: }
! 2612:
! 2613: /* reduce relation matrices */
! 2614: if (phase == 0) /* never reduced before */
! 2615: {
! 2616: matcopymax = 10*KCCO + MAXRELSUP;
! 2617: matcopy = (long**)gpmalloc(sizeof(long*)*(matcopymax + 1));
! 2618: setlg(matcopy, KCCO+1);
! 2619: for (j=1; j<=KCCO; j++) matcopy[j] = col_dup(KC,mat[j]);
! 2620: W = hnfspec(mat,vperm,&pdep,&B,&C,lgsub-1);
! 2621: for (j=1; j<=KCCO; j++) free(mat[j]); free(mat);
! 2622: KCCOPRO = KCCO; phase = 1;
! 2623: /* keep some room for the extra relation. We will update matrix size when
! 2624: * extrarel goes down
! 2625: */
! 2626: nlze = lg(pdep)>1? lg(pdep[1])-1: lg(B[1])-1;
! 2627: if (nlze)
! 2628: {
! 2629: list_jideal = cgetg(nlze+1, t_VECSMALL);
! 2630: for (i=1; i<=nlze; i++) list_jideal[i] = vperm[i];
! 2631: }
! 2632: extrarel = nlze; /* in case the regulator is 0 */
! 2633: if (extrarel < MIN_EXTRA) extrarel = MIN_EXTRA;
! 2634: extramat =cgetg(extrarel+1,t_MAT);
! 2635: extraC=cgetg(extrarel+1,t_MAT);
! 2636: for (j=1; j<=extrarel; j++)
! 2637: {
! 2638: extramat[j]=lgetg(KC+1,t_COL);
! 2639: extraC[j]=lgetg(RU+1,t_COL);
! 2640: for (i=1; i<=RU; i++)
! 2641: {
! 2642: p1 = cgetg(3,t_COMPLEX); mael(extraC,j,i)=(long)p1;
! 2643: p1[1]=lgetr(PRECREG);
! 2644: p1[2]=lgetr(PRECREG);
! 2645: }
! 2646: }
! 2647: }
! 2648: else
! 2649: {
! 2650: list_jideal = NULL;
! 2651: if (low_stack(limpile, stack_lim(av1,1)))
! 2652: {
! 2653: GEN *gptr[6];
! 2654: if(DEBUGMEM>1) err(warnmem,"buchall");
! 2655: gptr[0]=&W; gptr[1]=&C; gptr[2]=&B; gptr[3]=&pdep;
! 2656: gptr[4]=&extramat; gptr[5]=&extraC;
! 2657: gerepilemany(av1,gptr,6);
! 2658: }
! 2659: W = hnfadd(W,vperm,&pdep,&B,&C, extramat,extraC);
! 2660: nlze = lg(pdep)>1? lg(pdep[1])-1: lg(B[1])-1;
! 2661: KCCOPRO += extrarel;
! 2662: if (nlze && ++nreldep > MAXRELSUP) { sfb_increase=1; goto LABELINT; }
! 2663: }
! 2664: if (nlze) goto LABELINT; /* dependent rows */
! 2665:
! 2666: /* first attempt at regulator for the check */
! 2667: sreg = KCCOPRO - (lg(B)-1) - (lg(W)-1); /* = zc (cf hnffinal) */
! 2668: xarch = cgetg(sreg+1,t_MAT); /* cols corresponding to units */
! 2669: for (j=1; j<=sreg; j++) xarch[j] = C[j];
! 2670: reg = compute_multiple_of_R(xarch,RU,N,PRECREG,&sublambda);
! 2671:
! 2672: if (!reg)
! 2673: { /* not full rank for units */
! 2674: if (DEBUGLEVEL) fprintferr("regulator is zero.\n");
! 2675: if (++nrelsup > MAXRELSUP) goto INCREASEGEN;
! 2676: nlze=MIN_EXTRA; goto LABELINT;
! 2677: }
! 2678: if (!sublambda)
! 2679: { /* anticipate precision problems */
! 2680: prec=(PRECREG<<1)-2;
! 2681: if (DEBUGLEVEL) err(warnprec,"buchall (bestappr)",prec);
! 2682: avma = av0; nf = nfnewprec(nf,prec);
! 2683: av0 = avma; cbach /= 2;
! 2684: goto INCREASEGEN;
! 2685: }
! 2686:
! 2687: /* class number */
! 2688: if (DEBUGLEVEL) fprintferr("\n");
! 2689: clh = compute_class_number(W,&met,&u1,&u2);
! 2690:
! 2691: /* check */
! 2692: z = mulrr(lfun,gmul(gmul2n(gpuigs(shiftr(mppi(DEFAULTPREC),1),-R2),-R1),
! 2693: gsqrt(absi(D),DEFAULTPREC)));
! 2694: z = mulri(z,(GEN)zu[1]);
! 2695: /* z = Res (zeta_K, s = 1) * w D^(1/2) / [ 2^r1 (2pi)^r2 ] = h R */
! 2696: p1 = gmul2n(divir(clh,z), 1);
! 2697: /* c1 should be close to 2, and not much smaller */
! 2698: c1 = compute_check(sublambda,p1,&parch,®);
! 2699: if (!c1 || gcmpgs(gmul2n(c1,1),3) < 0)
! 2700: { /* precision problems */
! 2701: prec=(PRECREG<<1)-2;
! 2702: if (DEBUGLEVEL) err(warnprec,"buchall (compute_check)",prec);
! 2703: avma = av0; nf = nfnewprec(nf,prec);
! 2704: av0 = avma; cbach /= 2;
! 2705: goto INCREASEGEN;
! 2706: }
! 2707: if (gcmpgs(c1,3) > 0)
! 2708: {
! 2709: if (++nrelsup <= MAXRELSUP)
! 2710: {
! 2711: if (DEBUGLEVEL)
! 2712: {
! 2713: fprintferr("\n ***** check = %f\n",gtodouble(c1)/2);
! 2714: flusherr();
! 2715: }
! 2716: nlze=MIN_EXTRA; goto LABELINT;
! 2717: }
! 2718: if (cbach<11.99) { sfb_increase=1; goto LABELINT; }
! 2719: err(warner,"suspicious check. Try to increase extra relations");
! 2720: }
! 2721:
! 2722: /* Phase "be honest" */
! 2723: if (KCZ2 > KCZ)
! 2724: {
! 2725: if (!powsubfb)
! 2726: powsubfbgen(nf,subfb,CBUCHG+1,PRECREG,PRECREGINT);
! 2727: if (!be_honest(nf,subfb,RU,PRECREGINT)) goto INCREASEGEN;
! 2728: }
! 2729:
! 2730: /* regulator, roots of unity, fundamental units */
! 2731: if (flun < 0 || flun > 1)
! 2732: {
! 2733: xarch = cleancol(gmul(xarch,parch),N,PRECREG);
! 2734: if (DEBUGLEVEL) msgtimer("cleancol");
! 2735: }
! 2736: if (labs(flun) > 1)
! 2737: {
! 2738: fu = getfu(nf,&xarch,reg,flun,&k,PRECREG);
! 2739: if (k) fu = gmul((GEN)nf[7],fu);
! 2740: else if (labs(flun) > 2)
! 2741: {
! 2742: prec=(PRECREG<<1)-2;
! 2743: if (DEBUGLEVEL) err(warnprec,"buchall (getfu)",prec);
! 2744: avma = av0; nf = nfnewprec(nf,prec);
! 2745: av0 = avma; cbach /= 2;
! 2746: goto INCREASEGEN;
! 2747: }
! 2748: }
! 2749:
! 2750: /* class group generators */
! 2751: if (DEBUGLEVEL) fprintferr("\n");
! 2752: class_group_gen(nf,met,clh,u1,u2,vperm, &clg1, &clg2, PRECREGINT);
! 2753:
! 2754: /* cleanup */
! 2755: desallocate(matcopy);
! 2756: i = lg(C)-sreg; C += sreg; C[0] = evaltyp(t_MAT)|evallg(i);
! 2757: C = cleancol(C,N,PRECREG);
! 2758: settyp(vperm, t_COL);
! 2759: for (i=1; i<=KC; i++) vperm[i]=lstoi(vperm[i]);
! 2760: c1 = gdiv(gmul(reg,clh),z);
! 2761:
! 2762: return gerepileupto(av, buchall_end(nf,CHANGE,flun,k,fu,clg1,clg2,reg,c1,zu,W,B,xarch,C,vectbase,vperm));
! 2763: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>