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