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