Annotation of OpenXM_contrib/pari-2.2/src/basemath/buch1.c, Revision 1.1.1.1
1.1 noro 1: /* $Id: buch1.c,v 1.33 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: /* QUADRATIC FIELDS */
20: /* */
21: /*******************************************************************/
22: #include "pari.h"
23:
24: const int narrow = 0; /* should set narrow = flag in buchquad, but buggy */
25:
26: /* See buch2.c:
27: * precision en digits decimaux=2*(#digits decimaux de Disc)+50
28: * on prendra les p decomposes tels que prod(p)>lim dans la subbase
29: * LIMC=Max(c.(log(Disc))^2,exp((1/8).sqrt(log(Disc).loglog(Disc))))
30: * LIMC2=Max(6.(log(Disc))^2,exp((1/8).sqrt(log(Disc).loglog(Disc))))
31: * subbase contient les p decomposes tels que prod(p)>sqrt(Disc)
32: * lgsub=subbase[0]=#subbase;
33: * subfactorbase est la table des form[p] pour p dans subbase
34: * nbram est le nombre de p divisant Disc elimines dans subbase
35: * powsubfactorbase est la table des puissances des formes dans subfactorbase
36: */
37: #define HASHT 1024 /* power of 2 */
38: static const long CBUCH = 15; /* of the form 2^k-1 */
39: static const long randshift=BITS_IN_RANDOM-1 - 4; /* BITS_IN_RANDOM-1-k */
40:
41: static long KC,KC2,lgsub,limhash,RELSUP,PRECREG;
42: static long *primfact,*primfact1, *exprimfact,*exprimfact1, *badprim;
43: static long *factorbase,*numfactorbase, *subbase, *vectbase, **hashtab;
44: static GEN **powsubfactorbase,vperm,subfactorbase,Disc,sqrtD,isqrtD;
45:
46: GEN buchquad(GEN D, double c, double c2, long RELSUP0, long flag, long prec);
47: extern GEN roots_to_pol_intern(GEN L, GEN a, long v, int plus);
48: extern GEN roots_to_pol(GEN L, long v);
49: extern GEN colreducemodmat(GEN x, GEN y, GEN *Q);
50:
51: GEN
52: quadclassunit0(GEN x, long flag, GEN data, long prec)
53: {
54: long lx,RELSUP0;
55: double cbach, cbach2;
56:
57: if (!data) lx=1;
58: else
59: {
60: lx = lg(data);
61: if (typ(data)!=t_VEC || lx > 7)
62: err(talker,"incorrect parameters in quadclassunit");
63: if (lx > 4) lx = 4;
64: }
65: cbach = cbach2 = 0.1; RELSUP0 = 5;
66: switch(lx)
67: {
68: case 4: RELSUP0 = itos((GEN)data[3]);
69: case 3: cbach2 = gtodouble((GEN)data[2]);
70: case 2: cbach = gtodouble((GEN)data[1]);
71: }
72: return buchquad(x,cbach,cbach2,RELSUP0,flag,prec);
73: }
74:
75: /*******************************************************************/
76: /* */
77: /* Hilbert and Ray Class field using CM (Schertz) */
78: /* */
79: /*******************************************************************/
80:
81: int
82: isoforder2(GEN form)
83: {
84: GEN a=(GEN)form[1],b=(GEN)form[2],c=(GEN)form[3];
85: return !signe(b) || absi_equal(a,b) || egalii(a,c);
86: }
87:
88: GEN
89: getallforms(GEN D, long *pth, GEN *ptz)
90: {
91: long d = itos(D), t, b2, a, b, c, h, dover3 = labs(d)/3;
92: GEN z, L=cgetg(labs(d), t_VEC);
93: b2 = b = (d&1); h = 0; z=gun;
94: while (b2 <= dover3)
95: {
96: t = (b2-d)/4;
97: for (a=b?b:1; a*a<=t; a++)
98: if (t%a == 0)
99: {
100: c = t/a; z = mulsi(a,z);
101: L[++h] = (long)qfi(stoi(a),stoi(b),stoi(c));
102: if (b && a != b && a*a != t)
103: L[++h] = (long)qfi(stoi(a),stoi(-b),stoi(c));
104: }
105: b+=2; b2=b*b;
106: }
107: *pth = h; *ptz = z; setlg(L,h+1); return L;
108: }
109:
110: #define MOD4(x) ((((GEN)x)[2])&3)
111: #define MAXL 300
112: /* find P and Q two non principal prime ideals (above p,q) such that
113: * (pq, z) = 1 [coprime to all class group representatives]
114: * cl(P) = cl(Q) if P has order 2 in Cl(K)
115: * Try to have e = 24 / gcd(24, (p-1)(q-1)) as small as possible */
116: void
117: get_pq(GEN D, GEN z, GEN flag, GEN *ptp, GEN *ptq)
118: {
119: GEN wp=cgetg(MAXL,t_VEC), wlf=cgetg(MAXL,t_VEC), court=icopy(gun);
120: GEN p, form;
121: long i, ell, l = 1, d = itos(D);
122: byteptr diffell = diffptr + 2;
123:
124: if (typ(flag)==t_VEC)
125: { /* assume flag = [p,q]. Check nevertheless */
126: for (i=1; i<lg(flag); i++)
127: {
128: ell = itos((GEN)flag[i]);
129: if (smodis(z,ell) && kross(d,ell) > 0)
130: {
131: form = redimag(primeform(D,(GEN)flag[i],0));
132: if (!gcmp1((GEN)form[1])) {
133: wp[l] = flag[i];
134: l++; if (l == 3) break;
135: }
136: }
137: }
138: if (l<3) err(talker,"[quadhilbert] incorrect values in flag: %Z", flag);
139: *ptp = (GEN)wp[1];
140: *ptq = (GEN)wp[2]; return;
141: }
142:
143: ell = 3;
144: while (l < 3 || ell<=MAXL)
145: {
146: ell += *diffell++; if (!*diffell) err(primer1);
147: if (smodis(z,ell) && kross(d,ell) > 0)
148: {
149: court[2]=ell; form = redimag(primeform(D,court,0));
150: if (!gcmp1((GEN)form[1])) {
151: wp[l] = licopy(court);
152: wlf[l] = (long)form; l++;
153: }
154: }
155: }
156: setlg(wp,l); setlg(wlf,l);
157:
158: for (i=1; i<l; i++)
159: if (smodis((GEN)wp[i],3) == 1) break;
160: if (i==l) i = 1;
161: p = (GEN)wp[i]; form = (GEN)wlf[i];
162: i = l;
163: if (isoforder2(form))
164: {
165: long oki = 0;
166: for (i=1; i<l; i++)
167: if (gegal((GEN)wlf[i],form))
168: {
169: if (MOD4(p) == 1 || MOD4(wp[i]) == 1) break;
170: if (!oki) oki = i; /* not too bad, still e = 2 */
171: }
172: if (i==l) i = oki;
173: if (!i) err(bugparier,"quadhilbertimag (can't find p,q)");
174: }
175: else
176: {
177: if (MOD4(p) == 3)
178: {
179: for (i=1; i<l; i++)
180: if (MOD4(wp[i]) == 1) break;
181: }
182: if (i==l) i = 1;
183: }
184: *ptp = p;
185: *ptq = (GEN)wp[i];
186: }
187: #undef MAXL
188:
189: static GEN
190: gpq(GEN form, GEN p, GEN q, long e, GEN sqd, GEN u, long prec)
191: {
192: GEN a2 = shifti((GEN)form[1], 1);
193: GEN b = (GEN)form[2], p1,p2,p3,p4;
194: GEN w = lift(chinois(gmodulcp(negi(b),a2), u));
195: GEN al = cgetg(3,t_COMPLEX);
196: al[1] = lneg(gdiv(w,a2));
197: al[2] = ldiv(sqd,a2);
198: p1 = trueeta(gdiv(al,p),prec);
199: p2 = egalii(p,q)? p1: trueeta(gdiv(al,q),prec);
200: p3 = trueeta(gdiv(al,mulii(p,q)),prec);
201: p4 = trueeta(al,prec);
202: return gpowgs(gdiv(gmul(p1,p2),gmul(p3,p4)), e);
203: }
204:
205: /* returns an equation for the Hilbert class field of the imaginary
206: * quadratic field of discriminant D if flag=0, a vector of
207: * two-component vectors [form,g(form)] where g() is the root of the equation
208: * if flag is non-zero.
209: */
210: static GEN
211: quadhilbertimag(GEN D, GEN flag)
212: {
213: long av=avma,h,i,e,prec;
214: GEN z,L,P,p,q,qfp,qfq,up,uq,u;
215: int raw = ((typ(flag)==t_INT && signe(flag)));
216:
217: if (DEBUGLEVEL>=2) timer2();
218: if (gcmpgs(D,-11) >= 0) return polx[0];
219: L = getallforms(D,&h,&z);
220: if (DEBUGLEVEL>=2) msgtimer("class number = %ld",h);
221: if (h == 1) { avma=av; return polx[0]; }
222:
223: get_pq(D, z, flag, &p, &q);
224: e = 24 / cgcd((smodis(p,24)-1) * (smodis(q,24)-1), 24);
225: if(DEBUGLEVEL>=2) fprintferr("p = %Z, q = %Z, e = %ld\n",p,q,e);
226: qfp = primeform(D,p,0); up = gmodulcp((GEN)qfp[2],shifti(p,1));
227: if (egalii(p,q))
228: {
229: u = (GEN)compimagraw(qfp,qfp)[2];
230: u = gmodulcp(u, shifti(mulii(p,q),1));
231: }
232: else
233: {
234: qfq = primeform(D,q,0); uq = gmodulcp((GEN)qfq[2],shifti(q,1));
235: u = chinois(up,uq);
236: }
237: prec = raw? DEFAULTPREC: 3;
238: for(;;)
239: {
240: long av0 = avma, ex, exmax = 0;
241: GEN lead, sqd = gsqrt(negi(D),prec);
242: P = cgetg(h+1,t_VEC);
243: for (i=1; i<=h; i++)
244: {
245: GEN v, s = gpq((GEN)L[i], p, q, e, sqd, u, prec);
246: if (raw)
247: {
248: v = cgetg(3,t_VEC); P[i] = (long)v;
249: v[1] = L[i];
250: v[2] = (long)s;
251: }
252: else P[i] = (long)s;
253: ex = gexpo(s); if (ex > 0) exmax += ex;
254: }
255: if (DEBUGLEVEL>=2) msgtimer("roots");
256: if (raw) { P = gcopy(P); break; }
257: /* to avoid integer overflow (1 + 0.) */
258: lead = (exmax < bit_accuracy(prec))? gun: realun(prec);
259:
260: P = greal(roots_to_pol_intern(lead,P,0,0));
261: P = grndtoi(P,&exmax);
262: if (DEBUGLEVEL>=2) msgtimer("product, error bits = %ld",exmax);
263: if (exmax <= -10)
264: {
265: if (typ(flag)==t_VEC && !issquarefree(P)) { avma=av; return gzero; }
266: break;
267: }
268: avma = av0; prec += (DEFAULTPREC-2) + (1 + (exmax >> TWOPOTBITS_IN_LONG));
269: if (DEBUGLEVEL) err(warnprec,"quadhilbertimag",prec);
270: }
271: return gerepileupto(av,P);
272: }
273:
274: GEN quadhilbertreal(GEN D, GEN flag, long prec);
275:
276: GEN
277: quadhilbert(GEN D, GEN flag, long prec)
278: {
279: if (!flag) flag = gzero;
280: if (typ(D)!=t_INT)
281: {
282: D = checkbnf(D);
283: if (degpol(gmael(D,7,1)) != 2)
284: err(talker,"not a polynomial of degree 2 in quadhilbert");
285: D=gmael(D,7,3);
286: }
287: else
288: {
289: if (!isfundamental(D))
290: err(talker,"quadhilbert needs a fundamental discriminant");
291: }
292: return (signe(D)>0)? quadhilbertreal(D,flag,prec)
293: : quadhilbertimag(D,flag);
294: }
295:
296: /* AUXILLIARY ROUTINES FOR QUADRAYIMAGWEI */
297: #define to_approx(nf,a) ((GEN)gmul(gmael((nf),5,1), (a))[1])
298:
299: /* Z-basis for a (over C) */
300: static GEN
301: get_om(GEN nf, GEN a)
302: {
303: GEN om = cgetg(3,t_VEC);
304: om[1] = (long)to_approx(nf,(GEN)a[2]);
305: om[2] = (long)to_approx(nf,(GEN)a[1]);
306: return om;
307: }
308:
309: /* Compute all elts in class group G = [|G|,c,g], c=cyclic factors, g=gens.
310: * Set list[j + 1] = g1^e1...gk^ek where j is the integer
311: * ek + ck [ e(k-1) + c(k-1) [... + c2 [e1]]...] */
312: static GEN
313: getallelts(GEN nf, GEN G)
314: {
315: GEN C,c,g, *list, **pows, *gk;
316: long lc,i,j,k,no;
317:
318: no = itos((GEN)G[1]);
319: c = (GEN)G[2];
320: g = (GEN)G[3]; lc = lg(c)-1;
321: list = (GEN*) cgetg(no+1,t_VEC);
322: if (!lc)
323: {
324: list[1] = idealhermite(nf,gun);
325: return (GEN)list;
326: }
327: pows = (GEN**)cgetg(lc+1,t_VEC);
328: c = dummycopy(c); settyp(c, t_VECSMALL);
329: for (i=1; i<=lc; i++)
330: {
331: c[i] = k = itos((GEN)c[i]);
332: gk = (GEN*)cgetg(k, t_VEC); gk[1] = (GEN)g[i];
333: for (j=2; j<k; j++) gk[j] = idealmul(nf, gk[j-1], gk[1]);
334: pows[i] = gk; /* powers of g[i] */
335: }
336:
337: C = cgetg(lc+1, t_VECSMALL); C[1] = c[lc];
338: for (i=2; i<=lc; i++) C[i] = C[i-1] * c[lc-i+1];
339: /* C[i] = c(k-i+1) * ... * ck */
340: /* j < C[i+1] <==> j only involves g(k-i)...gk */
341: i = 1; list[1] = 0; /* dummy */
342: for (j=1; j < C[1]; j++)
343: list[j + 1] = pows[lc][j];
344: for ( ; j<no; j++)
345: {
346: GEN p1,p2;
347: if (j == C[i+1]) i++;
348: p2 = pows[lc-i][j/C[i]];
349: p1 = list[j%C[i] + 1]; if (p1) p2 = idealmul(nf,p2,p1);
350: list[j + 1] = p2;
351: }
352: list[1] = idealhermite(nf,gun);
353: return (GEN)list;
354: }
355:
356: /* x quadratic integer (approximate), recognize it. If error return NULL */
357: static GEN
358: findbezk(GEN nf, GEN x)
359: {
360: GEN a,b, M = gmael(nf,5,1), y = cgetg(3, t_COL), u = gcoeff(M,1,2);
361: long ea,eb;
362:
363: b = grndtoi(gdiv(gimag(x), gimag(u)), &eb);
364: a = grndtoi(greal(gsub(x, gmul(b,u))),&ea);
365: if (ea>-20 || eb>-20) return NULL;
366: if (!signe(b)) return a;
367: y[1] = (long)a;
368: y[2] = (long)b; return basistoalg(nf,y);
369: }
370:
371: static GEN
372: findbezk_pol(GEN nf, GEN x)
373: {
374: long i, lx = lgef(x);
375: GEN y = cgetg(lx,t_POL);
376: for (i=2; i<lx; i++)
377: if (! (y[i] = (long)findbezk(nf,(GEN)x[i])) ) return NULL;
378: y[1] = x[1]; return y;
379: }
380:
381: GEN
382: form_to_ideal(GEN x)
383: {
384: long tx = typ(x);
385: GEN b,c, y = cgetg(3, t_MAT);
386: if (tx != t_QFR && tx != t_QFI) err(typeer,"form_to_ideal");
387: c = cgetg(3,t_COL); y[1] = (long)c;
388: c[1] = x[1]; c[2] = zero;
389: c = cgetg(3,t_COL); y[2] = (long)c;
390: b = negi((GEN)x[2]);
391: if (mpodd(b)) b = addis(b,1);
392: c[1] = lshifti(b,-1); c[2] = un; return y;
393: }
394:
395: /* P as output by quadhilbertimag, convert forms to ideals */
396: static void
397: convert_to_id(GEN P)
398: {
399: long i,l = lg(P);
400: for (i=1; i<l; i++)
401: {
402: GEN p1 = (GEN)P[i];
403: p1[1] = (long)form_to_ideal((GEN)p1[1]);
404: }
405: }
406:
407: /* P approximation computed at initial precision prec. Compute needed prec
408: * to know P with 1 word worth of trailing decimals */
409: static long
410: get_prec(GEN P, long prec)
411: {
412: long k = gprecision(P);
413: if (k == 3) return (prec<<1)-2; /* approximation not trustworthy */
414: k = prec - k; /* lost precision when computing P */
415: if (k < 0) k = 0;
416: k += MEDDEFAULTPREC + (gexpo(P) >> TWOPOTBITS_IN_LONG);
417: if (k <= prec) k = (prec<<1)-2; /* dubious: old prec should have worked */
418: return k;
419: }
420:
421: /* AUXILLIARY ROUTINES FOR QUADRAYSIGMA */
422: GEN
423: PiI2(long prec)
424: {
425: GEN z = cgetg(3,t_COMPLEX);
426: GEN x = mppi(prec); setexpo(x,2);
427: z[1] = zero;
428: z[2] = (long)x; return z; /* = 2I Pi */
429: }
430:
431: /* Compute data for ellphist */
432: static GEN
433: ellphistinit(GEN om, long prec)
434: {
435: GEN p1,res,om1b,om2b, om1 = (GEN)om[1], om2 = (GEN)om[2];
436:
437: if (gsigne(gimag(gdiv(om1,om2))) < 0)
438: {
439: p1=om1; om1=om2; om2=p1;
440: p1=cgetg(3,t_VEC); p1[1]=(long)om1; p1[2]=(long)om2;
441: om = p1;
442: }
443: om1b = gconj(om1);
444: om2b = gconj(om2); res = cgetg(4,t_VEC);
445: res[1] = ldivgs(elleisnum(om,2,0,prec),12);
446: res[2] = ldiv(PiI2(prec), gmul(om2, gimag(gmul(om1b,om2))));
447: res[3] = (long)om2b; return res;
448: }
449:
450: /* Computes log(phi^*(z,om)), using res computed by ellphistinit */
451: static GEN
452: ellphist(GEN om, GEN res, GEN z, long prec)
453: {
454: GEN u = gimag(gmul(z, (GEN)res[3]));
455: GEN zst = gsub(gmul(u, (GEN)res[2]), gmul(z,(GEN)res[1]));
456: return gsub(ellsigma(om,z,1,prec),gmul2n(gmul(z,zst),-1));
457: }
458:
459: /* Computes phi^*(la,om)/phi^*(1,om) where (1,om) is an oriented basis of the
460: ideal gf*gc^{-1} */
461: static GEN
462: computeth2(GEN om, GEN la, long prec)
463: {
464: GEN p1,p2,res = ellphistinit(om,prec);
465:
466: p1 = gsub(ellphist(om,res,la,prec), ellphist(om,res,gun,prec));
467: p2 = gimag(p1);
468: if (gexpo(greal(p1))>20 || gexpo(p2)> bit_accuracy(min(prec,lg(p2)))-10)
469: return NULL;
470: return gexp(p1,prec);
471: }
472:
473: /* Computes P_2(X)=polynomial in Z_K[X] closest to prod_gc(X-th2(gc)) where
474: the product is over the ray class group bnr.*/
475: static GEN
476: computeP2(GEN bnr, GEN la, int raw, long prec)
477: {
478: long av=avma, av2, clrayno,i, first = 1;
479: GEN listray,P0,P,f,lanum, nf = checknf(bnr);
480:
481: f = gmael3(bnr,2,1,1);
482: if (typ(la) != t_COL) la = algtobasis(nf,la);
483: listray = getallelts(nf,(GEN)bnr[5]);
484: clrayno = lg(listray)-1; av2 = avma;
485: PRECPB:
486: if (!first)
487: {
488: if (DEBUGLEVEL) err(warnprec,"computeP2",prec);
489: nf = gerepileupto(av2, nfnewprec(checknf(bnr),prec));
490: }
491: first = 0; lanum = to_approx(nf,la);
492: P = cgetg(clrayno+1,t_VEC);
493: for (i=1; i<=clrayno; i++)
494: {
495: GEN om = get_om(nf, idealdiv(nf,f,(GEN)listray[i]));
496: GEN v, s = computeth2(om,lanum,prec);
497: if (!s) { prec = (prec<<1)-2; goto PRECPB; }
498: if (raw)
499: {
500: v = cgetg(3,t_VEC); P[i] = (long)v;
501: v[1] = (long)listray[i];
502: v[2] = (long)s;
503: }
504: else P[i] = (long)s;
505: }
506: if (!raw)
507: {
508: P0 = roots_to_pol(P, 0);
509: P = findbezk_pol(nf, P0);
510: if (!P) { prec = get_prec(P0, prec); goto PRECPB; }
511: }
512: return gerepilecopy(av, P);
513: }
514:
515: #define nexta(a) (a>0 ? -a : 1-a)
516: static GEN
517: do_compo(GEN x, GEN y)
518: {
519: long a, ph = degpol(y);
520: GEN z;
521: y = gmul(gpuigs(polx[0],ph), gsubst(y,0,gdiv(polx[MAXVARN],polx[0])));
522: for (a = 0;; a = nexta(a))
523: {
524: if (a) x = gsubst(x, 0, gaddsg(a, polx[0]));
525: z = subres(x,y);
526: z = gsubst(z, MAXVARN, polx[0]);
527: if (issquarefree(z)) return z;
528: }
529: }
530: #undef nexta
531:
532: static GEN
533: galoisapplypol(GEN nf, GEN s, GEN x)
534: {
535: long i, lx = lg(x);
536: GEN y = cgetg(lx,t_POL);
537:
538: for (i=2; i<lx; i++) y[i] = (long)galoisapply(nf,s,(GEN)x[i]);
539: y[1] = x[1]; return y;
540: }
541:
542: /* x quadratic, write it as ua + v, u,v rational */
543: static GEN
544: findquad(GEN a, GEN x, GEN p)
545: {
546: long tu,tv, av = avma;
547: GEN u,v;
548: if (typ(x) == t_POLMOD) x = (GEN)x[2];
549: if (typ(a) == t_POLMOD) a = (GEN)a[2];
550: u = poldivres(x, a, &v);
551: u = simplify(u); tu = typ(u);
552: v = simplify(v); tv = typ(v);
553: if (!is_scalar_t(tu) || !is_scalar_t(tv))
554: err(talker, "incorrect data in findquad");
555: x = v;
556: if (!gcmp0(u)) x = gadd(gmul(u, polx[varn(a)]), x);
557: if (typ(x) == t_POL) x = gmodulcp(x,p);
558: return gerepileupto(av, x);
559: }
560:
561: static GEN
562: findquad_pol(GEN nf, GEN a, GEN x)
563: {
564: long i, lx = lg(x);
565: GEN p = (GEN)nf[1], y = cgetg(lx,t_POL);
566: for (i=2; i<lx; i++) y[i] = (long)findquad(a, (GEN)x[i], p);
567: y[1] = x[1]; return y;
568: }
569:
570: static GEN
571: compocyclo(GEN nf, long m, long d, long prec)
572: {
573: GEN sb,a,b,s,p1,p2,p3,res,polL,polLK,nfL, D = (GEN)nf[3];
574: long ell,vx;
575:
576: p1 = quadhilbertimag(D, gzero);
577: p2 = cyclo(m,0);
578: if (d==1) return do_compo(p1,p2);
579:
580: ell = m&1 ? m : (m>>2);
581: if (!cmpsi(-ell,D)) /* ell = |D| */
582: {
583: p2 = gcoeff(nffactor(nf,p2),1,1);
584: return do_compo(p1,p2);
585: }
586: if (ell%4 == 3) ell = -ell;
587: /* nf = K = Q(a), L = K(b) quadratic extension = Q(t) */
588: polLK = quadpoly(stoi(ell)); /* relative polynomial */
589: res = rnfequation2(nf, polLK);
590: vx = varn(nf[1]);
591: polL = gsubst((GEN)res[1],0,polx[vx]); /* = charpoly(t) */
592: a = gsubst(lift((GEN)res[2]), 0,polx[vx]);
593: b = gsub(polx[vx], gmul((GEN)res[3], a));
594: nfL = initalg(polL,prec);
595: p1 = gcoeff(nffactor(nfL,p1),1,1);
596: p2 = gcoeff(nffactor(nfL,p2),1,1);
597: p3 = do_compo(p1,p2); /* relative equation over L */
598: /* compute non trivial s in Gal(L / K) */
599: sb= gneg(gadd(b, truecoeff(polLK,1))); /* s(b) = Tr(b) - b */
600: s = gadd(polx[vx], gsub(sb, b)); /* s(t) = t + s(b) - b */
601: p3 = gmul(p3, galoisapplypol(nfL, s, p3));
602: return findquad_pol(nf, a, p3);
603: }
604:
605: /* I integral ideal in HNF. (x) = I, x small in Z ? */
606: static long
607: isZ(GEN I)
608: {
609: GEN x = gcoeff(I,1,1);
610: if (signe(gcoeff(I,1,2)) || !egalii(x, gcoeff(I,2,2))) return 0;
611: return is_bigint(x)? -1: itos(x);
612: }
613:
614: /* Treat special cases directly. return NULL if not special case */
615: static GEN
616: treatspecialsigma(GEN nf, GEN gf, int raw, long prec)
617: {
618: GEN p1,p2,tryf, D = (GEN)nf[3];
619: long Ds,fl,i;
620:
621: if (raw)
622: err(talker,"special case in Schertz's theorem. Odd flag meaningless");
623: i = isZ(gf);
624: if (cmpis(D,-3)==0)
625: {
626: if (i == 4 || i == 5 || i == 7) return cyclo(i,0);
627: if (cmpis(gcoeff(gf,1,1), 9) || cmpis(content(gf),3)) return NULL;
628: p1 = (GEN)nfroots(nf,cyclo(3,0))[1]; /* f = P_3^3 */
629: return gadd(gpowgs(polx[0],3), p1); /* x^3+j */
630: }
631: if (cmpis(D,-4)==0)
632: {
633: if (i == 3 || i == 5) return cyclo(i,0);
634: if (i != 4) return NULL;
635: p1 = (GEN)nfroots(nf,cyclo(4,0))[1];
636: return gadd(gpowgs(polx[0],2), p1); /* x^2+i */
637: }
638: Ds = smodis(D,48);
639: if (i)
640: {
641: if (i==2 && Ds%16== 8) return compocyclo(nf, 4,1,prec);
642: if (i==3 && Ds% 3== 1) return compocyclo(nf, 3,1,prec);
643: if (i==4 && Ds% 8== 1) return compocyclo(nf, 4,1,prec);
644: if (i==6 && Ds ==40) return compocyclo(nf,12,1,prec);
645: return NULL;
646: }
647:
648: p1 = gcoeff(gf,1,1);
649: p2 = gcoeff(gf,2,2);
650: if (gcmp1(p2)) { fl = 0; tryf = p1; }
651: else {
652: if (Ds % 16 != 8 || !egalii(content(gf),gdeux)) return NULL;
653: fl = 1; tryf = shifti(p1,-1);
654: }
655: if (cmpis(tryf, 3) <= 0 || !gcmp0(resii(D, tryf)) || !isprime(tryf))
656: return NULL;
657:
658: i = itos(tryf); if (fl) i *= 4;
659: return compocyclo(nf,i,2,prec);
660: }
661:
662: static GEN
663: getallrootsof1(GEN bnf)
664: {
665: GEN z, u, nf = checknf(bnf), racunit = gmael3(bnf,8,4,2);
666: long i, n = itos(gmael3(bnf,8,4,1));
667:
668: u = cgetg(n+1, t_VEC);
669: z = basistoalg(nf, racunit);
670: for (i=1; ; i++)
671: {
672: u[i] = (long)algtobasis(nf,z);
673: if (i == n) return u;
674: z = gmul(z, racunit);
675: }
676: }
677:
678: /* Compute ray class field polynomial using sigma; if raw=1, pairs
679: [ideals,roots] are given instead so that congruence subgroups can be used */
680: static GEN
681: quadrayimagsigma(GEN bnr, int raw, long prec)
682: {
683: GEN allf,bnf,nf,pol,w,f,la,P,labas,lamodf,u;
684: long a,b,f2,i,lu;
685:
686: allf = conductor(bnr,gzero,2); bnr = (GEN)allf[2];
687: f = gmael(allf,1,1);
688: bnf= (GEN)bnr[1];
689: nf = (GEN)bnf[7];
690: pol= (GEN)nf[1];
691: if (gcmp1(gcoeff(f,1,1))) /* f = 1 ? */
692: {
693: P = quadhilbertimag((GEN)nf[3], stoi(raw));
694: if (raw) convert_to_id(P);
695: return gcopy(P);
696: }
697: P = treatspecialsigma(nf,f,raw,prec);
698: if (P) return P;
699:
700: w = gmodulcp(polx[varn(pol)], pol);
701: f2 = 2 * itos(gcoeff(f,1,1));
702: u = getallrootsof1(bnf); lu = lg(u);
703: for (i=1; i<lu; i++)
704: u[i] = (long)colreducemodmat((GEN)u[i], f, NULL); /* roots of 1, mod f */
705: if (DEBUGLEVEL>1)
706: fprintferr("quadray: looking for [a,b] != unit mod 2f\n[a,b] = ");
707: for (a=0; a<f2; a++)
708: for (b=0; b<f2; b++)
709: {
710: la = gaddgs(gmulsg(a,w),b);
711: if (smodis(gnorm(la), f2) != 1) continue;
712: if (DEBUGLEVEL>1) fprintferr("[%ld,%ld] ",a,b);
713:
714: labas = algtobasis(nf, la);
715: lamodf = colreducemodmat(labas, f, NULL);
716: for (i=1; i<lu; i++)
717: if (gegal(lamodf, (GEN)u[i])) break;
718: if (i < lu) continue; /* la = unit mod f */
719: if (DEBUGLEVEL)
720: {
721: if (DEBUGLEVEL>1) fprintferr("\n");
722: fprintferr("lambda = %Z\n",la);
723: }
724: return computeP2(bnr,labas,raw,prec);
725: }
726: err(bugparier,"quadrayimagsigma");
727: return NULL;
728: }
729:
730: GEN
731: quadray(GEN D, GEN f, GEN flag, long prec)
732: {
733: GEN bnr,y,p1,pol,bnf,lambda;
734: long av = avma, raw;
735:
736: if (!flag) flag = gzero;
737: if (typ(flag)==t_INT) lambda = NULL;
738: else
739: {
740: if (typ(flag)!=t_VEC || lg(flag)!=3) err(flagerr,"quadray");
741: lambda = (GEN)flag[1]; flag = (GEN)flag[2];
742: if (typ(flag)!=t_INT) err(flagerr,"quadray");
743: }
744: if (typ(D)!=t_INT)
745: {
746: bnf = checkbnf(D);
747: if (degpol(gmael(bnf,7,1)) != 2)
748: err(talker,"not a polynomial of degree 2 in quadray");
749: D=gmael(bnf,7,3);
750: }
751: else
752: {
753: if (!isfundamental(D))
754: err(talker,"quadray needs a fundamental discriminant");
755: pol = quadpoly(D); setvarn(pol, fetch_user_var("y"));
756: bnf = bnfinit0(pol,signe(D)>0?1:0,NULL,prec);
757: }
758: raw = (mpodd(flag) && signe(D) < 0);
759: bnr = bnrinit0(bnf,f,1);
760: if (gcmp1(gmael(bnr,5,1)))
761: {
762: avma = av; if (!raw) return polx[0];
763: y = cgetg(2,t_VEC); p1 = cgetg(3,t_VEC); y[1] = (long)p1;
764: p1[1]=(long)idmat(2);
765: p1[2]=(long)polx[0]; return y;
766: }
767: if (signe(D) > 0)
768: y = bnrstark(bnr,gzero, gcmp0(flag)?1:5, prec);
769: else
770: {
771: if (lambda)
772: y = computeP2(bnr,lambda,raw,prec);
773: else
774: y = quadrayimagsigma(bnr,raw,prec);
775: }
776: return gerepileupto(av, y);
777: }
778:
779: /*******************************************************************/
780: /* */
781: /* Routines related to binary quadratic forms (for internal use) */
782: /* */
783: /*******************************************************************/
784: extern void comp_gen(GEN z,GEN x,GEN y);
785: extern GEN codeform5(GEN x, long prec);
786: extern GEN comprealform5(GEN x, GEN y, GEN D, GEN sqrtD, GEN isqrtD);
787: extern GEN redrealform5(GEN x, GEN D, GEN sqrtD, GEN isqrtD);
788: extern GEN rhoreal_aux(GEN x, GEN D, GEN sqrtD, GEN isqrtD);
789:
790: #define rhorealform(x) rhoreal_aux(x,Disc,sqrtD,isqrtD)
791: #define redrealform(x) gcopy(fix_signs(redrealform5(x,Disc,sqrtD,isqrtD)))
792: #define comprealform(x,y) fix_signs(comprealform5(x,y,Disc,sqrtD,isqrtD))
793:
794: /* compute rho^n(x) */
795: static GEN
796: rhoreal_pow(GEN x, long n)
797: {
798: long i, av = avma, lim = stack_lim(av,1);
799: for (i=1; i<=n; i++)
800: {
801: x = rhorealform(x);
802: if (low_stack(lim, stack_lim(av,1)))
803: {
804: if(DEBUGMEM>1) err(warnmem,"rhoreal_pow");
805: x = gerepilecopy(av, x);
806: }
807: }
808: return gerepilecopy(av, x);
809: }
810:
811: static GEN
812: fix_signs(GEN x)
813: {
814: GEN a = (GEN)x[1];
815: GEN c = (GEN)x[3];
816: if (signe(a) < 0)
817: {
818: if (narrow || absi_equal(a,c)) return rhorealform(x);
819: setsigne(a,1); setsigne(c,-1);
820: }
821: return x;
822: }
823:
824: static GEN
825: redrealprimeform5(GEN Disc, long p)
826: {
827: long av = avma;
828: GEN y = primeform(Disc,stoi(p),PRECREG);
829: y = codeform5(y,PRECREG);
830: return gerepileupto(av, redrealform(y));
831: }
832:
833: static GEN
834: redrealprimeform(GEN Disc, long p)
835: {
836: long av = avma;
837: GEN y = primeform(Disc,stoi(p),PRECREG);
838: return gerepileupto(av, redrealform(y));
839: }
840:
841: static GEN
842: comprealform3(GEN x, GEN y)
843: {
844: long av = avma;
845: GEN z = cgetg(4,t_VEC); comp_gen(z,x,y);
846: return gerepileupto(av, redrealform(z));
847: }
848:
849: static GEN
850: initrealform5(long *ex)
851: {
852: GEN form = powsubfactorbase[1][ex[1]];
853: long i;
854:
855: for (i=2; i<=lgsub; i++)
856: form = comprealform(form, powsubfactorbase[i][ex[i]]);
857: return form;
858: }
859:
860: /*******************************************************************/
861: /* */
862: /* Common subroutines */
863: /* */
864: /*******************************************************************/
865: static void
866: buch_init(void)
867: {
868: if (DEBUGLEVEL) timer2();
869: primfact = new_chunk(100);
870: primfact1 = new_chunk(100);
871: exprimfact = new_chunk(100);
872: exprimfact1 = new_chunk(100);
873: badprim = new_chunk(100);
874: hashtab = (long**) new_chunk(HASHT);
875: }
876:
877: double
878: check_bach(double cbach, double B)
879: {
880: if (cbach >= B)
881: err(talker,"sorry, buchxxx couldn't deal with this field PLEASE REPORT!");
882: cbach *= 2; if (cbach > B) cbach = B;
883: if (DEBUGLEVEL) fprintferr("\n*** Bach constant: %f\n", cbach);
884: return cbach;
885: }
886:
887: static long
888: factorisequad(GEN f, long kcz, long limp)
889: {
890: long i,p,k,av,lo;
891: GEN q,r, x = (GEN)f[1];
892:
893: if (is_pm1(x)) { primfact[0]=0; return 1; }
894: av=avma; lo=0;
895: if (signe(x) < 0) x = absi(x);
896: for (i=1; ; i++)
897: {
898: p=factorbase[i]; q=dvmdis(x,p,&r);
899: if (!signe(r))
900: {
901: k=0; while (!signe(r)) { x=q; k++; q=dvmdis(x,p,&r); }
902: lo++; primfact[lo]=p; exprimfact[lo]=k;
903: }
904: if (cmpis(q,p)<=0) break;
905: if (i==kcz) { avma=av; return 0; }
906: }
907: p = x[2]; avma=av;
908: /* p = itos(x) if lgefint(x)=3 */
909: if (lgefint(x)!=3 || p > limhash) return 0;
910:
911: if (p != 1 && p <= limp)
912: {
913: for (i=1; i<=badprim[0]; i++)
914: if (p % badprim[i] == 0) return 0;
915: lo++; primfact[lo]=p; exprimfact[lo]=1;
916: p = 1;
917: }
918: primfact[0]=lo; return p;
919: }
920:
921: /* q may not be prime, but check for a "large prime relation" involving q */
922: static long *
923: largeprime(long q, long *ex, long np, long nrho)
924: {
925: const long hashv = ((q & (2 * HASHT - 1)) - 1) >> 1;
926: long *pt, i;
927:
928: /* If q = 0 (2048), very slim chance of getting a relation.
929: * And hashtab[-1] is undefined anyway */
930: if (hashv < 0) return NULL;
931: for (pt = hashtab[hashv]; ; pt = (long*) pt[0])
932: {
933: if (!pt)
934: {
935: pt = (long*) gpmalloc((lgsub+4)<<TWOPOTBYTES_IN_LONG);
936: *pt++ = nrho; /* nrho = pt[-3] */
937: *pt++ = np; /* np = pt[-2] */
938: *pt++ = q; /* q = pt[-1] */
939: pt[0] = (long)hashtab[hashv];
940: for (i=1; i<=lgsub; i++) pt[i]=ex[i];
941: hashtab[hashv]=pt; return NULL;
942: }
943: if (pt[-1] == q) break;
944: }
945: for(i=1; i<=lgsub; i++)
946: if (pt[i] != ex[i]) return pt;
947: return (pt[-2]==np)? (GEN)NULL: pt;
948: }
949:
950: static long
951: badmod8(GEN x)
952: {
953: long r = mod8(x);
954: if (!r) return 1;
955: if (signe(Disc) < 0) r = 8-r;
956: return (r < 4);
957: }
958:
959: /* cree factorbase, numfactorbase, vectbase; affecte badprim */
960: static void
961: factorbasequad(GEN Disc, long n2, long n)
962: {
963: long i,p,bad, av = avma;
964: byteptr d=diffptr;
965:
966: numfactorbase = (long*) gpmalloc(sizeof(long)*(n2+1));
967: factorbase = (long*) gpmalloc(sizeof(long)*(n2+1));
968: KC=0; bad=0; i=0; p = *d++;
969: while (p<=n2)
970: {
971: switch(krogs(Disc,p))
972: {
973: case -1: break; /* inert */
974: case 0: /* ramified */
975: {
976: GEN p1 = divis(Disc,p);
977: if (smodis(p1,p) == 0)
978: if (p!=2 || badmod8(p1)) { badprim[++bad]=p; break; }
979: i++; numfactorbase[p]=i; factorbase[i] = -p; break;
980: }
981: default: /* split */
982: i++; numfactorbase[p]=i; factorbase[i] = p;
983: }
984: p += *d++; if (!*d) err(primer1);
985: if (KC == 0 && p>n) KC = i;
986: }
987: if (!KC) { free(factorbase); free(numfactorbase); return; }
988: KC2 = i;
989: vectbase = (long*) gpmalloc(sizeof(long)*(KC2+1));
990: for (i=1; i<=KC2; i++)
991: {
992: p = factorbase[i];
993: vectbase[i]=p; factorbase[i]=labs(p);
994: }
995: if (DEBUGLEVEL)
996: {
997: msgtimer("factor base");
998: if (DEBUGLEVEL>7)
999: {
1000: fprintferr("factorbase:\n");
1001: for (i=1; i<=KC; i++) fprintferr("%ld ",factorbase[i]);
1002: fprintferr("\n"); flusherr();
1003: }
1004: }
1005: avma=av; badprim[0] = bad;
1006: }
1007:
1008: /* cree vectbase and subfactorbase. Affecte lgsub */
1009: static long
1010: subfactorbasequad(double ll, long KC)
1011: {
1012: long i,j,k,nbidp,p,pro[100], ss;
1013: GEN y;
1014: double prod;
1015:
1016: i=0; ss=0; prod=1;
1017: for (j=1; j<=KC && prod<=ll; j++)
1018: {
1019: p = vectbase[j];
1020: if (p>0) { pro[++i]=p; prod*=p; vperm[i]=j; } else ss++;
1021: }
1022: if (prod<=ll) return -1;
1023: nbidp=i;
1024: for (k=1; k<j; k++)
1025: if (vectbase[k]<=0) vperm[++i]=k;
1026:
1027: y=cgetg(nbidp+1,t_COL);
1028: if (PRECREG) /* real */
1029: for (j=1; j<=nbidp; j++)
1030: y[j] = (long)redrealprimeform5(Disc, pro[j]);
1031: else
1032: for (j=1; j<=nbidp; j++) /* imaginary */
1033: y[j] = (long)primeform(Disc,stoi(pro[j]),0);
1034: subbase = (long*) gpmalloc(sizeof(long)*(nbidp+1));
1035: lgsub = nbidp; for (j=1; j<=lgsub; j++) subbase[j]=pro[j];
1036: if (DEBUGLEVEL>7)
1037: {
1038: fprintferr("subfactorbase: ");
1039: for (i=1; i<=lgsub; i++)
1040: { fprintferr("%ld: ",subbase[i]); outerr((GEN)y[i]); }
1041: fprintferr("\n"); flusherr();
1042: }
1043: subfactorbase = y; return ss;
1044: }
1045:
1046: static void
1047: powsubfact(long n, long a)
1048: {
1049: GEN unform, *y, **x = (GEN**) gpmalloc(sizeof(GEN*)*(n+1));
1050: long i,j;
1051:
1052: for (i=1; i<=n; i++)
1053: x[i] = (GEN*) gpmalloc(sizeof(GEN)*(a+1));
1054: if (PRECREG) /* real */
1055: {
1056: unform=cgetg(6,t_VEC);
1057: unform[1]=un;
1058: unform[2]=(mod2(Disc) == mod2(isqrtD))? (long)isqrtD: laddsi(-1,isqrtD);
1059: unform[3]=lshifti(subii(sqri((GEN)unform[2]),Disc),-2);
1060: unform[4]=zero;
1061: unform[5]=(long)realun(PRECREG);
1062: for (i=1; i<=n; i++)
1063: {
1064: y = x[i]; y[0] = unform;
1065: for (j=1; j<=a; j++)
1066: y[j] = comprealform(y[j-1],(GEN)subfactorbase[i]);
1067: }
1068: }
1069: else /* imaginary */
1070: {
1071: unform = primeform(Disc, gun, 0);
1072: for (i=1; i<=n; i++)
1073: {
1074: y = x[i]; y[0] = unform;
1075: for (j=1; j<=a; j++)
1076: y[j] = compimag(y[j-1],(GEN)subfactorbase[i]);
1077: }
1078: }
1079: if (DEBUGLEVEL) msgtimer("powsubfact");
1080: powsubfactorbase = x;
1081: }
1082:
1083: static void
1084: desalloc(long **mat)
1085: {
1086: long i,*p,*q;
1087:
1088: free(vectbase); free(factorbase); free(numfactorbase);
1089: if (mat)
1090: {
1091: free(subbase);
1092: for (i=1; i<lg(subfactorbase); i++) free(powsubfactorbase[i]);
1093: for (i=1; i<lg(mat); i++) free(mat[i]);
1094: free(mat); free(powsubfactorbase);
1095: for (i=1; i<HASHT; i++)
1096: for (p = hashtab[i]; p; p = q) { q=(long*)p[0]; free(p-3); }
1097: }
1098: }
1099:
1100: /* L-function */
1101: static GEN
1102: lfunc(GEN Disc)
1103: {
1104: long av=avma, p;
1105: GEN y=realun(DEFAULTPREC);
1106: byteptr d=diffptr;
1107:
1108: for(p = *d++; p<=30000; p += *d++)
1109: {
1110: if (!*d) err(primer1);
1111: y = mulsr(p, divrs(y, p-krogs(Disc,p)));
1112: }
1113: return gerepileupto(av,y);
1114: }
1115:
1116: #define comp(x,y) x? (PRECREG? compreal(x,y): compimag(x,y)): y
1117: static GEN
1118: get_clgp(GEN Disc, GEN W, GEN *ptmet, long prec)
1119: {
1120: GEN p1,p2,res,*init, u1u2=smith2(W), u1=(GEN)u1u2[1], met=(GEN)u1u2[3];
1121: long c,i,j, l = lg(met);
1122:
1123: u1 = reducemodmatrix(ginv(u1), W);
1124: for (c=1; c<l; c++)
1125: if (gcmp1(gcoeff(met,c,c))) break;
1126: if (DEBUGLEVEL) msgtimer("smith/class group");
1127: res=cgetg(c,t_VEC); init = (GEN*)cgetg(l,t_VEC);
1128: for (i=1; i<l; i++)
1129: init[i] = primeform(Disc,stoi(labs(vectbase[vperm[i]])),prec);
1130: for (j=1; j<c; j++)
1131: {
1132: p1 = NULL;
1133: for (i=1; i<l; i++)
1134: {
1135: p2 = gpui(init[i], gcoeff(u1,i,j), prec);
1136: p1 = comp(p1,p2);
1137: }
1138: res[j] = (long)p1;
1139: }
1140: if (DEBUGLEVEL) msgtimer("generators");
1141: *ptmet = met; return res;
1142: }
1143:
1144: static GEN
1145: extra_relations(long LIMC, long *ex, long nlze, GEN extramatc)
1146: {
1147: long av,fpc,p,ep,i,j,k,nlze2, *col, *colg, s = 0, extrarel = nlze+2;
1148: long MAXRELSUP = min(50,4*KC);
1149: GEN p1,form, extramat = cgetg(extrarel+1,t_MAT);
1150:
1151: if (DEBUGLEVEL)
1152: {
1153: fprintferr("looking for %ld extra relations\n",extrarel);
1154: flusherr();
1155: }
1156: for (j=1; j<=extrarel; j++) extramat[j]=lgetg(KC+1,t_COL);
1157: nlze2 = PRECREG? max(nlze,lgsub): min(nlze+1,KC);
1158: if (nlze2 < 3 && KC > 2) nlze2 = 3;
1159: av = avma;
1160: while (s<extrarel)
1161: {
1162: form = NULL;
1163: for (i=1; i<=nlze2; i++)
1164: {
1165: ex[i]=mymyrand()>>randshift;
1166: if (ex[i])
1167: {
1168: p1 = primeform(Disc,stoi(factorbase[vperm[i]]),PRECREG);
1169: p1 = gpuigs(p1,ex[i]); form = comp(form,p1);
1170: }
1171: }
1172: if (!form) continue;
1173:
1174: fpc = factorisequad(form,KC,LIMC);
1175: if (fpc==1)
1176: {
1177: s++; col = (GEN)extramat[s];
1178: for (i=1; i<=nlze2; i++) col[vperm[i]] = -ex[i];
1179: for ( ; i<=KC; i++) col[vperm[i]]= 0;
1180: for (j=1; j<=primfact[0]; j++)
1181: {
1182: p=primfact[j]; ep=exprimfact[j];
1183: if (smodis((GEN)form[2], p<<1) > p) ep = -ep;
1184: col[numfactorbase[p]] += ep;
1185: }
1186: for (i=1; i<=KC; i++)
1187: if (col[i]) break;
1188: if (i>KC)
1189: {
1190: s--; avma = av;
1191: if (--MAXRELSUP == 0) return NULL;
1192: }
1193: else { av = avma; if (PRECREG) coeff(extramatc,1,s) = form[4]; }
1194: }
1195: else avma = av;
1196: if (DEBUGLEVEL)
1197: {
1198: if (fpc == 1) fprintferr(" %ld",s);
1199: else if (DEBUGLEVEL>1) fprintferr(".");
1200: flusherr();
1201: }
1202: }
1203: for (j=1; j<=extrarel; j++)
1204: {
1205: colg = cgetg(KC+1,t_COL);
1206: col = (GEN)extramat[j]; extramat[j] = (long) colg;
1207: for (k=1; k<=KC; k++)
1208: colg[k] = lstoi(col[vperm[k]]);
1209: }
1210: if (DEBUGLEVEL)
1211: {
1212: fprintferr("\n");
1213: msgtimer("extra relations");
1214: }
1215: return extramat;
1216: }
1217: #undef comp
1218:
1219: /*******************************************************************/
1220: /* */
1221: /* Imaginary Quadratic fields */
1222: /* */
1223: /*******************************************************************/
1224:
1225: static GEN
1226: imag_random_form(long current, long *ex)
1227: {
1228: long av = avma,i;
1229: GEN form,pc;
1230:
1231: for(;;)
1232: {
1233: form = pc = primeform(Disc,stoi(factorbase[current]),PRECREG);
1234: for (i=1; i<=lgsub; i++)
1235: {
1236: ex[i] = mymyrand()>>randshift;
1237: if (ex[i])
1238: form = compimag(form,powsubfactorbase[i][ex[i]]);
1239: }
1240: if (form != pc) return form;
1241: avma = av; /* ex = 0, try again */
1242: }
1243: }
1244:
1245: static void
1246: imag_relations(long lim, long s, long LIMC, long *ex, long **mat)
1247: {
1248: static long nbtest;
1249: long av = avma, i,j,pp,fpc,b1,b2,ep,current, first = (s==0);
1250: long *col,*fpd,*oldfact,*oldexp;
1251: GEN pc,form,form1;
1252:
1253: if (first) nbtest = 0 ;
1254: while (s<lim)
1255: {
1256: avma=av; nbtest++; current = first? 1+(s%KC): 1+s-RELSUP;
1257: form = imag_random_form(current,ex);
1258: fpc = factorisequad(form,KC,LIMC);
1259: if (!fpc)
1260: {
1261: if (DEBUGLEVEL>1) { fprintferr("."); flusherr(); }
1262: continue;
1263: }
1264: if (fpc > 1)
1265: {
1266: fpd = largeprime(fpc,ex,current,0);
1267: if (!fpd)
1268: {
1269: if (DEBUGLEVEL>1) { fprintferr("."); flusherr(); }
1270: continue;
1271: }
1272: form1 = powsubfactorbase[1][fpd[1]];
1273: for (i=2; i<=lgsub; i++)
1274: form1 = compimag(form1,powsubfactorbase[i][fpd[i]]);
1275: pc=primeform(Disc,stoi(factorbase[fpd[-2]]),0);
1276: form1=compimag(form1,pc);
1277: pp = fpc << 1;
1278: b1=smodis((GEN)form1[2], pp);
1279: b2=smodis((GEN)form[2], pp);
1280: if (b1 != b2 && b1+b2 != pp) continue;
1281:
1282: s++; col = mat[s];
1283: if (DEBUGLEVEL) { fprintferr(" %ld",s); flusherr(); }
1284: oldfact = primfact; oldexp = exprimfact;
1285: primfact = primfact1; exprimfact = exprimfact1;
1286: factorisequad(form1,KC,LIMC);
1287:
1288: if (b1==b2)
1289: {
1290: for (i=1; i<=lgsub; i++)
1291: col[numfactorbase[subbase[i]]] = fpd[i]-ex[i];
1292: col[fpd[-2]]++;
1293: for (j=1; j<=primfact[0]; j++)
1294: {
1295: pp=primfact[j]; ep=exprimfact[j];
1296: if (smodis((GEN)form1[2], pp<<1) > pp) ep = -ep;
1297: col[numfactorbase[pp]] -= ep;
1298: }
1299: }
1300: else
1301: {
1302: for (i=1; i<=lgsub; i++)
1303: col[numfactorbase[subbase[i]]] = -fpd[i]-ex[i];
1304: col[fpd[-2]]--;
1305: for (j=1; j<=primfact[0]; j++)
1306: {
1307: pp=primfact[j]; ep=exprimfact[j];
1308: if (smodis((GEN)form1[2], pp<<1) > pp) ep = -ep;
1309: col[numfactorbase[pp]] += ep;
1310: }
1311: }
1312: primfact = oldfact; exprimfact = oldexp;
1313: }
1314: else
1315: {
1316: s++; col = mat[s];
1317: if (DEBUGLEVEL) { fprintferr(" %ld",s); flusherr(); }
1318: for (i=1; i<=lgsub; i++)
1319: col[numfactorbase[subbase[i]]] = -ex[i];
1320: }
1321: for (j=1; j<=primfact[0]; j++)
1322: {
1323: pp=primfact[j]; ep=exprimfact[j];
1324: if (smodis((GEN)form[2], pp<<1) > pp) ep = -ep;
1325: col[numfactorbase[pp]] += ep;
1326: }
1327: col[current]--;
1328: if (!first && fpc == 1 && col[current] == 0)
1329: {
1330: s--; for (i=1; i<=KC; i++) col[i]=0;
1331: }
1332: }
1333: if (DEBUGLEVEL)
1334: {
1335: fprintferr("\nnbrelations/nbtest = %ld/%ld\n",s,nbtest);
1336: msgtimer("%s relations", first? "initial": "random");
1337: }
1338: }
1339:
1340: static int
1341: imag_be_honest(long *ex)
1342: {
1343: long p,fpc, s = KC, nbtest = 0, av = avma;
1344: GEN form;
1345:
1346: while (s<KC2)
1347: {
1348: p = factorbase[s+1];
1349: if (DEBUGLEVEL) { fprintferr(" %ld",p); flusherr(); }
1350: form = imag_random_form(s+1,ex);
1351: fpc = factorisequad(form,s,p-1);
1352: if (fpc == 1) { nbtest=0; s++; }
1353: else
1354: if (++nbtest > 20) return 0;
1355: avma = av;
1356: }
1357: return 1;
1358: }
1359:
1360: /*******************************************************************/
1361: /* */
1362: /* Real Quadratic fields */
1363: /* */
1364: /*******************************************************************/
1365:
1366: static GEN
1367: real_random_form(long *ex)
1368: {
1369: long av = avma, i;
1370: GEN p1,form = NULL;
1371:
1372: for(;;)
1373: {
1374: for (i=1; i<=lgsub; i++)
1375: {
1376: ex[i] = mymyrand()>>randshift;
1377: /* if (ex[i]) KB: less efficient if I put this in. Why ??? */
1378: {
1379: p1 = powsubfactorbase[i][ex[i]];
1380: form = form? comprealform3(form,p1): p1;
1381: }
1382: }
1383: if (form) return form;
1384: avma = av;
1385: }
1386: }
1387:
1388: static void
1389: real_relations(long lim, long s, long LIMC, long *ex, long **mat, GEN glog2,
1390: GEN vecexpo)
1391: {
1392: static long nbtest;
1393: long av = avma,av1,i,j,p,fpc,b1,b2,ep,current, first = (s==0);
1394: long *col,*fpd,*oldfact,*oldexp,limstack;
1395: long findecycle,nbrhocumule,nbrho;
1396: GEN p1,p2,form,form0,form1,form2;
1397:
1398: limstack=stack_lim(av,1);
1399: if (first) nbtest = 0;
1400: current = 0;
1401: p1 = NULL; /* gcc -Wall */
1402: while (s<lim)
1403: {
1404: form = real_random_form(ex);
1405: if (!first)
1406: {
1407: current = 1+s-RELSUP;
1408: p1 = redrealprimeform(Disc, factorbase[current]);
1409: form = comprealform3(form,p1);
1410: }
1411: form0 = form; form1 = NULL;
1412: findecycle = nbrhocumule = 0;
1413: nbrho = -1; av1 = avma;
1414: while (s<lim)
1415: {
1416: if (low_stack(limstack, stack_lim(av,1)))
1417: {
1418: GEN *gptr[2];
1419: int c = 1;
1420: if(DEBUGMEM>1) err(warnmem,"real_relations");
1421: gptr[0]=&form; if (form1) gptr[c++]=&form1;
1422: gerepilemany(av1,gptr,c);
1423: }
1424: if (nbrho < 0) nbrho = 0; /* first time in */
1425: else
1426: {
1427: if (findecycle) break;
1428: form = rhorealform(form);
1429: nbrho++; nbrhocumule++;
1430: if (first)
1431: {
1432: if (absi_equal((GEN)form[1],(GEN)form0[1])
1433: && egalii((GEN)form[2],(GEN)form0[2])
1434: && (!narrow || signe(form0[1])==signe(form[1]))) findecycle=1;
1435: }
1436: else
1437: {
1438: if (narrow)
1439: { form=rhorealform(form); nbrho++; }
1440: else if (absi_equal((GEN)form[1], (GEN)form[3])) /* a = -c */
1441: {
1442: if (absi_equal((GEN)form[1],(GEN)form0[1]) &&
1443: egalii((GEN)form[2],(GEN)form0[2])) break;
1444: form=rhorealform(form); nbrho++;
1445: }
1446: else
1447: { setsigne(form[1],1); setsigne(form[3],-1); }
1448: if (egalii((GEN)form[1],(GEN)form0[1]) &&
1449: egalii((GEN)form[2],(GEN)form0[2])) break;
1450: }
1451: }
1452: nbtest++; fpc = factorisequad(form,KC,LIMC);
1453: if (!fpc)
1454: {
1455: if (DEBUGLEVEL>1) { fprintferr("."); flusherr(); }
1456: continue;
1457: }
1458: if (fpc > 1)
1459: {
1460: fpd = largeprime(fpc,ex,current,nbrhocumule);
1461: if (!fpd)
1462: {
1463: if (DEBUGLEVEL>1) { fprintferr("."); flusherr(); }
1464: continue;
1465: }
1466: if (!form1) form1 = initrealform5(ex);
1467: if (!first)
1468: {
1469: p1 = redrealprimeform5(Disc, factorbase[current]);
1470: form1=comprealform(form1,p1);
1471: }
1472: form1 = rhoreal_pow(form1, nbrho); nbrho = 0;
1473: form2 = initrealform5(fpd);
1474: if (fpd[-2])
1475: {
1476: p1 = redrealprimeform5(Disc, factorbase[fpd[-2]]);
1477: form2=comprealform(form2,p1);
1478: }
1479: form2 = rhoreal_pow(form2, fpd[-3]);
1480: if (!narrow && !absi_equal((GEN)form2[1],(GEN)form2[3]))
1481: {
1482: setsigne(form2[1],1);
1483: setsigne(form2[3],-1);
1484: }
1485: p = fpc << 1;
1486: b1=smodis((GEN)form2[2], p);
1487: b2=smodis((GEN)form1[2], p);
1488: if (b1 != b2 && b1+b2 != p) continue;
1489:
1490: s++; col = mat[s]; if (DEBUGLEVEL) fprintferr(" %ld",s);
1491: oldfact = primfact; oldexp = exprimfact;
1492: primfact = primfact1; exprimfact = exprimfact1;
1493: factorisequad(form2,KC,LIMC);
1494: if (b1==b2)
1495: {
1496: for (i=1; i<=lgsub; i++)
1497: col[numfactorbase[subbase[i]]] = fpd[i]-ex[i];
1498: for (j=1; j<=primfact[0]; j++)
1499: {
1500: p=primfact[j]; ep=exprimfact[j];
1501: if (smodis((GEN)form2[2], p<<1) > p) ep = -ep;
1502: col[numfactorbase[p]] -= ep;
1503: }
1504: if (fpd[-2]) col[fpd[-2]]++; /* implies !first */
1505: p1 = subii((GEN)form1[4],(GEN)form2[4]);
1506: p2 = divrr((GEN)form1[5],(GEN)form2[5]);
1507: }
1508: else
1509: {
1510: for (i=1; i<=lgsub; i++)
1511: col[numfactorbase[subbase[i]]] = -fpd[i]-ex[i];
1512: for (j=1; j<=primfact[0]; j++)
1513: {
1514: p=primfact[j]; ep=exprimfact[j];
1515: if (smodis((GEN)form2[2], p<<1) > p) ep = -ep;
1516: col[numfactorbase[p]] += ep;
1517: }
1518: if (fpd[-2]) col[fpd[-2]]--;
1519: p1 = addii((GEN)form1[4],(GEN)form2[4]);
1520: p2 = mulrr((GEN)form1[5],(GEN)form2[5]);
1521: }
1522: primfact = oldfact; exprimfact = oldexp;
1523: }
1524: else
1525: {
1526: if (!form1) form1 = initrealform5(ex);
1527: if (!first)
1528: {
1529: p1 = redrealprimeform5(Disc, factorbase[current]);
1530: form1=comprealform(form1,p1);
1531: }
1532: form1 = rhoreal_pow(form1,nbrho); nbrho = 0;
1533:
1534: s++; col = mat[s]; if (DEBUGLEVEL) fprintferr(" %ld",s);
1535: for (i=1; i<=lgsub; i++)
1536: col[numfactorbase[subbase[i]]] = -ex[i];
1537: p1 = (GEN) form1[4];
1538: p2 = (GEN) form1[5];
1539: }
1540: for (j=1; j<=primfact[0]; j++)
1541: {
1542: p=primfact[j]; ep=exprimfact[j];
1543: if (smodis((GEN)form1[2], p<<1) > p) ep = -ep;
1544: col[numfactorbase[p]] += ep;
1545: }
1546: p1 = mpadd(mulir(mulsi(EXP220,p1), glog2), mplog(absr(p2)));
1547: affrr(shiftr(p1,-1), (GEN)vecexpo[s]);
1548: if (!first)
1549: {
1550: col[current]--;
1551: if (fpc == 1 && col[current] == 0)
1552: { s--; for (i=1; i<=KC; i++) col[i]=0; }
1553: break;
1554: }
1555: }
1556: avma = av;
1557: }
1558: if (DEBUGLEVEL)
1559: {
1560: fprintferr("\nnbrelations/nbtest = %ld/%ld\n",s,nbtest);
1561: msgtimer("%s relations", first? "initial": "random");
1562: }
1563: }
1564:
1565: static int
1566: real_be_honest(long *ex)
1567: {
1568: long p,fpc,s = KC,nbtest = 0,av = avma;
1569: GEN p1,form,form0;
1570:
1571: while (s<KC2)
1572: {
1573: p = factorbase[s+1];
1574: if (DEBUGLEVEL) { fprintferr(" %ld",p); flusherr(); }
1575: form = real_random_form(ex);
1576: p1 = redrealprimeform(Disc, p);
1577: form0 = form = comprealform3(form,p1);
1578: for(;;)
1579: {
1580: fpc = factorisequad(form,s,p-1);
1581: if (fpc == 1) { nbtest=0; s++; break; }
1582: form = rhorealform(form);
1583: if (++nbtest > 20) return 0;
1584: if (narrow || absi_equal((GEN)form[1],(GEN)form[3]))
1585: form = rhorealform(form);
1586: else
1587: {
1588: setsigne(form[1],1);
1589: setsigne(form[3],-1);
1590: }
1591: if (egalii((GEN)form[1],(GEN)form0[1])
1592: && egalii((GEN)form[2],(GEN)form0[2])) break;
1593: }
1594: avma = av;
1595: }
1596: return 1;
1597: }
1598:
1599: static GEN
1600: gcdrealnoer(GEN a,GEN b,long *pte)
1601: {
1602: long e;
1603: GEN k1,r;
1604:
1605: if (typ(a)==t_INT)
1606: {
1607: if (typ(b)==t_INT) return mppgcd(a,b);
1608: k1=cgetr(lg(b)); affir(a,k1); a=k1;
1609: }
1610: else if (typ(b)==t_INT)
1611: { k1=cgetr(lg(a)); affir(b,k1); b=k1; }
1612: if (expo(a)<-5) return absr(b);
1613: if (expo(b)<-5) return absr(a);
1614: a=absr(a); b=absr(b);
1615: while (expo(b) >= -5 && signe(b))
1616: {
1617: k1=gcvtoi(divrr(a,b),&e);
1618: if (e > 0) return NULL;
1619: r=subrr(a,mulir(k1,b)); a=b; b=r;
1620: }
1621: *pte=expo(b); return absr(a);
1622: }
1623:
1624: static GEN
1625: get_reg(GEN matc, long sreg)
1626: {
1627: long i,e,maxe;
1628: GEN reg = mpabs(gcoeff(matc,1,1));
1629:
1630: e = maxe = 0;
1631: for (i=2; i<=sreg; i++)
1632: {
1633: reg = gcdrealnoer(gcoeff(matc,1,i),reg,&e);
1634: if (!reg) return NULL;
1635: maxe = maxe? max(maxe,e): e;
1636: }
1637: if (DEBUGLEVEL)
1638: {
1639: if (DEBUGLEVEL>7) { fprintferr("reg = "); outerr(reg); }
1640: msgtimer("regulator");
1641: }
1642: return reg;
1643: }
1644:
1645: GEN
1646: buchquad(GEN D, double cbach, double cbach2, long RELSUP0, long flag, long prec)
1647: {
1648: long av0 = avma,av,tetpil,KCCO,KCCOPRO,i,j,s, *ex,**mat;
1649: long extrarel,nrelsup,nreldep,LIMC,LIMC2,cp,nbram,nlze;
1650: GEN p1,h,W,met,res,basecl,dr,c_1,pdep,C,B,extramat,extraC;
1651: GEN reg,vecexpo,glog2,cst;
1652: double drc,lim,LOGD;
1653:
1654: Disc = D; if (typ(Disc)!=t_INT) err(typeer,"buchquad");
1655: s=mod4(Disc);
1656: glog2 = vecexpo = NULL; /* gcc -Wall */
1657: switch(signe(Disc))
1658: {
1659: case -1:
1660: if (cmpis(Disc,-4) >= 0)
1661: {
1662: p1=cgetg(6,t_VEC); p1[1]=p1[4]=p1[5]=un;
1663: p1[2]=p1[3]=lgetg(1,t_VEC); return p1;
1664: }
1665: if (s==2 || s==1) err(funder2,"buchquad");
1666: PRECREG=0; break;
1667:
1668: case 1:
1669: if (s==2 || s==3) err(funder2,"buchquad");
1670: if (flag)
1671: err(talker,"sorry, narrow class group not implemented. Use bnfnarrow");
1672: PRECREG=1; break;
1673:
1674: default: err(talker,"zero discriminant in quadclassunit");
1675: }
1676: if (carreparfait(Disc)) err(talker,"square argument in quadclassunit");
1677: if (!isfundamental(Disc))
1678: err(warner,"not a fundamental discriminant in quadclassunit");
1679: buch_init(); RELSUP = RELSUP0;
1680: dr=cgetr(3); affir(Disc,dr); drc=fabs(rtodbl(dr)); LOGD=log(drc);
1681: lim=sqrt(drc); cst = mulrr(lfunc(Disc), dbltor(lim));
1682: if (!PRECREG) lim /= sqrt(3.);
1683: cp = (long)exp(sqrt(LOGD*log(LOGD)/8.0));
1684: if (cp < 13) cp = 13;
1685: av = avma; cbach /= 2;
1686:
1687: INCREASE: avma = av; cbach = check_bach(cbach,6.);
1688: nreldep = nrelsup = 0;
1689: LIMC = (long)(cbach*LOGD*LOGD);
1690: if (LIMC < cp) LIMC=cp;
1691: LIMC2 = max(20, (long)(max(cbach,cbach2)*LOGD*LOGD));
1692: if (LIMC2 < LIMC) LIMC2 = LIMC;
1693: if (PRECREG)
1694: {
1695: PRECREG = max(prec+1, MEDDEFAULTPREC + 2*(expi(Disc)>>TWOPOTBITS_IN_LONG));
1696: glog2 = glog(gdeux,PRECREG);
1697: sqrtD = gsqrt(Disc,PRECREG);
1698: isqrtD = gfloor(sqrtD);
1699: }
1700: factorbasequad(Disc,LIMC2,LIMC);
1701: if (!KC) goto INCREASE;
1702:
1703: vperm = cgetg(KC+1,t_VECSMALL); for (i=1; i<=KC; i++) vperm[i]=i;
1704: nbram = subfactorbasequad(lim,KC);
1705: if (nbram == -1) { desalloc(NULL); goto INCREASE; }
1706: KCCO = KC + RELSUP;
1707: if (DEBUGLEVEL) { fprintferr("KC = %ld, KCCO = %ld\n",KC,KCCO); flusherr(); }
1708: powsubfact(lgsub,CBUCH+7);
1709:
1710: mat = (long**) gpmalloc((KCCO+1)*sizeof(long*));
1711: setlg(mat, KCCO+1);
1712: for (i=1; i<=KCCO; i++)
1713: {
1714: mat[i] = (long*) gpmalloc((KC+1)*sizeof(long));
1715: for (j=1; j<=KC; j++) mat[i][j]=0;
1716: }
1717: ex = new_chunk(lgsub+1);
1718: limhash = ((ulong)LIMC < (MAXHALFULONG>>1))? LIMC*LIMC: HIGHBIT>>1;
1719: for (i=0; i<HASHT; i++) hashtab[i]=NULL;
1720:
1721: s = lgsub+nbram+RELSUP;
1722: if (PRECREG)
1723: {
1724: vecexpo=cgetg(KCCO+1,t_VEC);
1725: for (i=1; i<=KCCO; i++) vecexpo[i]=lgetr(PRECREG);
1726: real_relations(s,0,LIMC,ex,mat,glog2,vecexpo);
1727: real_relations(KCCO,s,LIMC,ex,mat,glog2,vecexpo);
1728: }
1729: else
1730: {
1731: imag_relations(s,0,LIMC,ex,mat);
1732: imag_relations(KCCO,s,LIMC,ex,mat);
1733: }
1734: if (KC2 > KC)
1735: {
1736: if (DEBUGLEVEL)
1737: fprintferr("be honest for primes from %ld to %ld\n",
1738: factorbase[KC+1],factorbase[KC2]);
1739: s = PRECREG? real_be_honest(ex): imag_be_honest(ex);
1740: if (DEBUGLEVEL)
1741: {
1742: fprintferr("\n");
1743: msgtimer("be honest");
1744: }
1745: if (!s) { desalloc(mat); goto INCREASE; }
1746: }
1747: C=cgetg(KCCO+1,t_MAT);
1748: if (PRECREG)
1749: {
1750: for (i=1; i<=KCCO; i++)
1751: {
1752: C[i]=lgetg(2,t_COL); coeff(C,1,i)=vecexpo[i];
1753: }
1754: if (DEBUGLEVEL>7) { fprintferr("C: "); outerr(C); flusherr(); }
1755: }
1756: else
1757: for (i=1; i<=KCCO; i++) C[i]=lgetg(1,t_COL);
1758: W = hnfspec(mat,vperm,&pdep,&B,&C,lgsub);
1759: nlze = lg(pdep)>1? lg(pdep[1])-1: lg(B[1])-1;
1760:
1761: KCCOPRO=KCCO;
1762: if (nlze)
1763: {
1764: EXTRAREL:
1765: s = PRECREG? 2: 1; extrarel=nlze+2;
1766: extraC=cgetg(extrarel+1,t_MAT);
1767: for (i=1; i<=extrarel; i++) extraC[i]=lgetg(s,t_COL);
1768: extramat = extra_relations(LIMC,ex,nlze,extraC);
1769: if (!extramat) { desalloc(mat); goto INCREASE; }
1770: W = hnfadd(W,vperm,&pdep,&B,&C, extramat,extraC);
1771: nlze = lg(pdep)>1? lg(pdep[1])-1: lg(B[1])-1;
1772: KCCOPRO += extrarel;
1773: if (nlze)
1774: {
1775: if (++nreldep > 5) { desalloc(mat); goto INCREASE; }
1776: goto EXTRAREL;
1777: }
1778: }
1779: /* tentative class number */
1780: h=gun; for (i=1; i<lg(W); i++) h=mulii(h,gcoeff(W,i,i));
1781: if (PRECREG)
1782: {
1783: /* tentative regulator */
1784: reg = get_reg(C, KCCOPRO - (lg(B)-1) - (lg(W)-1));
1785: if (!reg)
1786: {
1787: desalloc(mat);
1788: prec = (PRECREG<<1)-2; goto INCREASE;
1789: }
1790: if (gexpo(reg)<=-3)
1791: {
1792: if (++nrelsup <= 7)
1793: {
1794: if (DEBUGLEVEL) { fprintferr("regulateur nul\n"); flusherr(); }
1795: nlze=min(KC,nrelsup); goto EXTRAREL;
1796: }
1797: desalloc(mat); goto INCREASE;
1798: }
1799: c_1 = divrr(gmul2n(gmul(h,reg),1), cst);
1800: }
1801: else
1802: {
1803: reg = gun;
1804: c_1 = divrr(gmul(h,mppi(DEFAULTPREC)), cst);
1805: }
1806:
1807: if (gcmpgs(gmul2n(c_1,2),3)<0) { c_1=stoi(10); nrelsup=7; }
1808: if (gcmpgs(gmul2n(c_1,1),3)>0)
1809: {
1810: nrelsup++;
1811: if (nrelsup<=7)
1812: {
1813: if (DEBUGLEVEL)
1814: { fprintferr("***** check = %f\n\n",gtodouble(c_1)); flusherr(); }
1815: nlze=min(KC,nrelsup); goto EXTRAREL;
1816: }
1817: if (cbach < 5.99) { desalloc(mat); goto INCREASE; }
1818: err(warner,"suspicious check. Suggest increasing extra relations.");
1819: }
1820: basecl = get_clgp(Disc,W,&met,PRECREG);
1821: s = lg(basecl); desalloc(mat); tetpil=avma;
1822:
1823: res=cgetg(6,t_VEC);
1824: res[1]=lcopy(h); p1=cgetg(s,t_VEC);
1825: for (i=1; i<s; i++) p1[i] = (long)icopy(gcoeff(met,i,i));
1826: res[2]=(long)p1;
1827: res[3]=lcopy(basecl);
1828: res[4]=lcopy(reg);
1829: res[5]=lcopy(c_1); return gerepile(av0,tetpil,res);
1830: }
1831:
1832: GEN
1833: buchimag(GEN D, GEN c, GEN c2, GEN REL)
1834: {
1835: return buchquad(D,gtodouble(c),gtodouble(c2),itos(REL), 0,0);
1836: }
1837:
1838: GEN
1839: buchreal(GEN D, GEN sens0, GEN c, GEN c2, GEN REL, long prec)
1840: {
1841: return buchquad(D,gtodouble(c),gtodouble(c2),itos(REL), itos(sens0),prec);
1842: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>