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

Annotation of OpenXM_contrib/pari-2.2/src/basemath/buch1.c, Revision 1.1

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

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