[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

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>