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