[BACK]Return to stark.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / src / modules

Annotation of OpenXM_contrib/pari-2.2/src/modules/stark.c, Revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>