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