Annotation of OpenXM_contrib/pari/src/modules/stark.c, Revision 1.1.1.1
1.1 maekawa 1: /*******************************************************************/
2: /* */
3: /* COMPUTATION OF STARK UNITS */
4: /* OF TOTALLY REAL FIELDS */
5: /* */
6: /*******************************************************************/
7: /* $Id: stark.c,v 1.2 1999/09/23 17:50:57 karim Exp $ */
8: #include "pari.h"
9:
10: #define EXTRA_PREC (DEFAULTPREC-1)
11:
12: GEN roots_to_pol_intern(GEN L, GEN a, long v, int plus);
13: static int*** computean(GEN dtcr, long nmax, long prec);
14:
15: /********************************************************************/
16: /* Miscellaneous functions */
17: /********************************************************************/
18:
19: /* Compute the image of logelt by chi as a complex number if flag = 0,
20: otherwise as a polmod, see InitChar in part 3 */
21: static GEN
22: ComputeImagebyChar(GEN chi, GEN logelt, long flag)
23: {
24: GEN gn = gmul((GEN)chi[1], logelt), x = (GEN)chi[flag? 4: 2];
25: long d = itos((GEN)chi[3]), n = smodis(gn, d);
26: /* x^d = 1 and, if d even, x^(d/2) = -1 */
27: if ((d & 1) == 0)
28: {
29: d /= 2;
30: if (n >= d) return gneg(gpowgs(x, n-d));
31: }
32: return gpowgs(x, n);
33: }
34:
35: /* Compute the conjugate character */
36: static GEN
37: ConjChar(GEN chi, GEN cyc)
38: {
39: long i, l = lg(chi);
40: GEN p1 = cgetg(l, t_COL);
41:
42: for (i = 1; i < l; i++)
43: if (!signe((GEN)chi[i]))
44: p1[i] = zero;
45: else
46: p1[i] = lsubii((GEN)cyc[i], (GEN)chi[i]);
47:
48: return p1;
49: }
50:
51: /* Compute all the elements of a group given by its SNF */
52: static GEN
53: FindEltofGroup(long order, GEN cyc)
54: {
55: long l, i, adec, j, dj;
56: GEN rep, p1;
57:
58: l = lg(cyc)-1;
59:
60: rep = cgetg(order + 1, t_VEC);
61:
62: for (i = 1; i <= order; i++)
63: {
64: p1 = cgetg(l + 1, t_COL);
65: rep[i] = (long)p1;
66: adec = i;
67:
68: for (j = l; j; j--)
69: {
70: dj = itos((GEN)cyc[j]);
71: p1[j] = lstoi(adec%dj);
72: adec /= dj;
73: }
74: }
75:
76: return rep;
77: }
78:
79: /* Let dataC as given by InitQuotient0, compute a system of
80: representatives of the quotient */
81: static GEN
82: ComputeLift(GEN dataC)
83: {
84: long order, i, av = avma;
85: GEN cyc, surj, eltq, elt;
86:
87: order = itos((GEN)dataC[1]);
88: cyc = (GEN)dataC[2];
89: surj = (GEN)dataC[3];
90:
91: eltq = FindEltofGroup(order, cyc);
92:
93: elt = cgetg(order + 1, t_VEC);
94:
95: for (i = 1; i <= order; i++)
96: elt[i] = (long)inverseimage(surj, (GEN)eltq[i]);
97:
98: return gerepileupto(av, elt);
99: }
100:
101: /* Let bnr1, bnr2 be such that mod(bnr2) | mod(bnr1), compute the
102: matrix of the surjective map Cl(bnr1) ->> Cl(bnr2) */
103: static GEN
104: GetSurjMat(GEN bnr1, GEN bnr2)
105: {
106: long nbg, i;
107: GEN gen, M;
108:
109: gen = gmael(bnr1, 5, 3);
110: nbg = lg(gen) - 1;
111:
112: M = cgetg(nbg + 1, t_MAT);
113: for (i = 1; i <= nbg; i++)
114: M[i] = (long)isprincipalray(bnr2, (GEN)gen[i]);
115:
116: return M;
117: }
118:
119: /* A character is given by a vector [(c_i), z, d, pm] such that
120: chi(id) = z ^ sum(c_i * a_i) where
121: a_i= log(id) on the generators of bnr
122: z = exp(2i * Pi / d)
123: pm = z as a polmod */
124: static GEN
125: get_Char(GEN chi, long prec)
126: {
127: GEN p2, d, _2ipi = gmul(gi, shiftr(mppi(prec), 1));
128: p2 = cgetg(5, t_VEC); d = denom(chi);
129: p2[1] = lmul(d, chi);
130: if (egalii(d, gdeux))
131: p2[2] = lstoi(-1);
132: else
133: p2[2] = lexp(gdiv(_2ipi, d), prec);
134: p2[3] = (long)d;
135: p2[4] = lmodulcp(polx[0], cyclo(itos(d), 0));
136: return p2;
137: }
138:
139: /* Let chi a character defined over bnr and primitif over bnrc,
140: compute the corresponding primitive character and the vectors of
141: prime ideals dividing bnr but not bnr. Returns NULL if bnr = bnrc */
142: static GEN
143: GetPrimChar(GEN chi, GEN bnr, GEN bnrc, long prec)
144: {
145: long nbg, i, j, l, av = avma, nd;
146: GEN gen, cyc, U, chic, M, s, p1, cond, condc, p2, nf;
147: GEN prdiff, Mrc;
148:
149: cond = gmael(bnr, 2, 1);
150: condc = gmael(bnrc, 2, 1);
151: if (gegal(cond, condc)) return NULL;
152:
153: gen = gmael(bnr, 5, 3);
154: nbg = lg(gen) - 1;
155: cyc = gmael(bnr, 5, 2);
156: Mrc = diagonal(gmael(bnrc, 5, 2));
157: nf = gmael(bnr, 1, 7);
158:
159: cond = (GEN)cond[1];
160: condc = (GEN)condc[1];
161:
162: M = GetSurjMat(bnr, bnrc);
163: l = lg((GEN)M[1]);
164: p1 = hnfall(concatsp(M, Mrc));
165: U = (GEN)p1[2];
166:
167: chic = cgetg(l, t_VEC);
168: for (i = 1; i < l; i++)
169: {
170: s = gzero; p1 = (GEN)U[i + nbg];
171: for (j = 1; j <= nbg; j++)
172: {
173: p2 = gdiv((GEN)p1[j], (GEN)cyc[j]);
174: s = gadd(s,gmul(p2,(GEN)chi[j]));
175: }
176: chic[i] = (long)s;
177: }
178:
179: p2 = (GEN)idealfactor(nf, cond)[1];
180: l = lg(p2);
181:
182: prdiff = cgetg(l, t_COL);
183: for (nd=1, i=1; i < l; i++)
184: if (!idealval(nf, condc, (GEN)p2[i])) prdiff[nd++] = p2[i];
185: setlg(prdiff, nd);
186:
187: p1 = cgetg(3, t_VEC);
188: p1[1] = (long)get_Char(chic,prec);
189: p1[2] = lcopy(prdiff);
190:
191: return gerepileupto(av,p1);
192: }
193:
194: /* Let dataCR be a list of characters, compute the image of logelt */
195: static GEN
196: chiideal(GEN dataCR, GEN logelt, long flag)
197: {
198: long j, l = lg(dataCR);
199: GEN rep = cgetg(l, t_VEC);
200:
201: for (j = 1; j < l; j++)
202: rep[j] = (long)ComputeImagebyChar(gmael(dataCR, j, 5), logelt, flag);
203:
204: return rep;
205: }
206:
207: static GEN
208: GetDeg(GEN dataCR)
209: {
210: long i, l = lg(dataCR);
211: GEN degs = cgetg(l, t_VECSMALL);
212:
213: for (i = 1; i < l; i++)
214: degs[i] = lgef(gmael4(dataCR, i, 5, 4, 1)) - 3;
215: return degs;
216: }
217:
218: /********************************************************************/
219: /* 1rst part: find the field K */
220: /********************************************************************/
221:
222: static GEN AllStark(GEN data, GEN nf, long flag, long prec);
223: static GEN InitChar0(GEN dataD, long prec);
224:
225: /* Let A be a finite abelian group given by its relation and let C
226: define a subgroup of A, compute the order of A / C, its structure and
227: the matrix expressing the generators of A on those of A / C */
228: static GEN
229: InitQuotient0(GEN DA, GEN C)
230: {
231: long i, l;
232: GEN MQ, MrC, H, snf, snf2, rep, p1;
233:
234: l = lg(DA)-1;
235: H = gcmp0(C)? DA: C;
236: MrC = gauss(H, DA);
237: snf = smith2(hnf(MrC));
238: MQ = concatsp(gmul(H, (GEN)snf[1]), DA);
239: snf2 = smith2(hnf(MQ));
240:
241: rep = cgetg(5, t_VEC);
242:
243: p1 = cgetg(l + 1, t_VEC);
244: for (i = 1; i <= l; i++)
245: p1[i] = lcopy(gcoeff((GEN)snf2[3], i, i));
246:
247: rep[1] = (long)dethnf((GEN)snf2[3]);
248: rep[2] = (long)p1;
249: rep[3] = lcopy((GEN)snf2[1]);
250: rep[4] = lcopy(C);
251:
252: return rep;
253: }
254:
255: /* Let m be a modulus et C a subgroup of Clk(m), compute all the data
256: needed to work with the quotient Clk(m) / C namely 1) bnr(m), 2.1)
257: its order, 2.2) its structure, 2.3) the matrix Clk(m) ->> Clk(m)/C
258: and 2.4) the group C */
259: static GEN
260: InitQuotient(GEN bnr, GEN C)
261: {
262: GEN Mrm, dataquo = cgetg(3, t_VEC);
263: long av;
264:
265: dataquo[1] = lcopy(bnr);
266: av = avma; Mrm = diagonal(gmael(bnr, 5, 2));
267: dataquo[2] = lpileupto(av, InitQuotient0(Mrm, C));
268:
269: return dataquo;
270: }
271:
272: /* Let s: A -> B given by P, and let DA, DB be resp. the matrix of the
273: relations of A and B, let nbA, nbB be resp. the rank of A and B,
274: compute the kernel of s. If DA = 0 then A is free */
275: static GEN
276: ComputeKernel0(GEN P, GEN DA, GEN DB, long nbA, long nbB)
277: {
278: long rk, av = avma;
279: GEN herm, mask1, mask2, U;
280:
281: herm = hnfall(concatsp(P, DB));
282: rk = nbA + nbB + 1;
283: rk -= lg((GEN)herm[1]); /* two steps: bug in pgcc 1.1.3 inlining IS */
284:
285: mask1 = subis(shifti(gun, nbA), 1);
286: mask2 = subis(shifti(gun, rk), 1);
287:
288: U = matextract((GEN)herm[2], mask1, mask2);
289:
290: if (!gcmp0(DA)) U = concatsp(U, DA);
291: return gerepileupto(av, hnf(U));
292: }
293:
294: /* Let m and n be two moduli such that n|m and let C be a congruence
295: group modulo n, compute the corresponding congruence group modulo m
296: ie then kernel of the map Clk(m) ->> Clk(n)/C */
297: static GEN
298: ComputeKernel(GEN bnrm, GEN dataC)
299: {
300: long av = avma, i, nbm, nbq;
301: GEN bnrn, Mrm, genm, Mrq, mgq, P;
302:
303: bnrn = (GEN)dataC[1];
304: Mrm = diagonal(gmael(bnrm, 5, 2));
305: genm = gmael(bnrm, 5, 3);
306: nbm = lg(genm) - 1;
307: Mrq = diagonal(gmael(dataC, 2, 2));
308: mgq = gmael(dataC, 2, 3);
309: nbq = lg(mgq) - 1;
310:
311: P = cgetg(nbm + 1, t_MAT);
312: for (i = 1; i <= nbm; i++)
313: P[i] = lmul(mgq, isprincipalray(bnrn, (GEN)genm[i]));
314:
315: return gerepileupto(av, ComputeKernel0(P, Mrm, Mrq, nbm, nbq));
316: }
317:
318: /* Let C a congruence group in bnr, compute its subgroups of index 2 as
319: subgroups of Clk(bnr) */
320: static GEN
321: ComputeIndex2Subgroup(GEN bnr, GEN C)
322: {
323: long nb, i, l, av = avma;
324: GEN snf, Mr, U, CU, subgrp, rep, p1;
325:
326: disable_dbg(0);
327:
328: Mr = diagonal(gmael(bnr, 5, 2));
329: snf = smith2(gmul(ginv(C), Mr));
330:
331: U = ginv((GEN)snf[1]);
332: l = lg((GEN)snf[3]);
333:
334: p1 = cgetg(l, t_VEC);
335: for (i = 1; i < l; i++)
336: p1[i] = mael3(snf, 3, i, i);
337:
338: subgrp = subgrouplist(p1, 2);
339: nb = lg(subgrp) - 1; CU = gmul(C,U);
340:
341: rep = cgetg(nb, t_VEC);
342: for (i = 1; i < nb; i++) /* skip Id which comes last */
343: rep[i] = (long)hnf(concatsp(gmul(CU, (GEN)subgrp[i]), Mr));
344:
345: disable_dbg(-1);
346: return gerepileupto(av, gcopy(rep));
347: }
348:
349: /* Let pr be a prime (pr may divide mod(bnr)), compute the indexes
350: e,f of the splitting of pr in the class field nf(bnr/subgroup) */
351: static GEN
352: GetIndex(GEN pr, GEN bnr, GEN subgroup, long prec)
353: {
354: long av = avma, v, lg, i;
355: GEN bnf, mod, mod0, mpr0, mpr, bnrpr, subpr, M, e, f, dtQ, p1;
356: GEN rep, cycpr, cycQ;
357:
358: bnf = (GEN)bnr[1];
359: mod = gmael(bnr, 2, 1);
360: mod0 = (GEN)mod[1];
361:
362: /* Compute the part of mod coprime to pr */
363: v = idealval(bnf, mod0, pr);
364: mpr0 = idealdivexact(bnf, mod0, idealpow(bnf, pr, stoi(v)));
365:
366: mpr = cgetg(3, t_VEC);
367: mpr[1] = (long)mpr0;
368: mpr[2] = mod[2];
369: if (gegal(mpr0, mod0))
370: {
371: bnrpr = bnr;
372: subpr = subgroup;
373: }
374: else
375: {
376: bnrpr = buchrayinitgen(bnf, mpr, prec);
377: cycpr = gmael(bnrpr, 5, 2);
378: M = GetSurjMat(bnr, bnrpr);
379: M = gmul(M, subgroup);
380: subpr = hnf(concatsp(M, diagonal(cycpr)));
381: }
382:
383: /* e = #(bnr/subgroup) / #(bnrpr/subpr) */
384: e = gdiv(det(subgroup), det(subpr));
385:
386: /* f = order of [pr] in bnrpr/subpr */
387: dtQ = InitQuotient(bnrpr, subpr);
388: p1 = isprincipalray(bnrpr, pr);
389: p1 = gmul(gmael(dtQ, 2, 3), p1);
390: cycQ = gmael(dtQ, 2, 2);
391: lg = lg(cycQ) - 1;
392: f = gun;
393: for (i = 1; i <= lg; i++)
394: f = glcm(f, gdiv((GEN)cycQ[i], ggcd((GEN)cycQ[i], (GEN)p1[i])));
395:
396: rep = cgetg(3, t_VEC);
397: rep[1] = lcopy(e);
398: rep[2] = lcopy(f);
399:
400: return gerepileupto(av, rep);
401: }
402:
403:
404: /* Given a conductor and a subgroups, return the corresponding
405: complexity and precision required using quickpol */
406: static GEN
407: CplxModulus(GEN data, long *newprec, long prec)
408: {
409: long av = avma, pr, dprec;
410: GEN nf, cpl, pol, p1;
411:
412: nf = gmael3(data, 1, 1, 7);
413:
414: p1 = cgetg(6, t_VEC);
415:
416: p1[1] = data[1];
417: p1[2] = data[2];
418: p1[3] = data[3];
419: p1[4] = data[4];
420:
421: if (DEBUGLEVEL >= 2)
422: fprintferr("\nTrying modulus = %Z and subgroup = %Z\n",
423: mael3(p1, 1, 2, 1), (GEN)p1[2]);
424:
425: dprec = DEFAULTPREC;
426:
427: for (;;)
428: {
429: p1[5] = (long)InitChar0((GEN)data[3], dprec);
430: pol = AllStark(p1, nf, -1, dprec);
431: cpl = mpabs(poldisc0(pol, 0));
432:
433: if (!gcmp0(cpl)) break;
434: if (DEBUGLEVEL >= 2) err(warnprec, "CplxModulus", dprec);
435: dprec++;
436: }
437:
438: if (DEBUGLEVEL >= 2) fprintferr("cpl = %Z\n", cpl);
439:
440: pr = gexpo(pol)>>TWOPOTBITS_IN_LONG;
441: if (pr < 0) pr = 0;
442: *newprec = max(prec, pr + DEFAULTPREC);
443:
444: return gerepileupto(av, cpl);
445: }
446:
447: /* Let f be a conductor without infinite part and let C be a
448: congruence group modulo f, compute (m,D) such that D is a
449: congruence group of conductor m where m is a multiple of f
450: divisible by all the infinite places but one, D is a subgroup of
451: index 2 of Im(C) in Clk(m), no prime dividing f splits in the
452: corresponding quadratic extension and m is of minimal norm. Return
453: bnr(m), D, quotient Ck(m) / D and Clk(m) / C */
454: /* If fl != 0, try a second modulus is the first one seems too "bad" */
455: static GEN
456: FindModulus(GEN dataC, long fl, long *newprec, long prec)
457: {
458: long n, i, narch, nbp, maxnorm, minnorm, N, nbidnn, s, c, j, nbcand;
459: long av = avma, av1, av0, limnorm, tetpil, first = 1, pr;
460: GEN bnr, rep, bnf, nf, f, arch, m, listid, idnormn, bnrm, ImC;
461: GEN candD, D, bpr, indpr, sgp, p1, p2, rb;
462:
463: bnr = (GEN)dataC[1];
464: sgp = gmael(dataC, 2, 4);
465: bnf = (GEN)bnr[1];
466: nf = (GEN)bnf[7];
467: N = degree((GEN)nf[1]);
468: f = gmael3(bnr, 2, 1, 1);
469:
470: rep = cgetg(6, t_VEC);
471: for (i = 1; i <= 5; i++) rep[i] = zero;
472:
473: /* if cpl < rb, it is not necessary to try another modulus */
474: rb = powgi(gmul(gmael(bnf, 7, 3), det(f)), gmul2n(gmael(bnr, 5, 1), 3));
475:
476: bpr = (GEN)idealfactor(nf, f)[1];
477: nbp = lg(bpr) - 1;
478:
479: indpr = cgetg(nbp + 1,t_VEC);
480: for (i = 1; i <= nbp; i++)
481: {
482: p1 = GetIndex((GEN)bpr[i], bnr, sgp, prec);
483: indpr[i] = lmulii((GEN)p1[1], (GEN)p1[2]);
484: }
485:
486: /* Initialization of the possible infinite part */
487: arch = cgetg(N+1, t_VEC);
488: for (i = 1; i <= N; i++) arch[i] = un;
489:
490: /* narch = (N == 2)? 1: N; -- if N=2, only one case is necessary */
491: narch = N;
492:
493: m = cgetg(3, t_VEC);
494: m[2] = (long)arch;
495:
496: /* we go from minnorm up to maxnorm, if necessary we increase these values.
497: If we cannot find a suitable conductor of norm < limnorm, we stop */
498: maxnorm = 50;
499: minnorm = 1;
500: limnorm = 200;
501:
502: if (DEBUGLEVEL >= 2)
503: fprintferr("Looking for a modulus of norm: ");
504:
505: av0 = avma;
506: for(;;)
507: {
508: /* compute all ideals of norm <= maxnorm */
509: disable_dbg(0);
510: listid = ideallist(nf, maxnorm);
511: disable_dbg(-1);
512: av1 = avma;
513:
514: for (n = minnorm; n <= maxnorm; n++)
515: {
516: if (DEBUGLEVEL >= 2) fprintferr(" %ld", n);
517:
518: idnormn = (GEN)listid[n];
519: nbidnn = lg(idnormn) - 1;
520: for (i = 1; i <= nbidnn; i++)
521: {
522: tetpil = avma;
523: rep = gerepile(av1, tetpil, gcopy(rep));
524:
525: /* finite part of the conductor */
526: m[1] = (long)idealmul(nf, f, (GEN)idnormn[i]);
527:
528: for (s = 1; s <= narch; s++)
529: {
530: /* infinite part */
531: arch[N+1-s] = zero;
532:
533: /* compute Clk(m), check if m is a conductor */
534: disable_dbg(0);
535: bnrm = buchrayinitgen(bnf, m, prec);
536: p1 = conductor(bnrm, gzero, -1, prec);
537: disable_dbg(-1);
538: if (signe(p1))
539: {
540: /* compute Im(C) in Clk(m)... */
541: ImC = ComputeKernel(bnrm, dataC);
542:
543: /* ... and its subgroups of index 2 */
544: candD = ComputeIndex2Subgroup(bnrm, ImC);
545: nbcand = lg(candD) - 1;
546: for (c = 1; c <= nbcand; c++)
547: {
548: /* check if m is the conductor */
549: D = (GEN)candD[c];
550: disable_dbg(0);
551: p1 = conductor(bnrm, D, -1, prec);
552: disable_dbg(-1);
553: if (signe(p1))
554: {
555: /* check the splitting of primes */
556: for (j = 1; j <= nbp; j++)
557: {
558: p1 = GetIndex((GEN)bpr[j], bnrm, D, prec);
559: p1 = mulii((GEN)p1[1], (GEN)p1[2]);
560: if (egalii(p1, (GEN)indpr[j])) break; /* no good */
561: }
562: if (j > nbp)
563: {
564: p2 = cgetg(6, t_VEC);
565:
566: p2[1] = lcopy(bnrm);
567: p2[2] = lcopy(D);
568: p2[3] = (long)InitQuotient((GEN)p2[1], (GEN)p2[2]);
569: p2[4] = (long)InitQuotient((GEN)p2[1], ImC);
570:
571: p1 = CplxModulus(p2, &pr, prec);
572:
573: if (first == 1)
574: {
575: *newprec = pr;
576: for (j = 1; j <= 4; j++) rep[j] = p2[j];
577: rep[5] = (long)p1;
578: }
579: else
580: if (gcmp(p1, (GEN)rep[5]) < 0)
581: {
582: *newprec = pr;
583: for (j = 1; j <= 5; j++) rep[j] = p2[j];
584: rep[5] = (long)p1;
585: }
586:
587: if (!fl || (gcmp(p1, rb) < 0))
588: {
589: rep[5] = (long)InitChar0((GEN)rep[3], *newprec);
590: return gerepileupto(av, gcopy(rep));
591: }
592: if (DEBUGLEVEL >= 2)
593: fprintferr("Trying to find another modulus...");
594: first = 0;
595: }
596: }
597: }
598: }
599: arch[N+1-s] = un;
600: }
601: if (!first)
602: {
603: if (DEBUGLEVEL >= 2)
604: fprintferr("No, we're done!\nModulus = %Z and subgroup = %Z\n",
605: gmael3(rep, 1, 2, 1), rep[2]);
606: rep[5] = (long)InitChar0((GEN)rep[3], *newprec);
607: return gerepileupto(av, gcopy(rep));
608: }
609: }
610: }
611: /* if necessary compute more ideals */
612: tetpil = avma;
613: rep = gerepile(av0, tetpil, gcopy(rep));
614:
615: minnorm = maxnorm;
616: maxnorm <<= 1;
617: if (maxnorm > limnorm)
618: err(talker, "Cannot find a suitable modulus in FindModulus");
619: }
620: }
621:
622: /********************************************************************/
623: /* 2nd part: compute W(X) */
624: /********************************************************************/
625:
626: /* compute W(chi) such that Ld(s,chi) = W(chi) Ld(1 - s, chi*),
627: if flag != 0 do not check the result */
628: static GEN
629: ComputeArtinNumber(GEN datachi, long flag, long prec)
630: {
631: long av = avma, av2, G, ms, j, i, nz, zcard, q, l, N;
632: GEN chi, nc, dc, p1, cond0, cond1, elts, Msign, umod2, lambda, nf;
633: GEN sg, p2, chib, diff, vt, z, idg, mu, idh, zid, zstruc, zgen, zchi;
634: GEN allclass, classe, bnr, beta, s, tr, p3, den, muslambda, Pi;
635:
636: chi = (GEN)datachi[8];
637: /* trivial case */
638: if (cmpsi(2, (GEN)chi[3]) >= 0) return gun;
639:
640: bnr = (GEN)datachi[3];
641: nf = gmael(bnr, 1, 7);
642: diff = gmael(nf, 5, 5);
643: cond0 = gmael3(bnr, 2, 1, 1);
644: cond1 = gmael3(bnr, 2, 1, 2);
645: umod2 = gmodulcp(gun, gdeux);
646: N = degree((GEN)nf[1]);
647: Pi = mppi(prec);
648:
649: G = - bit_accuracy(prec) >> 1;
650: nc = idealnorm(nf, cond0);
651: dc = idealmul(nf, diff, cond0);
652: den = idealnorm(nf, dc);
653: z = gexp(gdiv(gmul2n(gmul(gi, Pi), 1), den), prec);
654:
655: q = 0;
656: for (i = 1; i < lg(cond1); i++)
657: if (gcmp1((GEN)cond1[i])) q++;
658:
659: /* compute a system of elements congru to 1 mod cond0 and giving all
660: possible signatures for cond1 */
661: p1 = zarchstar(nf, cond0, cond1, q);
662: elts = (GEN)p1[2];
663: Msign = gmul((GEN)p1[3], umod2);
664: ms = lg(elts) - 1;
665:
666: /* find lambda in diff.cond such that gcd(lambda.(diff.cond)^-1,cond0) = 1
667: and lambda >(cond1)> 0 */
668: lambda = idealappr(nf, dc);
669: sg = zsigne(nf, lambda, cond1);
670: p2 = lift(gmul(Msign, sg));
671:
672: for (j = 1; j <= ms; j++)
673: if (gcmp1((GEN)p2[j])) lambda = element_mul(nf, lambda, (GEN)elts[j]);
674:
675: idg = idealdivexact(nf, lambda, dc);
676:
677: /* find mu in idg such that idh=(mu) / idg is coprime with cond0 and
678: mu >(cond1)> 0 */
679: if (!gcmp1(gcoeff(idg, 1, 1)))
680: {
681: p1 = idealfactor(nf, idg);
682: p2 = idealfactor(nf, cond0);
683:
684: l = lg((GEN)p2[1]);
685: for (i = 1; i < l; i++) coeff(p2, i, 2) = zero;
686:
687: p1 = gtrans(concatsp(gtrans(p1), gtrans(p2)));
688: mu = idealapprfact(nf, p1);
689: sg = zsigne(nf, mu, cond1);
690: p2 = lift(gmul(Msign, sg));
691:
692: for (j = 1; j <= ms; j++)
693: if (gcmp1((GEN)p2[j])) mu = element_mul(nf, mu, (GEN)elts[j]);
694:
695: idh = idealdivexact(nf, mu, idg);
696: }
697: else
698: {
699: mu = gun;
700: idh = gcopy(idg);
701: }
702:
703: muslambda = element_div(nf, mu, lambda);
704:
705: /* compute a system of generators of (Ok/cond)^* cond1-positive */
706: zid = zidealstarinitgen(nf, cond0);
707:
708: zcard = itos(gmael(zid, 2, 1));
709: zstruc = gmael(zid, 2, 2);
710: zgen = gmael(zid, 2, 3);
711: nz = lg(zgen) - 1;
712:
713: zchi = cgetg(nz + 1, t_VEC);
714: for (i = 1; i <= nz; i++)
715: {
716: p1 = (GEN)zgen[i];
717: sg = zsigne(nf, p1, cond1);
718: p2 = lift(gmul(Msign, sg));
719:
720: for (j = 1; j <= ms; j++)
721: if (gcmp1((GEN)p2[j])) p1 = element_mul(nf, p1, (GEN)elts[j]);
722:
723: classe = isprincipalray(bnr, p1);
724: zchi[i] = (long)ComputeImagebyChar(chi, classe, 0);
725: zgen[i] = (long)p1;
726: }
727:
728: /* Sum chi(beta) * exp(2i * Pi * Tr(beta * mu / lambda) where beta
729: runs through the classes of (Ok/cond0)^* and beta cond1-positive */
730: allclass = FindEltofGroup(zcard, zstruc);
731:
732: p3 = cgetg(N + 1, t_COL);
733: for (i = 1; i <= N; i++) p3[i] = zero;
734:
735: vt = cgetg(N + 1, t_VEC);
736: for (i = 1; i <= N; i++)
737: {
738: p3[i] = un;
739: vt[i] = ltrace(basistoalg(nf, p3));
740: p3[i] = zero;
741: }
742:
743: s = cgetg(3, t_COMPLEX);
744: s[1] = lgetr(prec);
745: s[2] = lgetr(prec);
746: gaffect(gzero, s);
747:
748: av2 = avma;
749: for (i = 1; i <= zcard; i++)
750: {
751: beta = gun;
752: chib = gun;
753: p1 = (GEN)allclass[i];
754:
755: for (j = 1; j <= nz; j++)
756: {
757: p2 = element_powmodideal(nf, (GEN)zgen[j], (GEN)p1[j], cond0);
758: beta = element_mul(nf, beta, p2);
759: chib = gmul(chib, powgi((GEN)zchi[j], (GEN)p1[j]));
760: }
761:
762: sg = zsigne(nf, beta, cond1);
763: p2 = lift(gmul(Msign, sg));
764:
765: for (j = 1; j <= ms; j++)
766: if (gcmp1((GEN)p2[j]))
767: beta = element_mul(nf, beta, (GEN)elts[j]);
768:
769: beta = element_mul(nf, beta, muslambda);
770: tr = gmul(vt, beta);
771: tr = gmod(gmul(tr, den), den);
772:
773: gaffect(gadd(s, gmul(chib, powgi(z,tr))), s);
774:
775: avma = av2;
776: }
777:
778: classe = isprincipalray(bnr, idh);
779: s = gmul(s, ComputeImagebyChar(chi, classe, 0));
780: s = gdiv(s, gsqrt(nc, prec));
781:
782: p1 = gsubgs(gabs(s, prec), 1);
783:
784: i = expo(p1);
785: if ((i > G) && !flag)
786: err(bugparier, "ComputeArtinNumber");
787:
788: return gerepileupto(av, gmul(s, gpowgs(gneg_i(gi),q)));
789: }
790:
791: /* compute the constant W of the functional equation of
792: Lambda(chi). If flag = 1 then chi is assumed to be primitive */
793: GEN
794: bnrrootnumber(GEN bnr, GEN chi, long flag, long prec)
795: {
796: long av = avma, l, i;
797: GEN cond, condc, bnrc, chic, cyc, d, p1, p2, dtcr, Pi;
798:
799: if ((flag < 0) || (flag > 1))
800: err(flagerr,"bnrrootnumber");
801:
802: checkbnr(bnr);
803:
804: cond = gmael(bnr, 2, 1);
805: l = lg(gmael(bnr, 5, 2));
806: Pi = mppi(prec);
807:
808: if ((typ(chi) != t_VEC) || (lg(chi) != l))
809: err(talker, "incorrect character in bnrrootnumber");
810:
811: if (!flag)
812: {
813: condc = bnrconductorofchar(bnr, chi, prec);
814: if (gegal(cond, condc)) flag = 1;
815: }
816: else condc = cond;
817:
818: if (flag)
819: bnrc = bnr;
820: else
821: bnrc = buchrayinitgen((GEN)bnr[1], condc, prec);
822:
823: chic = cgetg(l, t_VEC);
824: cyc = gmael(bnr, 5, 2);
825: for (i = 1; i < l; i++)
826: chic[i] = ldiv((GEN)chi[i], (GEN)cyc[i]);
827: d = denom(chic);
828:
829: p2 = cgetg(4, t_VEC);
830: p2[1] = lmul(d, chic);
831: if (egalii(d, gdeux))
832: p2[2] = lstoi(-1);
833: else
834: p2[2] = lexp(gdiv(gmul2n(gmul(gi, Pi), 1), d), prec);
835: p2[3] = (long)d;
836:
837: dtcr = cgetg(9, t_VEC);
838: dtcr[1] = (long)chi;
839: dtcr[2] = zero;
840: dtcr[3] = (long)bnrc;
841: dtcr[4] = (long)bnr;
842: dtcr[5] = (long)p2;
843: dtcr[6] = zero;
844: dtcr[7] = (long)condc;
845:
846: p1 = GetPrimChar(chi, bnr, bnrc, prec);
847:
848: if (!p1)
849: dtcr[8] = (long)p2;
850: else
851: dtcr[8] = p1[1];
852:
853: return gerepileupto(av, ComputeArtinNumber(dtcr, 0, prec));
854: }
855:
856: /********************************************************************/
857: /* 3rd part: initialize the characters */
858: /********************************************************************/
859:
860: static GEN
861: LiftChar(GEN cyc, GEN Mat, GEN chi)
862: {
863: long lm, l, i, j, av;
864: GEN lchi, s;
865:
866: lm = lg(cyc) - 1;
867: l = lg(chi) - 1;
868:
869: lchi = cgetg(lm + 1, t_COL);
870: for (i = 1; i <= lm; i++)
871: {
872: av = avma;
873: s = gzero;
874:
875: for (j = 1; j <= l; j++)
876: s = gadd(s, gmul((GEN)chi[j], gcoeff(Mat, j, i)));
877:
878: lchi[i] = (long)gerepileupto(av, gmod(gmul(s, (GEN)cyc[i]), (GEN)cyc[i]));
879: }
880:
881: return lchi;
882: }
883:
884: /* Let chi be a character, A(chi) corresponding to the primes dividing diff
885: at s = flag. If s = 0, returns [r, A] where r is the order of vanishing
886: at s = 0 corresponding to diff. No Garbage collector */
887: static GEN
888: ComputeAChi(GEN dtcr, long flag, long prec)
889: {
890: long l, i;
891: GEN p1, ray, r, A, rep, diff, chi, bnrc;
892:
893: diff = (GEN)dtcr[6];
894: bnrc = (GEN)dtcr[3];
895: chi = (GEN)dtcr[8];
896: l = lg(diff) - 1;
897:
898: A = gun;
899: r = gzero;
900:
901: for (i = 1; i <= l; i++)
902: {
903: ray = isprincipalray(bnrc, (GEN)diff[i]);
904: p1 = ComputeImagebyChar(chi, ray, 0);
905:
906: if (flag)
907: A = gmul(A, gsub(gun, gdiv(p1, idealnorm((GEN)bnrc[1], (GEN)diff[i]))));
908: else
909: {
910: if (gcmp1(p1))
911: {
912: r = addis(r, 1);
913: A = gmul(A, glog(idealnorm((GEN)bnrc[1], (GEN)diff[i]), prec));
914: }
915: else
916: A = gmul(A, gsub(gun, p1));
917: }
918: }
919:
920: if (flag) return A;
921:
922: rep = cgetg(3, t_VEC);
923: rep[1] = (long)r;
924: rep[2] = (long)A;
925:
926: return rep;
927: }
928:
929: /* Given a list [chi, cond(chi)] of characters over Cl(bnr), compute a
930: vector dataCR containing for each character:
931: 1: chi
932: 2: the constant C(chi)
933: 3: bnr(cond(chi))
934: 4: bnr(m)
935: 5: [(c_i), z, d, pm] in bnr(m)
936: 6: diff(chi) primes dividing m but not cond(chi)
937: 7: finite part of cond(chi)
938: 8: [(c_i), z, d, pm] in bnr(cond(chi))
939: 9: [q, r1 - q, r2, rc] where
940: q = number of real places in cond(chi)
941: rc = max{r1 + r2 - q + 1, r2 + q} */
942: static GEN
943: InitChar(GEN bnr, GEN listCR, long prec)
944: {
945: GEN modul, bnf, dk, r1, r2, C, dataCR, chi, cond, Mr, chic;
946: GEN p1, p2, q;
947: long N, prec2, h, i, j, nbg, av = avma;
948:
949: modul = gmael(bnr, 2, 1);
950: Mr = gmael(bnr, 5, 2);
951: nbg = lg(Mr) - 1;
952: bnf = (GEN)bnr[1];
953: dk = gmael(bnf, 7, 3);
954: r1 = gmael3(bnf, 7, 2, 1);
955: r2 = gmael3(bnf, 7, 2, 2);
956: N = degree(gmael(bnf, 7, 1));
957: prec2 = ((prec - 2)<<1) + EXTRA_PREC;
958: C = gmul2n(gsqrt(gdiv(absi(dk), gpowgs(mppi(prec2),N)), prec2), -itos(r2));
959:
960: disable_dbg(0);
961:
962: h = lg(listCR) - 1;
963: dataCR = cgetg(h + 1, t_VEC);
964: for (i = 1; i <= h ;i++)
965: dataCR[i] = lgetg(10, t_VEC);
966:
967: q = gnorml2((GEN)modul[2]);
968: p1 = cgetg(5, t_VEC);
969: p1[1] = (long)q;
970: p1[2] = lsub(r1, q);
971: p1[3] = (long)r2;
972: p1[4] = lmax(gaddgs(gadd((GEN)p1[2], r2), 1), gadd(r2, q));
973:
974: for (i = 1; i <= h; i++)
975: {
976: GEN olddata, data = (GEN)dataCR[i];
977:
978: chi = gmael(listCR, i, 1);
979: cond = gmael(listCR, i, 2);
980:
981: /* do we already know about the invariants of chi? */
982: olddata = NULL;
983: for (j = 1; j < i; j++)
984: if (gegal(cond, gmael(listCR, j, 2)))
985: { olddata = (GEN)dataCR[j]; break; }
986:
987: /* if cond(chi) = cond(bnr) */
988: if (!olddata && gegal(cond, modul))
989: {
990: data[2] = lmul(C, gsqrt(det((GEN)cond[1]), prec2));
991: data[3] = (long)bnr;
992: data[6] = lgetg(1, t_VEC);
993: data[7] = modul[1];
994: data[9] = (long)p1;
995:
996: olddata = data;
997: }
998:
999: data[1] = (long)chi; /* the character */
1000: if (!olddata)
1001: {
1002: data[2] = lmul(C, gsqrt(det((GEN)cond[1]), prec2));
1003: data[3] = (long)buchrayinitgen(bnf, cond, prec);
1004: }
1005: else
1006: {
1007: data[2] = olddata[2]; /* constant C(chi) */
1008: data[3] = olddata[3]; /* bnr(cond(chi)) */
1009: }
1010: data[4] = (long)bnr; /* bnr(m) */
1011:
1012: chic = cgetg(nbg + 1, t_VEC);
1013: for (j = 1; j <= nbg; j++)
1014: chic[j] = ldiv((GEN)chi[j], (GEN)Mr[j]);
1015: data[5] = (long)get_Char(chic,prec); /* char associated to bnr(m) */
1016:
1017: /* compute diff(chi) and the corresponding primitive character */
1018: data[7] = cond[1];
1019: p2 = GetPrimChar(chi, bnr, (GEN)data[3], prec2);
1020: if (p2)
1021: {
1022: data[6] = p2[2];
1023: data[8] = p2[1];
1024: }
1025: else
1026: {
1027: data[6] = lgetg(1, t_VEC);
1028: data[8] = data[5];
1029: }
1030:
1031: /* compute q and store [q, r1 - q, r2] */
1032: if (!olddata)
1033: {
1034: q = gnorml2((GEN)cond[2]);
1035: p2 = cgetg(5, t_VEC);
1036: p2[1] = (long)q;
1037: p2[2] = lsubii(r1, q);
1038: p2[3] = (long)r2;
1039: p2[4] = lmax(addis(addii((GEN)p2[2], r2), 1), addii(r2, q));
1040: data[9] = (long)p2;
1041: }
1042: else
1043: data[9] = olddata[9];
1044: }
1045:
1046: disable_dbg(-1);
1047: return gerepileupto(av, gcopy(dataCR));
1048: }
1049:
1050: /* compute the list of characters to consider for AllStark and
1051: initialize the data to compute with them */
1052: static GEN
1053: InitChar0(GEN dataD, long prec)
1054: {
1055: GEN MrD, listCR, p1, chi, lchi, Surj, cond, bnr, p2, Mr, d, allCR;
1056: long hD, h, nc, i, j, lD, nbg, tnc, av = avma;
1057:
1058: Surj = gmael(dataD, 2, 3);
1059: MrD = gmael(dataD, 2, 2);
1060: bnr = (GEN)dataD[1];
1061: Mr = gmael(bnr, 5, 2);
1062: hD = itos(gmael(dataD, 2, 1));
1063: h = hD >> 1;
1064: lD = lg(MrD)-1;
1065: nbg = lg(Mr) - 1;
1066:
1067: disable_dbg(0);
1068:
1069: listCR = cgetg(h + 1, t_VEC); /* non-conjugate characters */
1070: nc = 1;
1071: allCR = cgetg(h + 1, t_VEC); /* all characters, including conjugates */
1072: tnc = 1;
1073:
1074: p1 = FindEltofGroup(hD, MrD);
1075:
1076: for (i = 1; tnc <= h; i++)
1077: {
1078: /* lift a character of D in Clk(m) */
1079: chi = (GEN)p1[i];
1080: for (j = 1; j <= lD; j++) chi[j] = ldiv((GEN)chi[j], (GEN)MrD[j]);
1081: lchi = LiftChar(Mr, Surj, chi);
1082:
1083: for (j = 1; j < tnc; j++)
1084: if (gegal(lchi, (GEN)allCR[j])) break;
1085: if (j != tnc) continue;
1086:
1087: cond = bnrconductorofchar(bnr, lchi, prec);
1088: if (gcmp0((GEN)cond[2])) continue;
1089:
1090: /* the infinite part of chi is non trivial */
1091: p2 = cgetg(3, t_VEC);
1092: p2[1] = (long)lchi;
1093: p2[2] = (long)cond;
1094: listCR[nc++] = (long)p2;
1095: allCR[tnc++] = (long)lchi;
1096:
1097: /* compute the order of chi */
1098: p2 = cgetg(nbg + 1, t_VEC);
1099: for (j = 1; j <= nbg; j++)
1100: p2[j] = ldiv((GEN)lchi[j], (GEN)Mr[j]);
1101: d = denom(p2);
1102:
1103: /* if chi is not real, add its conjugate character to allCR */
1104: if (!gegal(d, gdeux))
1105: allCR[tnc++] = (long)ConjChar(lchi, Mr);
1106: }
1107:
1108: setlg(listCR, nc);
1109: disable_dbg(-1);
1110: return gerepileupto(av, InitChar(bnr, listCR, prec));
1111: }
1112:
1113: /* recompute dataCR with the new precision */
1114: static GEN
1115: CharNewPrec(GEN dataCR, GEN nf, long prec)
1116: {
1117: GEN dk, C, p1, Pi;
1118: long av = avma, N, l, j, prec2;
1119:
1120: dk = (GEN)nf[3];
1121: N = degree((GEN)nf[1]);
1122: l = lg(dataCR) - 1;
1123: prec2 = ((prec - 2)<<1) + EXTRA_PREC;
1124:
1125: Pi = mppi(prec2);
1126:
1127: C = gsqrt(gdiv(dk, gpowgs(Pi, N)), prec2);
1128:
1129: for (j = 1; j <= l; j++)
1130: {
1131: mael(dataCR, j, 2) = lmul(C, gsqrt(det(gmael(dataCR, j, 7)), prec2));
1132:
1133: mael4(dataCR, j, 3, 1, 7) = lcopy(nf);
1134:
1135: p1 = gmael(dataCR, j, 5);
1136: p1[2] = lexp(gdiv(gmul2n(gmul(gi, Pi), 1), (GEN)p1[3]), prec);
1137:
1138: p1 = gmael(dataCR, j, 8);
1139: p1[2] = lexp(gdiv(gmul2n(gmul(gi, Pi), 1), (GEN)p1[3]), prec);
1140: }
1141:
1142: return gerepileupto(av, gcopy(dataCR));
1143: }
1144:
1145: /********************************************************************/
1146: /* 4th part: compute the coefficients an(chi) */
1147: /* */
1148: /* matan entries are arrays of ints containing the coefficients of */
1149: /* an(chi) as a polmod modulo cyclo(order(chi)) */
1150: /********************************************************************/
1151:
1152: static void
1153: _0toCoeff(int *rep, long dg)
1154: {
1155: long i;
1156: for (i=0; i<dg; i++) rep[i] = 0;
1157: }
1158:
1159: /* transform a polmod into coeff */
1160: static void
1161: Polmod2Coeff(int *rep, GEN polmod, long dg)
1162: {
1163: GEN pol = (GEN)polmod[2];
1164: long i,d = lgef(pol)-3;
1165:
1166: pol += 2;
1167: for (i=0; i<=d; i++) rep[i] = itos((GEN)pol[i]);
1168: for ( ; i<dg; i++) rep[i] = 0;
1169: }
1170:
1171: /* initialize a cl x nmax x [degs[1], ..., degs[cl] matrix of ints */
1172: /* modified to allocate ints and pointers separately since this used to
1173: break on 64bit platforms --GN1999Sep01 */
1174: static int***
1175: InitMatAn(long cl, long nmax, GEN degs, long flag)
1176: {
1177: long si,dg,i,j,k, n = nmax+1;
1178: int *c, **pj, ***A;
1179:
1180: for (si=0, i=1; i <= cl; i++)
1181: {
1182: dg = degs[i];
1183: si += dg;
1184: }
1185: A = (int***)gpmalloc((cl+1)*sizeof(int**) + cl*n*sizeof(int*));
1186: c = (int*)gpmalloc(si*n*sizeof(int));
1187: A[0] = (int**)c; /* keep it around for FreeMat() */
1188:
1189: pj = (int**)(A + (cl+1));
1190: for (i = 1; i <= cl; i++, pj+=n)
1191: {
1192: A[i] = pj; dg = degs[i];
1193: for (j = 0; j < n; j++,c+=dg)
1194: {
1195: pj[j] = c;
1196: c[0] = (j == 1 || flag);
1197: for (k = 1; k < dg; k++) c[k] = 0;
1198: }
1199: }
1200: return A;
1201: }
1202:
1203: static void
1204: FreeMat(int ***m)
1205: {
1206: free((void *)(m[0]));
1207: free((void *)m);
1208: }
1209:
1210: /* initialize coeff reduction */
1211: /* similar change --GN1999Sep01 */
1212: static int***
1213: InitReduction(GEN dataCR, GEN degs)
1214: {
1215: long av = avma,si,sp,dg,i,j, cl = lg(dataCR)-1;
1216: int *c, **pj, ***A;
1217: GEN d,polmod,pol, x = polx[0];
1218:
1219: for (si=sp=0, i=1; i <= cl; i++)
1220: {
1221: dg = degs[i];
1222: sp += dg;
1223: si += dg*dg;
1224: }
1225: A = (int***)gpmalloc((cl+1)*sizeof(int**) + sp*sizeof(int*));
1226: c = (int*)gpmalloc(si*sizeof(int));
1227: A[0] = (int**)c; /* keep it around for FreeMat() */
1228:
1229: pj = (int**)(A + (cl+1));
1230: for (i = 1; i <= cl; i++)
1231: {
1232: A[i] = pj;
1233: d = gmael3(dataCR, i, 5, 3);
1234: pol = cyclo(itos(d), 0);
1235: dg = degs[i]; /* degree(pol) */
1236: for (j = 0; j < dg; j++,c+=dg)
1237: {
1238: pj[j] = c;
1239: polmod = gmodulcp(gpowgs(x, dg + j), pol);
1240: Polmod2Coeff(c, polmod, dg);
1241: }
1242: pj += dg;
1243: }
1244: avma = av; return A;
1245: }
1246:
1247: #if 0
1248: static void
1249: pan(int ***an,long cl, long nmax, GEN degs)
1250: {
1251: long i,j,k;
1252: for (i = 1; i <= cl; i++)
1253: {
1254: long dg = degs[i];
1255: for (j = 0; j <= nmax; j++)
1256: for (k = 0; k < dg; k++) fprintferr("%d ",an[i][j][k]);
1257: }
1258: }
1259: #endif
1260:
1261: /* multiply (with reduction) a polmod with a coeff. put result in c1 */
1262: static void
1263: MulPolmodCoeff(GEN polmod, int* c1, int** reduc, long dg)
1264: {
1265: long av,i,j;
1266: int c, *c2, *c3;
1267:
1268: if (gcmp1(polmod)) return;
1269: for (i = 0; i < dg; i++)
1270: if (c1[i]) break;
1271: if (i == dg) return;
1272: av = avma;
1273: c3 = (int*)new_chunk(2*dg);
1274: c2 = (int*)new_chunk(dg);
1275: Polmod2Coeff(c2,polmod, dg);
1276:
1277: for (i = 0; i < 2*dg; i++)
1278: {
1279: c = 0;
1280: for (j = 0; j <= i; j++)
1281: if (j < dg && j > i - dg) c += c1[j] * c2[i-j];
1282: c3[i] = c;
1283: }
1284: c2 = c1;
1285: for (i = 0; i < dg; i++)
1286: {
1287: c = c3[i];
1288: for (j = 0; j < dg; j++) c += reduc[j][i] * c3[dg+j];
1289: c2[i] = c;
1290: }
1291: for ( ; i < dg; i++) c2[i] = 0;
1292: avma = av;
1293: }
1294:
1295: /* c0 <- c0 + c2 * c1 */
1296: static void
1297: AddMulCoeff(int *c0, int *c2, int* c1, int** reduc, long dg)
1298: {
1299: long av,i,j;
1300: int c, *c3;
1301:
1302: if (!c2) /* c2 == 1 */
1303: {
1304: for (i = 0; i < dg; i++) c0[i] += c1[i];
1305: return;
1306: }
1307: for (i = 0; i <= dg; i++)
1308: if (c1[i]) break;
1309: if (i > dg) return;
1310: av = avma;
1311: c3 = (int*)new_chunk(2*dg);
1312: for (i = 0; i < 2*dg; i++)
1313: {
1314: c = 0;
1315: for (j = 0; j <= i; j++)
1316: if (j < dg && j > i - dg) c += c1[j] * c2[i-j];
1317: c3[i] = c;
1318: }
1319: for (i = 0; i < dg; i++)
1320: {
1321: c = c0[i] + c3[i];
1322: for (j = 0; j < dg; j++) c += reduc[j][i] * c3[dg+j];
1323: c0[i] = c;
1324: }
1325:
1326: avma = av;
1327: }
1328:
1329: /* returns 0 if c is zero, 1 otherwise. */
1330: static long
1331: IsZero(int* c, long dg)
1332: {
1333: long i;
1334:
1335: for (i = 0; i < dg; i++)
1336: if (c[i]) return 0;
1337: return 1;
1338: }
1339:
1340: /* evaluate the coeff. No Garbage collector */
1341: static GEN
1342: EvalCoeff(GEN z, int* c, long dg)
1343: {
1344: long i,j;
1345: GEN e, r;
1346:
1347: #if 0
1348: /* standard Horner */
1349: e = stoi(c[dg - 1]);
1350: for (i = dg - 2; i >= 0; i--)
1351: e = gadd(stoi(c[i]), gmul(z, e));
1352: #else
1353: /* specific attention to sparse polynomials */
1354: e = NULL;
1355: for (i = dg-1; i >=0; i=j-1)
1356: {
1357: for (j=i; c[j] == 0; j--)
1358: if (j==0)
1359: {
1360: if (!e) return NULL;
1361: if (i!=j) z = gpuigs(z,i-j+1);
1362: return gmul(e,z);
1363: }
1364: if (e)
1365: {
1366: r = (i==j)? z: gpuigs(z,i-j+1);
1367: e = gadd(gmul(e,r), stoi(c[j]));
1368: }
1369: else
1370: e = stoi(c[j]);
1371: }
1372: #endif
1373: return e;
1374: }
1375:
1376: /* copy the n * m array matan */
1377: static void
1378: CopyCoeff(int*** a, int*** a2, long n, long m, GEN degs)
1379: {
1380: long i,j,k;
1381:
1382: for (i = 1; i <= n; i++)
1383: {
1384: long dg = degs[i];
1385: int **b = a[i], **b2 = a2[i];
1386: for (j = 0; j <= m; j++)
1387: {
1388: int *c = b[j], *c2 = b2[j];
1389: for (k = 0; k < dg; k++) c2[k] = c[k];
1390: }
1391: }
1392: return;
1393: }
1394:
1395: /* initialize the data for GetRay */
1396: static GEN
1397: InitGetRay(GEN bnr, long nmax)
1398: {
1399: long bd, i, j, l;
1400: GEN listid, listcl, id, rep, bnf, cond;
1401:
1402: bnf = (GEN)bnr[1];
1403: cond = gmael3(bnr, 2, 1, 1);
1404:
1405: if (nmax < 1000) return NULL;
1406:
1407: rep = cgetg(4, t_VEC);
1408:
1409: disable_dbg(0);
1410: bd = min(1000, nmax / 50);
1411: listid = ideallist(bnf, bd);
1412: disable_dbg(-1);
1413:
1414: listcl = cgetg(bd + 1, t_VEC);
1415: for (i = 1; i <= bd; i++)
1416: {
1417: l = lg((GEN)listid[i]) - 1;
1418: listcl[i] = lgetg(l + 1, t_VEC);
1419:
1420: for (j = 1; j <= l; j++)
1421: {
1422: id = gmael(listid, i, j);
1423: if (gcmp1(gcoeff(idealadd(bnf, id, cond), 1, 1)))
1424: mael(listcl, i, j) = (long)isprincipalray(bnr, id);
1425: }
1426: }
1427:
1428: if (DEBUGLEVEL) msgtimer("InitGetRay");
1429:
1430: rep[1] = (long)listid;
1431: rep[2] = (long)listcl;
1432: /* rep[3] != NULL iff the field is totally real */
1433: if (!cmpsi(degree(gmael(bnf, 7, 1)), gmael3(bnf, 7, 2, 1)))
1434: rep[3] = un;
1435: else
1436: rep[3] = 0;
1437:
1438: return rep;
1439: }
1440:
1441: /* compute the class of the prime ideal pr in cl(bnr) using dataray */
1442: static GEN
1443: GetRay(GEN bnr, GEN dataray, GEN pr, long prec)
1444: {
1445: long av = avma, N, n, bd, c;
1446: GEN id, tid, t2, u, alpha, p1, cl, listid, listcl, nf, cond;
1447:
1448: if (!dataray)
1449: return isprincipalray(bnr, pr);
1450:
1451: listid = (GEN)dataray[1];
1452: listcl = (GEN)dataray[2];
1453: cond = gmael3(bnr, 2, 1, 1);
1454: bd = lg(listid) - 1;
1455: nf = gmael(bnr, 1, 7);
1456: N = degree((GEN)nf[1]);
1457:
1458: if (dataray[3])
1459: t2 = gmael(nf, 5, 4);
1460: else
1461: t2 = gmael(nf, 5, 3);
1462:
1463: id = prime_to_ideal(nf, pr);
1464: tid = qf_base_change(t2, id, 1);
1465:
1466: if (dataray[3])
1467: u = lllgramint(tid);
1468: else
1469: u = lllgramintern(tid,100,1,prec);
1470:
1471: if (!u) return gerepileupto(av, isprincipalray(bnr, id));
1472:
1473: c = 1; alpha = NULL;
1474: for (c=1; c<=N; c++)
1475: {
1476: p1 = gmul(id, (GEN)u[c]);
1477: if (gcmp1(gcoeff(idealadd(nf, p1, cond), 1, 1))) { alpha = p1; break; }
1478: }
1479: if (!alpha)
1480: return gerepileupto(av, isprincipalray(bnr, pr));
1481:
1482: id = idealdivexact(nf, alpha, id);
1483:
1484: n = itos(det(id));
1485: if (n > bd)
1486: cl = isprincipalray(bnr, id);
1487: else
1488: {
1489: cl = NULL;
1490: c = 1;
1491: p1 = (GEN)listid[n];
1492: while (!cl)
1493: {
1494: if (gegal((GEN)p1[c], id))
1495: cl = gmael(listcl, n, c);
1496: c++;
1497: }
1498: }
1499:
1500: return gerepileupto(av, gsub(isprincipalray(bnr, alpha), cl));
1501: }
1502:
1503: /* correct the coefficients an(chi) according with diff(chi) in place */
1504: static void
1505: CorrectCoeff(GEN dtcr, int** an, int** reduc, long nmax, long dg)
1506: {
1507: long lg, av1, j, p, q, limk, k, l, av = avma;
1508: int ***an2, **an1, *c, *c2;
1509: GEN chi, bnrc, diff, ray, ki, ki2, pr, degs;
1510:
1511: chi = (GEN)dtcr[8];
1512: bnrc = (GEN)dtcr[3];
1513: diff = (GEN)dtcr[6];
1514: lg = lg(diff) - 1;
1515: if (!lg) return;
1516:
1517: if (DEBUGLEVEL > 2) fprintferr("diff(chi) = %Z", diff);
1518:
1519: degs = cgetg(2, t_VECSMALL); degs[1] = dg;
1520: an2 = InitMatAn(1, nmax, degs, 0); an1 = an2[1];
1521: c = (int*)new_chunk(dg);
1522: av1 = avma;
1523:
1524: for (j = 1; j <= lg; j++)
1525: {
1526: for (k = 0; k <= nmax; k++)
1527: for (l = 0; l < dg; l++) an1[k][l] = an[k][l];
1528:
1529: pr = (GEN)diff[j];
1530: ray = isprincipalray(bnrc, pr);
1531: ki = ComputeImagebyChar(chi, ray, 1);
1532: ki2 = gcopy(ki);
1533:
1534: q = p = itos(powgi((GEN)pr[1], (GEN)pr[4]));
1535: limk = nmax / q;
1536:
1537: while (q <= nmax)
1538: {
1539: if (gcmp1(ki2)) c2 = NULL; else { Polmod2Coeff(c,ki2, dg); c2 = c; }
1540: for(k = 1; k <= limk; k++)
1541: AddMulCoeff(an[k*q], c2, an1[k], reduc, dg);
1542:
1543: q *= p; limk /= p;
1544: ki2 = gmul(ki2, ki);
1545: }
1546: avma = av1;
1547: }
1548: FreeMat(an2); avma = av;
1549: }
1550:
1551: /* compute the coefficients an in the general case */
1552: static int***
1553: ComputeCoeff(GEN dataCR, long nmax, long prec)
1554: {
1555: long cl, i, j, av = avma, av2, np, q, limk, k, id, cpt = 10, dg;
1556: int ***matan, ***reduc, ***matan2, *c2;
1557: GEN c, degs, tabprem, bnf, pr, cond, ray, ki, ki2, prime, npg, bnr, dataray;
1558: byteptr dp = diffptr;
1559:
1560: bnr = gmael(dataCR, 1, 4);
1561: bnf = (GEN)bnr[1];
1562: cond = gmael3(bnr, 2, 1, 1);
1563: cl = lg(dataCR) - 1;
1564:
1565: dataray = InitGetRay(bnr, nmax);
1566:
1567: degs = GetDeg(dataCR);
1568: matan = InitMatAn(cl, nmax, degs, 0);
1569: matan2 = InitMatAn(cl, nmax, degs, 0);
1570: reduc = InitReduction(dataCR, degs);
1571: c = cgetg(cl + 1, t_VEC);
1572: for (i = 1; i <= cl; i++)
1573: c[i] = (long)new_chunk(degs[i]);
1574:
1575: if (DEBUGLEVEL > 1) fprintferr("p = ");
1576:
1577: prime = stoi(2); dp++;
1578: av2 = avma;
1579: while (*dp && (prime[2] <= nmax))
1580: {
1581: tabprem = primedec(bnf, prime);
1582: for (j = 1; j < lg(tabprem); j++)
1583: {
1584: pr = (GEN)tabprem[j];
1585: npg = powgi((GEN)pr[1], (GEN)pr[4]);
1586: if (is_bigint(npg) || (np=npg[2]) > nmax
1587: || idealval(bnf, cond, pr)) continue;
1588:
1589: CopyCoeff(matan, matan2, cl, nmax, degs);
1590: ray = GetRay(bnr, dataray, pr, prec);
1591: ki = chiideal(dataCR, ray, 1);
1592: ki2 = dummycopy(ki);
1593:
1594: for (q = np; q <= nmax; q *= np)
1595: {
1596: limk = nmax / q;
1597: for (id = 1; id <= cl; id++)
1598: {
1599: dg = degs[id];
1600: if (gcmp1((GEN)ki2[id]))
1601: c2 = NULL;
1602: else
1603: {
1604: c2 = (int*)c[id];
1605: Polmod2Coeff(c2, (GEN)ki2[id], dg);
1606: }
1607: for (k = 1; k <= limk; k++)
1608: AddMulCoeff(matan[id][k*q], c2, matan2[id][k], reduc[id], dg);
1609: ki2[id] = lmul((GEN)ki2[id], (GEN)ki[id]);
1610: }
1611: }
1612: }
1613: avma = av2;
1614: prime[2] += (*dp++);
1615: if (!*dp) err(primer1);
1616:
1617: if (DEBUGLEVEL > 1 && prime[2] > cpt)
1618: { fprintferr("%ld ", prime[2]); cpt += 10; }
1619: }
1620: if (DEBUGLEVEL > 1) fprintferr("\n");
1621:
1622: for (i = 1; i <= cl; i++)
1623: CorrectCoeff((GEN)dataCR[i], matan[i], reduc[i], nmax, degs[i]);
1624:
1625: FreeMat(matan2); FreeMat(reduc);
1626: avma = av; return matan;
1627: }
1628:
1629: /********************************************************************/
1630: /* 5th part: compute L functions at s=1 */
1631: /********************************************************************/
1632:
1633: /* if flag != 0, prec means decimal digits */
1634: static GEN
1635: get_limx(long N, long prec, GEN *pteps, long flag)
1636: {
1637: GEN gN, mu, alpha, beta, eps, A0, c1, c0, c2, lneps, limx, Pi = mppi(prec);
1638:
1639: gN = stoi(N);
1640: mu = gmul2n(gN, -1);
1641:
1642: alpha = gmul2n(stoi(N + 3), -1);
1643: beta = gpui(gdeux, gmul2n(gN, -1), 3);
1644:
1645: if (flag)
1646: *pteps = eps = gmul2n(gpowgs(dbltor(10.), -prec), -1);
1647: else
1648: *pteps = eps = gmul2n(gpowgs(dbltor(10.), (long)(-(prec-2) / pariK1)), -1);
1649:
1650: A0 = gmul2n(gun, N);
1651: A0 = gmul(A0, gpowgs(mu, N + 2));
1652: A0 = gmul(A0, gpowgs(gmul2n(Pi, 1), 1 - N));
1653: A0 = gsqrt(A0, 3);
1654:
1655: c1 = gmul(mu, gpui(beta, ginv(mu), 3));
1656: c0 = gdiv(gmul(A0, gpowgs(gmul(gdeux, Pi), N - 1)), mu);
1657: c0 = gmul(c0, gpui(c1, gsub(gun, alpha), 3));
1658: c2 = gdiv(gsub(alpha, gun), mu);
1659:
1660: lneps = glog(gdiv(c0, eps), 3);
1661: limx = gdiv(gsub(glog(lneps, 3), glog(c1, 3)), gadd(c2, gdiv(lneps, mu)));
1662: limx = gmul(gpui(gdiv(c1, lneps), mu, 3),
1663: gadd(gun, gmul(c2, gmul(mu, limx))));
1664: return limx;
1665: }
1666:
1667: static long
1668: GetBoundN0(GEN C, long N, long prec, long flag)
1669: {
1670: long av = avma, N0;
1671: GEN eps, limx = get_limx(N, prec, &eps, flag);
1672:
1673: N0 = itos(gfloor(gdiv(C, limx)));
1674: avma = av; return N0;
1675: }
1676:
1677: static long
1678: GetBoundi0(long N, long prec)
1679: {
1680: long av = avma, imin, i0, itest;
1681: GEN ftest, borneps, eps, limx = get_limx(N, prec, &eps, 0);
1682:
1683: borneps = gsqrt(gmul(limx, gpowgs(mppi(3),3)), 3);
1684: borneps = gdiv(gpowgs(stoi(5), N), gmul(eps, borneps));
1685:
1686: imin = 1;
1687: i0 = 1400;
1688: while(i0 - imin >= 4)
1689: {
1690: itest = (i0 + imin) >> 1;
1691:
1692: ftest = gpowgs(limx, itest);
1693: ftest = gmul(ftest, gpowgs(mpfactr(itest / 2, 3), N));
1694:
1695: if(gcmp(ftest, borneps) >= 0)
1696: i0 = itest;
1697: else
1698: imin = itest;
1699: }
1700: avma = av;
1701:
1702: return (i0 / 2) * 2;
1703: }
1704:
1705: /* compute the principal part at the integers s = 0, -1, -2, ..., -i0
1706: of Gamma((s+1)/2)^a Gamma(s/2)^b Gamma(s)^c / (s - z) with z = 0 and 1 */
1707: /* NOTE: this is surely not the best way to do this, but it's fast enough! */
1708: static GEN
1709: ppgamma(long a, long b, long c, long i0, long prec)
1710: {
1711: GEN cst, gamun, gamdm, an, bn, cn_evn, cn_odd, x, x2, aij, p1, cf, p2;
1712: long i, j, r, av = avma;
1713:
1714: r = max(b + c + 1, a + c);
1715:
1716: aij = cgetg(i0 + 1, t_VEC);
1717: for (i = 1; i <= i0; i++)
1718: {
1719: aij[i] = lgetg(3, t_VEC);
1720: mael(aij, i, 1) = lgetg(r + 1, t_VEC);
1721: mael(aij, i, 2) = lgetg(r + 1, t_VEC);
1722: }
1723:
1724: x = polx[0];
1725: x2 = gmul2n(x, -1);
1726:
1727: /* Euler gamma constant, values of Riemann zeta functions at
1728: positive integers */
1729: cst = cgetg(r + 2, t_VEC);
1730: cst[1] = (long)mpeuler(prec);
1731: for (i = 2; i <= r + 1; i++)
1732: cst[i] = (long)gzeta(stoi(i), prec);
1733:
1734: /* the expansion of log(Gamma(s)) at s = 1 */
1735: gamun = cgetg(r + 2, t_SER);
1736: gamun[1] = evalsigne(1) | evalvalp(0) | evalvarn(0);
1737: gamun[2] = zero;
1738: for (i = 1; i <= r; i++)
1739: {
1740: gamun[i + 2] = ldivgs((GEN)cst[i], i);
1741: if (i%2) gamun[i + 2] = lneg((GEN)gamun[i + 2]);
1742: }
1743:
1744: /* the expansion of log(Gamma(s)) at s = 1/2 */
1745: gamdm = cgetg(r + 2, t_SER);
1746: gamdm[1] = evalsigne(1) | evalvalp(0) | evalvarn(0);
1747: gamdm[2] = (long)mplog(gsqrt(mppi(prec), prec));
1748: gamdm[3] = lneg(gadd(gmul2n(glog(gdeux, prec), 1), (GEN)cst[1]));
1749: for (i = 2; i <= r; i++)
1750: gamdm[i + 2] = lmul((GEN)gamun[i + 2], subis(shifti(gun, i), 1));
1751:
1752: gamun = gexp(gamun, prec);
1753: gamdm = gexp(gamdm, prec);
1754:
1755: /* We simplify to get one of the following two expressions */
1756:
1757: /* Case 1 (b > a): sqrt{Pi}^a 2^{a - as} Gamma(s/2)^{b-a} Gamma(s)^{a + c} */
1758: if (b > a)
1759: {
1760: cf = gpui(mppi(prec), gmul2n(stoi(a), -1), prec);
1761:
1762: /* an is the expansion of Gamma(x)^{a+c} */
1763: an = gpowgs(gdiv(gamun, x), a + c);
1764:
1765: /* bn is the expansion of 2^{a - ax} */
1766: bn = gpowgs(gpow(gdeux, gsubsg(1, x), prec), a);
1767:
1768: /* cn_evn is the expansion of Gamma(x/2)^{b-a} */
1769: cn_evn = gpowgs(gdiv(gsubst(gamun, 0, x2), x2), b - a);
1770:
1771: /* cn_odd is the expansion of Gamma((x-1)/2)^{b-a} */
1772: cn_odd = gpowgs(gdiv(gsubst(gamdm, 0, x2), gsub(x2, ghalf)), b - a);
1773:
1774: for (i = 0; i < i0/2; i++)
1775: {
1776: p1 = gmul(cf, gmul(an, gmul(bn, cn_evn)));
1777:
1778: p2 = gdiv(p1, gsubgs(x, 2*i));
1779: for (j = 1; j <= r; j++)
1780: mael3(aij, 2*i + 1, 1, j) = (long)polcoeff0(p2, -j, 0);
1781:
1782: p2 = gdiv(p1, gsubgs(x, 2*i + 1));
1783: for (j = 1; j <= r; j++)
1784: mael3(aij, 2*i + 1, 2, j) = (long)polcoeff0(p2, -j, 0);
1785:
1786: /* an(x-s-1) = an(x-s) / (x-s-1)^{a+c} */
1787: an = gdiv(an, gpowgs(gsubgs(x, 2*i + 1), a + c));
1788:
1789: /* bn(x-s-1) = 2^a bn(x-s) */
1790: bn = gmul2n(bn, a);
1791:
1792: /* cn_evn(x-s-2) = cn_evn(x-s) / (x/2 - (s+2)/2)^{b-a} */
1793: cn_evn = gdiv(cn_evn, gpowgs(gsubgs(x2, i + 1), b - a));
1794:
1795: p1 = gmul(cf, gmul(an, gmul(bn, cn_odd)));
1796:
1797: p2 = gdiv(p1, gsubgs(x, 2*i + 1));
1798: for (j = 1; j <= r; j++)
1799: mael3(aij, 2*i + 2, 1, j) = (long)polcoeff0(p2, -j, 0);
1800:
1801: p2 = gdiv(p1, gsubgs(x, 2*i + 2));
1802: for (j = 1; j <= r; j++)
1803: mael3(aij, 2*i + 2, 2, j) = (long)polcoeff0(p2, -j, 0);
1804:
1805: an = gdiv(an, gpowgs(gsubgs(x, 2*i + 2), a + c));
1806: bn = gmul2n(bn, a);
1807:
1808: /* cn_odd(x-s-2) = cn_odd(x-s) / (x/2 - (s+2)/2)^{b-a} */
1809: cn_odd = gdiv(cn_odd, gpowgs(gsub(x2, gaddgs(ghalf, i + 1)), b - a));
1810: }
1811: }
1812: else
1813: /* Case 2 (b <= a): sqrt{Pi}^b 2^{b - bs} Gamma((s+1)/2)^{a-b}
1814: Gamma(s)^{b + c) */
1815: {
1816: cf = gpui(mppi(prec), gmul2n(stoi(b), -1), prec);
1817:
1818: /* an is the expansion of Gamma(x)^{b+c} */
1819: an = gpowgs(gdiv(gamun, x), b + c);
1820:
1821: /* bn is the expansion of 2^{b - bx} */
1822: bn = gpowgs(gpow(gdeux, gsubsg(1, x), prec), b);
1823:
1824: /* cn_evn is the expansion of Gamma((x+1)/2)^{a-b} */
1825: cn_evn = gpowgs(gsubst(gamdm, 0, x2), a - b);
1826:
1827: /* cn_odd is the expansion of Gamma(x/2)^{a-b} */
1828: cn_odd = gpowgs(gdiv(gsubst(gamun, 0, x2), x2), a - b);
1829:
1830: for (i = 0; i < i0/2; i++)
1831: {
1832: p1 = gmul(cf, gmul(an, gmul(bn, cn_evn)));
1833:
1834: p2 = gdiv(p1, gsubgs(x, 2*i));
1835: for (j = 1; j <= r; j++)
1836: mael3(aij, 2*i + 1, 1, j) = (long)polcoeff0(p2, -j, 0);
1837:
1838: p2 = gdiv(p1, gsubgs(x, 2*i + 1));
1839: for (j = 1; j <= r; j++)
1840: mael3(aij, 2*i + 1, 2, j) = (long)polcoeff0(p2, -j, 0);
1841:
1842: /* an(x-s-1) = an(x-s) / (x-s-1)^{b+c} */
1843: an = gdiv(an, gpowgs(gsubgs(x, 2*i + 1), b + c));
1844:
1845: /* bn(x-s-1) = 2^b bn(x-s) */
1846: bn = gmul2n(bn, b);
1847:
1848: /* cn_evn(x-s-2) = cn_evn(x-s) / (x/2 - (s+1)/2)^{a-b} */
1849: cn_evn = gdiv(cn_evn, gpowgs(gsub(x2, gaddgs(ghalf, i)), a - b));
1850:
1851: p1 = gmul(cf, gmul(an, gmul(bn, cn_odd)));
1852:
1853: p2 = gdiv(p1, gsubgs(x, 2*i + 1));
1854: for (j = 1; j <= r; j++)
1855: mael3(aij, 2*i + 2, 1, j) = (long)polcoeff0(p2, -j, 0);
1856:
1857: p2 = gdiv(p1, gsubgs(x, 2*i + 2));
1858: for (j = 1; j <= r; j++)
1859: mael3(aij, 2*i + 2, 2, j) = (long)polcoeff0(p2, -j, 0);
1860:
1861: an = gdiv(an, gpowgs(gsubgs(x, 2*i + 2), b + c));
1862: bn = gmul2n(bn, b);
1863:
1864: /* cn_odd(x-s-2) = cn_odd(x-s) / (x/2 - (s+1)/2)^{a-b} */
1865: cn_odd = gdiv(cn_odd, gpowgs(gsubgs(x2, i + 1), a - b));
1866: }
1867: }
1868:
1869: return gerepileupto(av, gcopy(aij));
1870: }
1871:
1872: static GEN
1873: GetST(GEN dataCR, long prec)
1874: {
1875: GEN N0, CC, bnr, bnf, Pi, racpi, C, cond, aij, B, S, T, csurn, lncsurn;
1876: GEN degs, p1, p2, nsurc, an, rep, powlncn, powracpi;
1877: long i, j, k, n, av = avma, av1, av2, N, hk, fj, id, prec2, i0, nmax;
1878: long a, b, c, rc1, rc2, r;
1879: int ***matan;
1880:
1881: if (DEBUGLEVEL) timer2();
1882: bnr = gmael(dataCR, 1, 4);
1883: bnf = (GEN)bnr[1];
1884: N = degree(gmael(bnf, 7, 1));
1885: hk = lg(dataCR) - 1;
1886: prec2 = ((prec - 2)<<1) + EXTRA_PREC;
1887:
1888: Pi = mppi(prec2);
1889: racpi = gsqrt(Pi, prec2);
1890:
1891: C = cgetg(hk + 1, t_VEC);
1892: cond = cgetg(hk + 1, t_VEC);
1893: N0 = new_chunk(hk+1);
1894: CC = new_chunk(hk+1);
1895: nmax = 0;
1896: for (i = 1; i <= hk; i++)
1897: {
1898: C[i] = mael(dataCR, i, 2);
1899:
1900: p1 = cgetg(3, t_VEC);
1901: p1[1] = mael(dataCR, i, 7);
1902: p1[2] = mael(dataCR, i, 9);
1903: cond[i] = (long)p1;
1904:
1905: N0[i] = GetBoundN0((GEN)C[i], N, prec, 0);
1906: if (nmax < N0[i]) nmax = N0[i];
1907: }
1908:
1909: i0 = GetBoundi0(N, prec);
1910:
1911: if (nmax >= VERYBIGINT)
1912: err(talker, "Too many coefficients (%ld) in GetST: computation impossible", nmax);
1913:
1914: if(DEBUGLEVEL > 1) fprintferr("nmax = %ld and i0 = %ld\n", nmax, i0);
1915:
1916: matan = ComputeCoeff(dataCR, nmax, prec);
1917: degs = GetDeg(dataCR);
1918: if (DEBUGLEVEL) msgtimer("Compute an");
1919:
1920: p1 = cgetg(3, t_COMPLEX);
1921: p1[1] = lgetr(prec2);
1922: p1[2] = lgetr(prec2);
1923: gaffect(gzero, p1);
1924:
1925: S = cgetg(hk + 1, t_VEC);
1926: T = cgetg(hk + 1, t_VEC);
1927: for (id = 1; id <= hk; id++)
1928: {
1929: S[id] = lcopy(p1);
1930: T[id] = lcopy(p1);
1931: for (k = 1; k < id; k++)
1932: if (gegal((GEN)cond[id], (GEN)cond[k])) break;
1933: CC[id] = k;
1934: }
1935:
1936: powracpi = cgetg(hk + 1, t_VEC);
1937: for (j = 1; j <= hk; j++)
1938: powracpi[j] = (long)gpow(racpi, gmael3(dataCR, j, 9, 2), prec2);
1939:
1940: av1 = avma;
1941: if (DEBUGLEVEL > 1) fprintferr("n = ");
1942:
1943: for (id = 1; id <= hk; id++)
1944: {
1945: if (CC[id] != id) continue;
1946: p2 = gmael(dataCR, id, 9);
1947: a = itos((GEN)p2[1]);
1948: b = itos((GEN)p2[2]);
1949: c = itos((GEN)p2[3]);
1950: aij = ppgamma(a, b, c, i0, prec2);
1951: rc1 = a + c;
1952: rc2 = b + c; r = max(rc2 + 1, rc1);
1953: av2 = avma;
1954:
1955: for (n = 1; n <= N0[id]; n++)
1956: {
1957: for (k = 1; k <= hk; k++)
1958: if (CC[k] == id && !IsZero(matan[k][n], degs[k])) break;
1959: if (k > hk) continue;
1960:
1961: csurn = gdivgs((GEN)C[id], n);
1962: nsurc = ginv(csurn);
1963:
1964: B = cgetg(r + 1, t_VEC);
1965: lncsurn = glog(csurn, prec2);
1966: powlncn = gun;
1967: fj = 1;
1968:
1969: p1 = gzero;
1970: p2 = gzero;
1971: for (j = 1; j <= r; j++)
1972: {
1973: if (j > 2) fj = fj * (j - 1);
1974:
1975: B[j] = ldivgs(powlncn, fj);
1976: p1 = gadd(p1, gmul((GEN)B[j], gmael3(aij, i0, 2, j)));
1977: p2 = gadd(p2, gmul((GEN)B[j], gmael3(aij, i0, 1, j)));
1978:
1979: powlncn = gmul(powlncn, lncsurn);
1980: }
1981: for (i = i0 - 1; i > 1; i--)
1982: {
1983: p1 = gmul(p1, nsurc);
1984: p2 = gmul(p2, nsurc);
1985: for (j = i%2? rc2: rc1; j; j--)
1986: {
1987: p1 = gadd(p1, gmul((GEN)B[j], gmael3(aij, i, 2, j)));
1988: p2 = gadd(p2, gmul((GEN)B[j], gmael3(aij, i, 1, j)));
1989: }
1990: }
1991: p1 = gmul(p1, nsurc);
1992: p2 = gmul(p2, nsurc);
1993: for (j = 1; j <= r; j++)
1994: {
1995: p1 = gadd(p1, gmul((GEN)B[j], gmael3(aij, 1, 2, j)));
1996: p2 = gadd(p2, gmul((GEN)B[j], gmael3(aij, 1, 1, j)));
1997: }
1998:
1999: p1 = gadd(p1, gmul(csurn, (GEN)powracpi[id]));
2000:
2001: for (j = 1; j <= hk; j++)
2002: if (CC[j] == id &&
2003: (an = EvalCoeff(gmael3(dataCR, j, 5, 2), matan[j][n], degs[j])))
2004: {
2005: gaffect(gadd((GEN)S[j], gmul(p1, an)), (GEN)S[j]);
2006: gaffect(gadd((GEN)T[j], gmul(p2, gconj(an))), (GEN)T[j]);
2007: }
2008: avma = av2;
2009: if (DEBUGLEVEL > 1 && n%100 == 0) fprintferr("%ld ", n);
2010: }
2011: avma = av1;
2012: }
2013: FreeMat(matan);
2014:
2015: if (DEBUGLEVEL > 1) fprintferr("\n");
2016: if (DEBUGLEVEL) msgtimer("Compute S&T");
2017:
2018: rep = cgetg(3, t_VEC);
2019: rep[1] = (long)S;
2020: rep[2] = (long)T;
2021: return gerepileupto(av, gcopy(rep));
2022: }
2023:
2024: /* Given datachi, S(chi) and T(chi), return L(1, chi) if fl = 1,
2025: or [r(chi), c(chi)] where r(chi) is the rank of chi and c(chi)
2026: is given by L(s, chi) = c(chi).s^r(chi) at s = 0 if fl = 0.
2027: if fl2 = 1, adjust the value to get L_S(s, chi). */
2028: static GEN
2029: GetValue(GEN datachi, GEN S, GEN T, long fl, long fl2, long prec)
2030: {
2031: GEN W, A, q, b, c, d, rchi, cf, VL, rep, racpi, nS, nT;
2032: long av = avma;
2033:
2034: racpi = gsqrt(mppi(prec), prec);
2035: W = ComputeArtinNumber(datachi, 0, prec);
2036: A = ComputeAChi(datachi, fl, prec);
2037:
2038: d = gmael(datachi, 8, 3);
2039:
2040: q = gmael(datachi, 9, 1);
2041: b = gmael(datachi, 9, 2);
2042: c = gmael(datachi, 9, 3);
2043:
2044: rchi = addii(b, c);
2045:
2046: if (!fl)
2047: {
2048: cf = gmul2n(gpow(racpi, q, 0), itos(b));
2049:
2050: nS = gdiv(gconj(S), cf);
2051: nT = gdiv(gconj(T), cf);
2052:
2053: /* VL = W(chi).S(conj(chi)) + T(chi)) / (sqrt(Pi)^q 2^{r1 - q}) */
2054: VL = gadd(gmul(W, nS), nT);
2055: if (cmpis(d, 3) < 0) VL = greal(VL);
2056:
2057: if (fl2)
2058: {
2059: VL = gmul((GEN)A[2], VL);
2060: rchi = gadd(rchi, (GEN)A[1]);
2061: }
2062:
2063: rep = cgetg(3, t_VEC);
2064: rep[1] = (long)rchi;
2065: rep[2] = (long)VL;
2066: }
2067: else
2068: {
2069: cf = gmul((GEN)datachi[2], gpow(racpi, b, 0));
2070:
2071: /* VL = S(chi) + W(chi).T(chi)) / (C(chi) sqrt(Pi)^{r1 - q}) */
2072: rep = gdiv(gadd(S, gmul(W, T)), cf);
2073: if (cmpis(d, 3) < 0) rep = greal(rep);
2074:
2075: if (fl2) rep = gmul(A, rep);
2076: }
2077:
2078: return gerepileupto(av, gcopy(rep));
2079: }
2080:
2081: /* return the order and the first non-zero term of L(s, chi0)
2082: at s = 0. If flag = 1, adjust the value to get L_S(s, chi0). */
2083: static GEN
2084: GetValue1(GEN bnr, long flag, long prec)
2085: {
2086: GEN bnf, hk, Rk, wk, c, r, r1, r2, rep, mod0, diff;
2087: long i, l, av = avma;
2088:
2089: bnf = (GEN)bnr[1];
2090:
2091: r1 = gmael3(bnf, 7, 2, 1);
2092: r2 = gmael3(bnf, 7, 2, 2);
2093:
2094: hk = gmael3(bnf, 8, 1, 1);
2095: Rk = gmael(bnf, 8, 2);
2096: wk = gmael3(bnf, 8, 4, 1);
2097:
2098:
2099: c = gneg_i(gdiv(gmul(hk, Rk), wk));
2100: r = subis(addii(r1, r2), 1);
2101:
2102: if (flag)
2103: {
2104: mod0 = gmael3(bnr, 2, 1, 1);
2105: diff = (GEN)idealfactor((GEN)bnf[7], mod0)[1];
2106:
2107: l = lg(diff) - 1;
2108: r = addis(r, l);
2109: for (i = 1; i <= l; i++)
2110: c = gmul(c, glog(idealnorm((GEN)bnf[7], (GEN)diff[i]), prec));
2111: }
2112:
2113: rep = cgetg(3, t_VEC);
2114: rep[1] = (long)r;
2115: rep[2] = (long)c;
2116:
2117: return gerepileupto(av, gcopy(rep));
2118: }
2119:
2120: /********************************************************************/
2121: /* 6th part: recover the coefficients */
2122: /********************************************************************/
2123:
2124: static long
2125: TestOne(GEN plg, GEN beta, GEN B, long v, long G, long N)
2126: {
2127: long j;
2128: GEN p1;
2129:
2130: p1 = gsub(beta, (GEN)plg[v]);
2131: if (expo(p1) >= G) return 0;
2132:
2133: for (j = 1; j <= N; j++)
2134: if (j != v)
2135: {
2136: p1 = gabs((GEN)plg[j], DEFAULTPREC);
2137: if (gcmp(p1, B) > 0) return 0;
2138: }
2139: return 1;
2140: }
2141:
2142: /* Using linear dependance relations */
2143: static GEN
2144: RecCoeff2(GEN nf, GEN beta, GEN B, long v, long prec)
2145: {
2146: long N, G, i, bacmin, bacmax, av = avma, av2;
2147: GEN vec, velt, p1, cand, M, plg, pol, cand2;
2148:
2149: M = gmael(nf, 5, 1);
2150: pol = (GEN)nf[1];
2151: N = degree(pol);
2152: vec = gtrans((GEN)gtrans(M)[v]);
2153: velt = (GEN)nf[7];
2154:
2155: G = min( - 20, - bit_accuracy(prec) >> 4);
2156:
2157: p1 = cgetg(2, t_VEC);
2158:
2159: p1[1] = lneg(beta);
2160: vec = concat(p1, vec);
2161:
2162: p1[1] = zero;
2163: velt = concat(p1, velt);
2164:
2165: bacmin = (long)(.225 * bit_accuracy(prec));
2166: bacmax = (long)(.315 * bit_accuracy(prec));
2167:
2168: av2 = avma;
2169:
2170: for (i = bacmax; i >= bacmin; i--)
2171: {
2172: p1 = lindep2(vec, i);
2173:
2174: if (signe((GEN)p1[1]))
2175: {
2176: p1 = ground(gdiv(p1, (GEN)p1[1]));
2177: cand = gmodulcp(gmul(velt, gtrans(p1)), pol);
2178: cand2 = algtobasis(nf, cand);
2179: plg = gmul(M, cand2);
2180:
2181: if (TestOne(plg, beta, B, v, G, N))
2182: return gerepileupto(av, gcopy(cand));
2183: }
2184: avma = av2;
2185: }
2186: return NULL;
2187: }
2188:
2189: /* Using Cohen's method */
2190: static GEN
2191: RecCoeff3(GEN nf, GEN beta, GEN B, long v, long prec)
2192: {
2193: GEN A, M, nB, cand, sol, p1, plg, B2, C2, max = stoi(10000);
2194: GEN beta2, eps, nf2;
2195: long N, G, i, j, k, l, ct = 0, av = avma, prec2;
2196:
2197: N = degree((GEN)nf[1]);
2198: G = min( - 20, - bit_accuracy(prec) >> 4);
2199:
2200: eps = gpowgs(stoi(10), - max(8, (G >> 1)));
2201:
2202: p1 = gceil(gdiv(glog(B, DEFAULTPREC), dbltor(2.3026)));
2203: prec2 = max((prec << 1) - 2, (long)(itos(p1) * pariK1 + BIGDEFAULTPREC));
2204: nf2 = nfnewprec(nf, prec2);
2205: beta2 = gprec_w(beta, prec2);
2206:
2207: LABrcf: ct++;
2208: B2 = sqri(B);
2209: C2 = gdiv(B2, gsqr(eps));
2210:
2211: M = gmael(nf2, 5, 1);
2212:
2213: A = cgetg(N+2, t_MAT);
2214: for (i = 1; i <= N+1; i++)
2215: A[i] = lgetg(N+2, t_COL);
2216:
2217: coeff(A, 1, 1) = ladd(gmul(C2, gsqr(beta2)), B2);
2218: for (j = 2; j <= N+1; j++)
2219: {
2220: p1 = gmul(C2, gmul(gneg_i(beta2), gcoeff(M, v, j-1)));
2221: coeff(A, 1, j) = coeff(A, j, 1) = (long)p1;
2222: }
2223: for (i = 2; i <= N+1; i++)
2224: for (j = 2; j <= N+1; j++)
2225: {
2226: p1 = gzero;
2227: for (k = 1; k <= N; k++)
2228: {
2229: GEN p2 = gmul(gcoeff(M, k, j-1), gcoeff(M, k, i-1));
2230: if (k == v) p2 = gmul(C2, p2);
2231: p1 = gadd(p1,p2);
2232: }
2233: coeff(A, i, j) = coeff(A, j, i) = (long)p1;
2234: }
2235:
2236: nB = mulsi(N+1, B2);
2237: cand = fincke_pohst(A, nB, max, 3, prec2, NULL);
2238:
2239: if (!cand)
2240: {
2241: if (ct > 3) { avma = av; return NULL; }
2242:
2243: prec2 = (prec2 << 1) - 2;
2244: if (DEBUGLEVEL >= 2) err(warnprec,"RecCoeff", prec2);
2245: nf2 = nfnewprec(nf2, prec2);
2246: beta2 = gprec_w(beta2, prec2);
2247: goto LABrcf;
2248: }
2249:
2250: cand = (GEN)cand[3];
2251: l = lg(cand) - 1;
2252:
2253: if (DEBUGLEVEL >= 2)
2254: fprintferr("Found %ld vector(s) in RecCoeff3 \n", l);
2255:
2256: sol = cgetg(N + 1, t_COL);
2257: for (i = 1; i <= l; i++)
2258: {
2259: p1 = (GEN)cand[i];
2260: if (gcmp1(mpabs((GEN)p1[1])))
2261: {
2262: for (j = 1; j <= N; j++)
2263: sol[j] = lmulii((GEN)p1[1], (GEN)p1[j + 1]);
2264: plg = gmul(M, sol);
2265: if (TestOne(plg, beta, B, v, G, N))
2266: return gerepileupto(av, basistoalg(nf, sol));
2267: }
2268: }
2269: avma = av; return NULL;
2270: }
2271:
2272: /* Attempts to find an algebraic integer close to beta at the place v
2273: and less than B at all the others */
2274: GEN
2275: RecCoeff(GEN nf, GEN pol, long v, long prec)
2276: {
2277: long av = avma, j, G, cl = lgef(pol)-3;
2278: GEN p1, beta, Bmax = stoi(10000);
2279:
2280: /* if precision(pol) is too low, abort */
2281: for (j = 2; j <= cl+1; j++)
2282: {
2283: p1 = (GEN)pol[j];
2284: G = bit_accuracy(gprecision(p1)) - gexpo(p1);
2285: if (G < 34) { avma = av; return NULL; }
2286: }
2287:
2288: pol = dummycopy(pol);
2289: for (j = 2; j <= cl+1; j++)
2290: {
2291: GEN bound = binome(stoi(cl), j - 2);
2292: bound = shifti(bound, cl + 2 - j);
2293:
2294: if (DEBUGLEVEL > 1) fprintferr("In RecCoeff with B = %Z\n", bound);
2295:
2296: beta = greal((GEN)pol[j]);
2297: p1 = RecCoeff2(nf, beta, bound, v, prec);
2298: if (!p1)
2299: {
2300: if (cmpii(bound, Bmax) > 0) bound = Bmax;
2301: p1 = RecCoeff3(nf, beta, bound, v, prec);
2302: if (!p1) return NULL;
2303: }
2304: pol[j] = (long)p1;
2305: }
2306: pol[j] = un;
2307: return gerepileupto(av, gcopy(pol));
2308: }
2309:
2310: /*******************************************************************/
2311: /*******************************************************************/
2312: /* */
2313: /* Computation of class fields of */
2314: /* real quadratic fields using Stark units */
2315: /* */
2316: /*******************************************************************/
2317: /*******************************************************************/
2318:
2319: /* compute the coefficients an for the quadratic case */
2320: static int***
2321: computean(GEN dtcr, long nmax, long prec)
2322: {
2323: long i, j, cl, q, cp, al, v1, v2, v, fldiv, av, av1;
2324: int ***matan, ***reduc;
2325: GEN bnf, ideal, dk, degs, idno, p1, prime, chi, qg, chi1, chi2;
2326: GEN chi11, chi12, bnr, pr, pr1, pr2, xray, xray1, xray2, dataray;
2327: byteptr dp = diffptr;
2328:
2329: av = avma;
2330:
2331: cl = lg(dtcr) - 1;
2332: degs = GetDeg(dtcr);
2333:
2334: matan = InitMatAn(cl, nmax, degs, 1);
2335: reduc = InitReduction(dtcr, degs);
2336:
2337: bnr = gmael(dtcr, 1, 4); bnf = (GEN)bnr[1];
2338: dataray = InitGetRay(bnr, nmax);
2339:
2340: ideal = gmael3(bnr, 2, 1, 1);
2341: idno = idealnorm(bnf, ideal);
2342: dk = gmael(bnf, 7, 3);
2343:
2344: prime = stoi(2);
2345: dp++;
2346:
2347: av1 = avma;
2348:
2349: while (*dp && prime[2] <= nmax)
2350: {
2351: qg = prime;
2352: al = 1;
2353:
2354: switch (krogs(dk, prime[2]))
2355: {
2356: /* prime is inert */
2357: case -1:
2358: fldiv = divise(idno, prime);
2359:
2360: if (!fldiv)
2361: {
2362: xray = GetRay(bnr, dataray, prime, prec);
2363: chi = chiideal(dtcr, xray, 1);
2364: chi1 = dummycopy(chi);
2365: }
2366:
2367: while(cmpis(qg, nmax) <= 0)
2368: {
2369: q = qg[2];
2370:
2371: for (cp = 1, i = q; i <= nmax; i += q, cp++)
2372: if(cp % prime[2])
2373: {
2374: if (fldiv || al%2)
2375: for (j = 1; j <= cl; j++)
2376: _0toCoeff(matan[j][i], degs[j]);
2377: else
2378: for (j = 1; j <= cl; j++)
2379: MulPolmodCoeff((GEN)chi[j], matan[j][i], reduc[j], degs[j]);
2380: }
2381:
2382: qg = mulsi(q, prime);
2383: al++;
2384:
2385: if (al%2 && !fldiv)
2386: for (j = 1; j <= cl; j++)
2387: chi[j] = lmul((GEN)chi[j], (GEN)chi1[j]);
2388: }
2389: break;
2390:
2391: /* prime is ramified */
2392: case 0:
2393: fldiv = divise(idno, prime);
2394:
2395: if (!fldiv)
2396: {
2397: pr = (GEN)primedec(bnf, prime)[1];
2398: xray = GetRay(bnr, dataray, pr, prec);
2399: chi = chiideal(dtcr, xray, 1);
2400: chi2 = dummycopy(chi);
2401: }
2402:
2403: while(cmpis(qg, nmax) <= 0)
2404: {
2405: q = qg[2];
2406:
2407: for (cp = 1, i = q; i <= nmax; i += q, cp++)
2408: if(cp % prime[2])
2409: {
2410: if (fldiv)
2411: for(j = 1; j <= cl; j++)
2412: _0toCoeff(matan[j][i], degs[j]);
2413: else
2414: {
2415: for(j = 1; j <= cl; j++)
2416: MulPolmodCoeff((GEN)chi[j], matan[j][i], reduc[j], degs[j]);
2417: }
2418: }
2419:
2420: qg = mulsi(q, prime);
2421: al++;
2422:
2423: if (cmpis(qg, nmax) <= 0 && !fldiv)
2424: for (j = 1; j <= cl; j++)
2425: chi[j] = lmul((GEN)chi[j], (GEN)chi2[j]);
2426: }
2427: break;
2428:
2429: /* prime is split */
2430: case 1:
2431: p1 = primedec(bnf, prime);
2432: pr1 = (GEN)p1[1];
2433: pr2 = (GEN)p1[2];
2434: v1 = idealval(bnf, ideal, pr1);
2435: v2 = idealval(bnf, ideal, pr2);
2436:
2437: if (v1 + v2 == 0)
2438: {
2439: xray1 = GetRay(bnr, dataray, pr1, prec);
2440: xray2 = GetRay(bnr, dataray, pr2, prec);
2441: chi11 = chiideal(dtcr, xray1, 1);
2442: chi12 = chiideal(dtcr, xray2, 1);
2443:
2444: chi1 = gadd(chi11, chi12);
2445: chi2 = dummycopy(chi12);
2446:
2447: while(cmpis(qg, nmax) <= 0)
2448: {
2449: q = qg[2];
2450:
2451: for (cp = 1, i = q; i <= nmax; i += q, cp++)
2452: if(cp % prime[2])
2453: for(j = 1; j <= cl; j++)
2454: MulPolmodCoeff((GEN)chi1[j], matan[j][i], reduc[j], degs[j]);
2455:
2456: qg = mulsi(q, prime);
2457: al++;
2458:
2459: if(cmpis(qg, nmax) <= 0)
2460: for (j = 1; j <= cl; j++)
2461: {
2462: chi2[j] = lmul((GEN)chi2[j], (GEN)chi12[j]);
2463: chi1[j] = ladd((GEN)chi2[j], gmul((GEN)chi1[j], (GEN)chi11[j]));
2464: }
2465: }
2466: }
2467: else
2468: {
2469: if (v1) { v = v2; pr = pr2; } else { v = v1; pr = pr1; }
2470:
2471: if (v == 0)
2472: {
2473: xray = GetRay(bnr, dataray, pr, prec);
2474: chi1 = chiideal(dtcr, xray, 1);
2475: chi = gcopy(chi1);
2476: }
2477:
2478: while(cmpis(qg, nmax) <= 0)
2479: {
2480: q = qg[2];
2481: for (cp = 1, i = q; i <= nmax; i += q, cp++)
2482: if(cp % prime[2])
2483: {
2484: if (v)
2485: for (j = 1; j <= cl; j++)
2486: _0toCoeff(matan[j][i], degs[j]);
2487: else
2488: for (j = 1; j <= cl; j++)
2489: MulPolmodCoeff((GEN)chi[j], matan[j][i], reduc[j], degs[j]);
2490: }
2491:
2492: qg = mulii(qg, prime);
2493: al++;
2494:
2495: if (!v && (cmpis(qg, nmax) <= 0))
2496: for (j = 1; j <= cl; j++)
2497: chi[j] = lmul((GEN)chi[j], (GEN)chi1[j]);
2498: }
2499: }
2500: break;
2501: }
2502:
2503: prime[2] += (*dp++);
2504:
2505: avma = av1;
2506: }
2507:
2508: for (i = 1; i <= cl; i++)
2509: CorrectCoeff((GEN)dtcr[i], matan[i], reduc[i], nmax, degs[i]);
2510:
2511: FreeMat(reduc);
2512: avma = av; return matan;
2513: }
2514:
2515: /* compute S and T for the quadratic case */
2516: static GEN
2517: QuadGetST(GEN data, long prec)
2518: {
2519: long av = avma, n, j, nmax, cl, av1, av2, k;
2520: int ***matan;
2521: GEN nn, C, p1, p2, c2, cexp, cn, v, veclprime2, veclprime1;
2522: GEN dtcr, cond, rep, an, cf, degs, veint1;
2523:
2524: dtcr = (GEN)data[5];
2525: cl = lg(dtcr) - 1;
2526: degs = GetDeg(dtcr);
2527:
2528: cf = gmul2n(mpsqrt(mppi(prec)), 1);
2529: C = cgetg(cl+1, t_VEC);
2530: cond = cgetg(cl+1, t_VEC);
2531: c2 = cgetg(cl + 1, t_VEC);
2532: nn = new_chunk(cl+1);
2533: nmax = 0;
2534: for (j = 1; j <= cl; j++)
2535: {
2536: C[j] = mael(dtcr, j, 2);
2537: c2[j] = ldivsg(2, (GEN)C[j]);
2538: cond[j] = mael(dtcr, j, 7);
2539: nn[j] = (long)(bit_accuracy(prec) * gtodouble((GEN)C[j]) * 0.35);
2540:
2541: nmax = max(nmax, nn[j]);
2542: }
2543:
2544: if (nmax >= VERYBIGINT)
2545: err(talker, "Too many coefficients (%ld) in QuadGetST: computation impossible", nmax);
2546:
2547: if (DEBUGLEVEL >= 2)
2548: fprintferr("nmax = %ld\n", nmax);
2549:
2550: /* compute the coefficients */
2551: matan = computean(dtcr, nmax, prec);
2552: if (DEBUGLEVEL) msgtimer("Compute an");
2553:
2554: /* allocate memory for the answer */
2555: rep = cgetg(3, t_VEC);
2556:
2557: /* allocate memory for veclprime1 */
2558: veclprime1 = cgetg(cl + 1, t_VEC);
2559: for (j = 1; j <= cl; j++)
2560: {
2561: v = cgetg(3, t_COMPLEX);
2562: v[1] = lgetr(prec);
2563: v[2] = lgetr(prec); gaffect(gzero, v);
2564: veclprime1[j] = (long)v;
2565: }
2566:
2567: av1 = avma;
2568: cn = cgetr(prec);
2569: p1 = gmul2n(cf, -1);
2570:
2571: /* compute veclprime1 */
2572: for (j = 1; j <= cl; j++)
2573: {
2574: long n0 = 0;
2575: p2 = gmael3(dtcr, j, 5, 2);
2576: cexp = gexp(gneg_i((GEN)c2[j]), prec);
2577: av2 = avma; affsr(1, cn); v = (GEN)veclprime1[j];
2578: for (n = 1; n <= nn[j]; n++)
2579: if ( (an = EvalCoeff(p2, matan[j][n], degs[j])) )
2580: {
2581: affrr(gmul(cn, gpowgs(cexp, n - n0)), cn);
2582: n0 = n;
2583: gaffect(gadd(v, gmul(divrs(cn,n), an)), v);
2584: avma = av2;
2585: }
2586: gaffect(gmul(p1, gmul(v, (GEN)C[j])), v);
2587: avma = av2;
2588: }
2589: avma = av1;
2590: rep[1] = (long)veclprime1;
2591: if (DEBUGLEVEL) msgtimer("Compute V1");
2592:
2593: /* allocate memory for veclprime2 */
2594: veclprime2 = cgetg(cl + 1, t_VEC);
2595: for (j = 1; j <= cl; j++)
2596: {
2597: v = cgetg(3, t_COMPLEX);
2598: v[1] = lgetr(prec);
2599: v[2] = lgetr(prec); gaffect(gzero, v);
2600: veclprime2[j] = (long)v;
2601: }
2602:
2603: /* compute f1(C/n) */
2604: av1 = avma;
2605:
2606: veint1 = cgetg(cl + 1, t_VEC);
2607: for (j = 1; j <= cl; j++)
2608: {
2609: p1 = NULL;
2610: for (k = 1; k < j; k++)
2611: if (gegal((GEN)cond[j], (GEN)cond[k])) { p1 = (GEN)veint1[k]; break; }
2612: if (p1 == NULL)
2613: {
2614: p1 = veceint1((GEN)c2[j], stoi(nn[j]), prec);
2615: veint1[j] = (long)p1;
2616: }
2617: av2 = avma; p2 = gmael3(dtcr, j, 5, 2);
2618: v = (GEN)veclprime2[j];
2619: for (n = 1; n <= nn[j]; n++)
2620: if ( (an = EvalCoeff(p2, matan[j][n], degs[j])) )
2621: {
2622: gaffect(gadd(v, gmul((GEN)p1[n], an)), v);
2623: avma = av2;
2624: }
2625: gaffect(gmul(cf, gconj(v)), v);
2626: avma = av2;
2627: }
2628: avma = av1;
2629: rep[2] = (long)veclprime2;
2630: if (DEBUGLEVEL) msgtimer("Compute V2");
2631: FreeMat(matan); return gerepileupto(av, rep);
2632: }
2633:
2634: #if 0
2635: /* recover a quadratic integer by an exhaustive search */
2636: static GEN
2637: recbeta2(GEN nf, GEN beta, GEN bound, long prec)
2638: {
2639: long av = avma, av2, tetpil, i, range, G, e, m;
2640: GEN om, om1, om2, dom, p1, a, b, rom, bom2, *gptr[2];
2641:
2642: G = min( - 20, - bit_accuracy(prec) >> 4);
2643:
2644: if (DEBUGLEVEL > 3)
2645: fprintferr("\n Precision needed: %ld", G);
2646:
2647: om = gmael(nf, 7, 2);
2648: rom = (GEN)nf[6];
2649: om1 = poleval(om, (GEN)rom[2]);
2650: om2 = poleval(om, (GEN)rom[1]);
2651: dom = subrr(om1, om2);
2652:
2653: /* b will run from b to b + range */
2654: p1 = gaddgs(gmul2n(gceil(absr(divir(bound, dom))), 1), 2);
2655: range = VERYBIGINT;
2656: if (cmpis(p1, VERYBIGINT) < 0)
2657: range = itos(p1);
2658:
2659: av2 = avma;
2660:
2661: b = gdiv(gsub(bound, beta), dom);
2662: if (gsigne(b) < 0)
2663: b = subis(negi(gcvtoi(gneg_i(b), &e)), 1);
2664: else
2665: b=gcvtoi(b, &e);
2666:
2667: if (e > 0) /* precision is lost in truncation */
2668: {
2669: avma = av;
2670: return NULL;
2671: }
2672:
2673: bom2 = mulir(b, om2);
2674: m = 0;
2675:
2676: for (i = 0; i <= range; i++)
2677: {
2678: /* for every b, we construct a and test it */
2679: a = grndtoi(gsub(beta, bom2), &e);
2680:
2681: if (e > 0) /* precision is lost in truncation */
2682: {
2683: avma = av;
2684: return NULL;
2685: }
2686:
2687: p1 = gsub(mpadd(a, bom2), beta);
2688:
2689: if ((DEBUGLEVEL > 3) && (expo(p1)<m))
2690: {
2691: m = expo(p1);
2692: fprintferr("\n Precision found: %ld", expo(p1));
2693: }
2694:
2695: if (gcmp0(p1) || (expo(p1) < G)) /* result found */
2696: {
2697: p1 = gadd(a, gmul(b, om));
2698: return gerepileupto(av, gmodulcp(p1, (GEN)nf[1]));
2699: }
2700:
2701: tetpil = avma;
2702:
2703: b = gaddgs(b, 1);
2704: bom2 = gadd(bom2, om2);
2705:
2706: gptr[0] = &b;
2707: gptr[1] = &bom2;
2708: gerepilemanysp(av2, tetpil, gptr, 2);
2709: }
2710:
2711: /* if it fails... */
2712: return NULL;
2713: }
2714: #endif
2715:
2716: /* let polrel define Hk/k, find L/Q such that Hk=Lk and L and k are
2717: disjoint */
2718: static GEN
2719: makescind(GEN nf, GEN polabs, long cl, long prec)
2720: {
2721: long av = avma, i, l;
2722: GEN pol, p1, nf2, dabs, dk, bas;
2723:
2724: /* check the result (a little): signature and discriminant */
2725: bas = allbase4(polabs,0,&dabs,NULL);
2726: dk = (GEN)nf[3];
2727: if (!egalii(dabs, gpowgs(dk,cl)) || sturm(polabs) != 2*cl)
2728: err(bugparier, "quadhilbert");
2729:
2730: /* attempt to find the subfields using polred */
2731: p1 = cgetg(3,t_VEC); p1[1]=(long)polabs; p1[2]=(long)bas;
2732: p1 = polred(p1, (prec<<1) - 2);
2733: l = lg(p1);
2734:
2735: for (i = 1; i < l; i++)
2736: {
2737: pol = (GEN)p1[i];
2738: if (degree(pol) == cl)
2739: if (cl % 2 || !gegal(sqri(discf(pol)), dabs)) break;
2740: }
2741: if (DEBUGLEVEL) msgtimer("polred");
2742:
2743: /* ... if it fails, then use nfsubfields */
2744: if (i == l)
2745: {
2746: nf2 = nfinit0(polabs, 1, prec);
2747: p1 = subfields(nf2, stoi(cl));
2748: l = lg(p1);
2749: if (DEBUGLEVEL) msgtimer("subfields");
2750:
2751: for (i = 1; i < l; i++)
2752: {
2753: pol = gmael(p1, i, 1);
2754: if (cl % 2 || !gegal(sqri(discf(pol)), (GEN)nf2[3])) break;
2755: }
2756: if (i == l)
2757: for (i = 1; i < l; i++)
2758: {
2759: pol = gmael(p1, i, 1);
2760: if (degree(gcoeff(nffactor(nf, pol), 1, 1)) == cl) break;
2761: }
2762: if (i == l)
2763: err(bugparier, "makescind (no polynomial found)");
2764: }
2765: pol = polredabs(pol, prec);
2766: return gerepileupto(av, pol);
2767: }
2768:
2769: /* compute the Hilbert class field using genus class field theory when
2770: the exponent of the class group is 2 */
2771: static GEN
2772: GenusField(GEN bnf, long prec)
2773: {
2774: long hk, c, l, av = avma;
2775: GEN disc, quat, x2, pol, div, d;
2776:
2777: hk = itos(gmael3(bnf, 8, 1, 1));
2778: disc = gmael(bnf, 7, 3);
2779: quat = stoi(4);
2780: x2 = gsqr(polx[0]);
2781:
2782: if (gcmp0(modii(disc, quat))) disc = divii(disc, quat);
2783:
2784: div = divisors(disc);
2785: c = 1;
2786: l = 0;
2787:
2788: while(l < hk)
2789: {
2790: c++;
2791: d = (GEN)div[c];
2792:
2793: if (gcmp1(modii(d, quat)))
2794: {
2795: if (!l)
2796: pol = gsub(x2, d);
2797: else
2798: pol=(GEN)compositum(pol, gsub(x2, d))[1];
2799:
2800: l = degree(pol);
2801: }
2802: }
2803:
2804: return gerepileupto(av, polredabs(pol, prec));
2805: }
2806:
2807: /* if flag = 0 returns the reduced polynomial, flag = 1 returns the
2808: non-reduced polynomial, flag = 2 returns an absolute reduced
2809: polynomial, flag = 3 returns the polynomial of the Stark's unit,
2810: flag = -1 computes a fast and crude approximation of the result */
2811: static GEN
2812: AllStark(GEN data, GEN nf, long flag, long newprec)
2813: {
2814: long cl, i, j, cpt = 0, av, av2, N, h, v, n, bnd = 300;
2815: int ***matan;
2816: GEN p0, p1, p2, S, T, polrelnum, polrel, Lp, W, A, veczeta, sig, valchi;
2817: GEN degs, ro, C, Cmax, dataCR, cond1, L1, *gptr[2], an, Pi;
2818:
2819: N = degree((GEN)nf[1]);
2820: cond1 = gmael4(data, 1, 2, 1, 2);
2821: Pi = mppi(newprec);
2822:
2823: v = 1;
2824: while(gcmp1((GEN)cond1[v])) v++;
2825:
2826: LABDOUB:
2827:
2828: av = avma;
2829:
2830: dataCR = (GEN)data[5];
2831: cl = lg(dataCR)-1;
2832: degs = GetDeg(dataCR);
2833: h = itos(gmul2n(det((GEN)data[2]), -1));
2834:
2835: if (flag >= 0)
2836: {
2837: /* compute S,T differently if nf is quadratic */
2838: if (N == 2)
2839: p1 = QuadGetST(data, newprec);
2840: else
2841: p1 = GetST(dataCR, newprec);
2842:
2843: S = (GEN)p1[1];
2844: T = (GEN)p1[2];
2845:
2846: Lp = cgetg(cl + 1, t_VEC);
2847: for (i = 1; i <= cl; i++)
2848: Lp[i] = GetValue((GEN)dataCR[i], (GEN)S[i], (GEN)T[i], 0, 1, newprec)[2];
2849:
2850: if (DEBUGLEVEL) msgtimer("Compute W");
2851: }
2852: else
2853: {
2854: /* compute a crude approximation of the result */
2855: C = cgetg(cl + 1, t_VEC);
2856: for (i = 1; i <= cl; i++) C[i] = mael(dataCR, i, 2);
2857: Cmax = vecmax(C);
2858:
2859: n = GetBoundN0(Cmax, N, newprec, 0);
2860: if (n > bnd) n = bnd;
2861: if (DEBUGLEVEL) fprintferr("nmax in QuickPol: %ld \n", n);
2862:
2863: matan = ComputeCoeff(dataCR, n, newprec);
2864:
2865: p0 = cgetg(3, t_COMPLEX);
2866: p0[1] = lgetr(newprec); affsr(0, (GEN)p0[1]);
2867: p0[2] = lgetr(newprec); affsr(0, (GEN)p0[2]);
2868:
2869: L1 = cgetg(cl+1, t_VEC);
2870: /* we use the formulae L(1) = sum (an / n) */
2871: for (i = 1; i <= cl; i++)
2872: {
2873: av2 = avma;
2874: p1 = p0; p2 = gmael3(dataCR, i, 5, 2);
2875: for (j = 1; j <= n; j++)
2876: if ( (an = EvalCoeff(p2, matan[i][j], degs[i])) )
2877: p1 = gadd(p1, gdivgs(an, j));
2878: L1[i] = lpileupto(av2, p1);
2879: }
2880: FreeMat(matan);
2881:
2882: p1 = gmul2n(gpowgs(mpsqrt(Pi), N - 2), 1);
2883:
2884: Lp = cgetg(cl+1, t_VEC);
2885: for (i = 1; i <= cl; i++)
2886: {
2887: W = ComputeArtinNumber((GEN)dataCR[i], 1, newprec);
2888: A = (GEN)ComputeAChi((GEN)dataCR[i], 0, newprec)[2];
2889: W = gmul((GEN)C[i], gmul(A, W));
2890:
2891: Lp[i] = ldiv(gmul(W, gconj((GEN)L1[i])), p1);
2892: }
2893: }
2894:
2895: p1 = ComputeLift(gmael(data, 4, 2));
2896:
2897: veczeta = cgetg(h + 1, t_VEC);
2898: for (i = 1; i <= h; i++)
2899: {
2900: GEN z = gzero;
2901:
2902: sig = (GEN)p1[i];
2903: valchi = chiideal(dataCR, sig, 0);
2904:
2905: for (j = 1; j <= cl; j++)
2906: {
2907: GEN p2 = greal(gmul((GEN)Lp[j], (GEN)valchi[j]));
2908: if (!gegal(gdeux, gmael3(dataCR, j, 5, 3)))
2909: p2 = gmul2n(p2, 1); /* character not real */
2910: z = gadd(z,p2);
2911: }
2912: veczeta[i] = ldivgs(z, 2 * h);
2913: }
2914: if (DEBUGLEVEL >= 2) fprintferr("zetavalues = %Z\n", veczeta);
2915:
2916: ro = cgetg(h+1, t_VEC); /* roots */
2917: for (j = 1; j <= h; j++)
2918: {
2919: p1 = gexp(gmul2n((GEN)veczeta[j], 1), newprec);
2920: ro[j] = ladd(p1, ginv(p1));
2921: }
2922: polrelnum = roots_to_pol_intern(realun(newprec),ro, 0,0);
2923: if (DEBUGLEVEL)
2924: {
2925: if (DEBUGLEVEL >= 2) fprintferr("polrelnum = %Z\n", polrelnum);
2926: msgtimer("Compute %s", (flag < 0)? "quickpol": "polrelnum");
2927: }
2928:
2929: if (flag < 0)
2930: return gerepileupto(av, gcopy(polrelnum));
2931:
2932: /* we try to recognize this polynomial */
2933: polrel = RecCoeff(nf, polrelnum, v, newprec);
2934:
2935: if (!polrel) /* if it fails... */
2936: {
2937: long pr;
2938: if (++cpt >= 3) err(talker,
2939: "insufficient precision: computation impossible");
2940:
2941: /* we compute the precision that we need */
2942: pr = 1 + (gexpo(polrelnum)>>TWOPOTBITS_IN_LONG);
2943: if (pr < 0) pr = 0;
2944: newprec = DEFAULTPREC + max(newprec,pr);
2945:
2946: if (DEBUGLEVEL) err(warnprec, "AllStark", newprec);
2947:
2948: nf = nfnewprec(nf, newprec);
2949: data[5] = (long)CharNewPrec((GEN)data[5], nf, newprec);
2950:
2951: gptr[0] = &data;
2952: gptr[1] = &nf;
2953: gerepilemany(av, gptr, 2);
2954:
2955: goto LABDOUB;
2956: }
2957:
2958: /* and we compute the polynomial of eps if flag = 3 */
2959: if (flag == 3)
2960: {
2961: n = fetch_var();
2962: p1 = gsub(polx[0], gadd(polx[n], ginv(polx[n])));
2963: polrel = polresultant0(polrel, p1, 0, 0);
2964: polrel = gmul(polrel, gpowgs(polx[n], h));
2965: polrel = gsubst(polrel, n, polx[0]);
2966: polrel = gmul(polrel, leading_term(polrel));
2967: delete_var();
2968: }
2969:
2970: if (DEBUGLEVEL >= 2) fprintferr("polrel = %Z\n", polrel);
2971: if (DEBUGLEVEL) msgtimer("Recpolnum");
2972:
2973: /* we want a reduced relative polynomial */
2974: if (!flag) return gerepileupto(av, rnfpolredabs(nf, polrel, 0, newprec));
2975:
2976: /* we just want the polynomial computed */
2977: if (flag!=2) return gerepileupto(av, gcopy(polrel));
2978:
2979: /* we want a reduced absolute polynomial */
2980: return gerepileupto(av, rnfpolredabs(nf, polrel, 2, newprec));
2981: }
2982:
2983: /********************************************************************/
2984: /* Main functions */
2985: /********************************************************************/
2986:
2987: /* compute the polynomial over Q of the Hilbert class field of
2988: Q(sqrt(D)) where D is a positive fundamental discriminant */
2989: GEN
2990: quadhilbertreal(GEN D, long prec)
2991: {
2992: long av = avma, cl, newprec;
2993: GEN pol, bnf, bnr, dataC, bnrh, nf, exp;
2994:
2995: if (DEBUGLEVEL) timer2();
2996:
2997: disable_dbg(0);
2998: /* quick computation of the class number */
2999:
3000: cl = itos((GEN)quadclassunit0(D, 0, NULL, prec)[1]);
3001: if (cl == 1)
3002: {
3003: disable_dbg(-1);
3004: avma = av; return polx[0];
3005: }
3006:
3007: /* initialize the polynomial defining Q(sqrt{D}) as a polynomial in y */
3008: pol = quadpoly(D);
3009: setvarn(pol, fetch_var());
3010:
3011: /* compute the class group */
3012: bnf = bnfinit0(pol, 1, NULL, prec);
3013: nf = (GEN)bnf[7];
3014: disable_dbg(-1);
3015:
3016: if (DEBUGLEVEL) msgtimer("Compute Cl(k)");
3017:
3018: /* if the exponent of the class group is 2, use rather Genus Field Theory */
3019: exp = gmael4(bnf, 8, 1, 2, 1);
3020: if (gegal(exp, gdeux)) { delete_var(); return GenusField(bnf, prec); }
3021:
3022: /* find the modulus defining N */
3023:
3024: bnr = buchrayinitgen(bnf, gun, prec);
3025: dataC = InitQuotient(bnr, gzero);
3026: bnrh = FindModulus(dataC, 1, &newprec, prec);
3027:
3028: if (DEBUGLEVEL) msgtimer("FindModulus");
3029:
3030: if (newprec > prec)
3031: {
3032: if (DEBUGLEVEL >= 2) fprintferr("new precision: %ld\n", newprec);
3033: nf = nfnewprec(nf, newprec);
3034: }
3035:
3036: /* use the generic function AllStark */
3037: pol = AllStark(bnrh, nf, 2, newprec);
3038: delete_var();
3039: return gerepileupto(av, makescind(nf, pol, cl, prec));
3040: }
3041:
3042: GEN
3043: bnrstark(GEN bnr, GEN subgroup, long flag, long prec)
3044: {
3045: long cl, N, newprec, av = avma;
3046: GEN bnf, dataS, p1, Mcyc, nf, data;
3047:
3048: if (flag < 0 || flag > 3) err(flagerr,"bnrstark");
3049:
3050: /* check the bnr */
3051: checkbnrgen(bnr);
3052:
3053: bnf = (GEN)bnr[1];
3054: nf = (GEN)bnf[7];
3055: Mcyc = diagonal(gmael(bnr, 5, 2));
3056: N = degree((GEN)nf[1]);
3057: if (N == 1)
3058: err(talker, "the ground field must be distinct from Q");
3059:
3060: /* check the bnf */
3061: if (!varn(gmael(bnf, 7, 1)))
3062: err(talker, "main variable in bnrstark must not be x");
3063:
3064: if (cmpis(gmael3(bnf, 7, 2, 1), N))
3065: err(talker, "not a totally real ground base field in bnrstark");
3066:
3067: /* check the subgroup */
3068: if (gcmp0(subgroup))
3069: subgroup = Mcyc;
3070: else
3071: {
3072: p1 = gauss(subgroup, Mcyc);
3073: if (!gcmp1(denom(p1)))
3074: err(talker, "incorrect subgroup in bnrstark");
3075: }
3076:
3077: /* compute bnr(conductor) */
3078: p1 = conductor(bnr, subgroup, 2, prec);
3079: bnr = (GEN)p1[2];
3080: subgroup = (GEN)p1[3];
3081:
3082: /* check the class field */
3083: if (!gcmp0(gmael3(bnr, 2, 1, 2)))
3084: err(talker, "not a totally real class field in bnrstark");
3085:
3086: cl = itos(det(subgroup));
3087: if (cl == 1) return polx[0];
3088:
3089: timer2();
3090:
3091: /* find a suitable extension N */
3092: dataS = InitQuotient(bnr, subgroup);
3093: data = FindModulus(dataS, 1, &newprec, prec);
3094:
3095: if (newprec > prec)
3096: {
3097: if (DEBUGLEVEL >= 2) fprintferr("new precision: %ld\n", newprec);
3098: nf = nfnewprec(nf, newprec);
3099: }
3100:
3101: return gerepileupto(av, AllStark(data, nf, flag, newprec));
3102: }
3103:
3104: /* For each character of bnr, compute L(1, chi) (or equivalently the
3105: first non-zero term c(chi) of the expansion at s = 0). The binary
3106: digits of flag mean 1: if 0 then compute the term c(chi) and return
3107: [r(chi), c(chi)] where r(chi) is the order of L(s, chi) at s = 0,
3108: or if 1 then compute the value at s = 1 (and in this case, only for
3109: non-trivial characters), 2: if 0 then compute the value of the
3110: primitive L-function associated to chi, if 1 then compute the value
3111: of the L-function L_S(s, chi) where S is the set of places dividing
3112: the modulus of bnr (and the infinite places), 3: return also the
3113: character */
3114: GEN
3115: bnrL1(GEN bnr, long flag, long prec)
3116: {
3117: GEN bnf, nf, cyc, Mcyc, p1, L1, chi, cchi, allCR, listCR, dataCR;
3118: GEN S, T, rep, indCR, invCR;
3119: long N, cl, i, j, nc, a, av = avma;
3120:
3121: bnf = (GEN)bnr[1];
3122: nf = (GEN)bnf[7];
3123: cyc = gmael(bnr, 5, 2);
3124: Mcyc = diagonal(cyc);
3125: N = degree((GEN)nf[1]);
3126:
3127: if (N == 1)
3128: err(talker, "the ground field must distinct from Q");
3129:
3130: if ((flag < 0) || (flag > 8))
3131: err(flagerr,"bnrL1");
3132:
3133: /* check the bnr */
3134: checkbnrgen(bnr);
3135:
3136: /* compute bnr(conductor) */
3137: if (!(flag & 2))
3138: {
3139: p1 = conductor(bnr, gzero, 2, prec);
3140: bnr = (GEN)p1[2];
3141: cyc = gmael(bnr, 5, 2);
3142: Mcyc = diagonal(cyc);
3143: }
3144:
3145: cl = itos(det(Mcyc));
3146:
3147: /* compute all the characters */
3148: allCR = FindEltofGroup(cl, cyc);
3149:
3150: /* make a list of all non-trivial characters modulo conjugation */
3151: listCR = cgetg(cl, t_VEC);
3152: indCR = new_chunk(cl);
3153: invCR = new_chunk(cl);
3154:
3155: nc = 0;
3156:
3157: for (i = 1; i < cl; i++)
3158: {
3159: chi = (GEN)allCR[i];
3160: cchi = ConjChar(chi, cyc);
3161:
3162: a = i;
3163: for (j = 1; j <= nc; j++)
3164: if (gegal(gmael(listCR, j, 1), cchi)) a = -j;
3165:
3166: if (a > 0)
3167: {
3168: nc++;
3169: listCR[nc] = lgetg(3, t_VEC);
3170: mael(listCR, nc, 1) = (long)chi;
3171: mael(listCR, nc, 2) = (long)bnrconductorofchar(bnr, chi, prec);
3172:
3173: indCR[i] = nc;
3174: invCR[nc] = i;
3175: }
3176: else
3177: indCR[i] = -invCR[-a];
3178: }
3179:
3180: setlg(listCR, nc + 1);
3181: if (nc == 0) err(talker, "no non-trivial character in bnrL1");
3182:
3183: /* compute the data for these characters */
3184: dataCR = InitChar(bnr, listCR, prec);
3185:
3186: p1 = GetST(dataCR, prec);
3187:
3188: S = (GEN)p1[1];
3189: T = (GEN)p1[2];
3190:
3191: if (flag & 1)
3192: L1 = cgetg(cl, t_VEC);
3193: else
3194: L1 = cgetg(cl + 1, t_VEC);
3195:
3196: for (i = 1; i < cl; i++)
3197: {
3198: a = indCR[i];
3199: if (a > 0)
3200: L1[i] = (long)GetValue((GEN)dataCR[a], (GEN)S[a], (GEN)T[a], flag & 1,
3201: flag & 2, prec);
3202: }
3203:
3204: for (i = 1; i < cl; i++)
3205: {
3206: a = indCR[i];
3207: if (a < 0)
3208: L1[i] = lconj((GEN)L1[-a]);
3209: }
3210:
3211: if (!(flag & 1))
3212: L1[cl] = (long)GetValue1(bnr, flag & 2, prec);
3213: else
3214: cl--;
3215:
3216: if (flag & 4)
3217: {
3218: rep = cgetg(cl + 1, t_VEC);
3219: for (i = 1; i <= cl; i++)
3220: {
3221: p1 = cgetg(3, t_VEC);
3222: p1[1] = allCR[i];
3223: p1[2] = L1[i];
3224:
3225: rep[i] = (long)p1;
3226: }
3227: }
3228: else
3229: rep = L1;
3230:
3231: return gerepileupto(av, gcopy(rep));
3232: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>