Annotation of OpenXM_contrib/pari/src/basemath/buch1.c, Revision 1.1
1.1 ! maekawa 1: /*******************************************************************/
! 2: /* */
! 3: /* CLASS GROUP AND REGULATOR (McCURLEY, BUCHMANN) */
! 4: /* QUADRATIC FIELDS */
! 5: /* */
! 6: /*******************************************************************/
! 7: /* $Id: buch1.c,v 1.2 1999/09/23 17:50:56 karim Exp $ */
! 8: #include "pari.h"
! 9:
! 10: /* See buch2.c:
! 11: * precision en digits decimaux=2*(#digits decimaux de Disc)+50
! 12: * on prendra les p decomposes tels que prod(p)>lim dans la subbase
! 13: * LIMC=Max(c.(log(Disc))^2,exp((1/8).sqrt(log(Disc).loglog(Disc))))
! 14: * LIMC2=Max(6.(log(Disc))^2,exp((1/8).sqrt(log(Disc).loglog(Disc))))
! 15: * subbase contient les p decomposes tels que prod(p)>sqrt(Disc)
! 16: * lgsub=subbase[0]=#subbase;
! 17: * subfactorbase est la table des form[p] pour p dans subbase
! 18: * nbram est le nombre de p divisant Disc elimines dans subbase
! 19: * powsubfactorbase est la table des puissances des formes dans subfactorbase
! 20: */
! 21: #define HASHT 1024
! 22: static const long CBUCH = 15; /* of the form 2^k-1 */
! 23: static const long randshift=BITS_IN_RANDOM-1 - 4; /* BITS_IN_RANDOM-1-k */
! 24:
! 25: static long sens,KC,KC2,lgsub,limhash,RELSUP,PRECREG;
! 26: static long *primfact,*primfact1, *exprimfact,*exprimfact1, *badprim;
! 27: static long *factorbase,*numfactorbase, *subbase, *vectbase, **hashtab;
! 28: static GEN **powsubfactorbase,vperm,subfactorbase,Disc,sqrtD,isqrtD;
! 29:
! 30: GEN buchquad(GEN D, double c, double c2, long RELSUP0, long flag, long prec);
! 31: GEN roots_to_pol_intern(GEN L, GEN a, long v, int plus);
! 32:
! 33: GEN
! 34: quadclassunit0(GEN x, long flag, GEN data, long prec)
! 35: {
! 36: long lx,RELSUP0;
! 37: double cbach, cbach2;
! 38:
! 39: if (!data) lx=1;
! 40: else
! 41: {
! 42: lx = lg(data);
! 43: if (typ(data)!=t_VEC || lx > 7)
! 44: err(talker,"incorrect parameters in quadclassunit");
! 45: if (lx > 4) lx = 4;
! 46: }
! 47: cbach = cbach2 = 0.1; RELSUP0 = 5;
! 48: switch(lx)
! 49: {
! 50: case 4: RELSUP0 = itos((GEN)data[3]);
! 51: case 3: cbach2 = gtodouble((GEN)data[2]);
! 52: case 2: cbach = gtodouble((GEN)data[1]);
! 53: }
! 54: return buchquad(x,cbach,cbach2,RELSUP0,flag,prec);
! 55: }
! 56:
! 57: /*******************************************************************/
! 58: /*******************************************************************/
! 59: /* */
! 60: /* Corps de classe de Hilbert et de rayon avec CM (Schertz) */
! 61: /* */
! 62: /*******************************************************************/
! 63: /*******************************************************************/
! 64:
! 65: int
! 66: isoforder2(GEN form)
! 67: {
! 68: GEN a=(GEN)form[1],b=(GEN)form[2],c=(GEN)form[3];
! 69: return !signe(b) || absi_equal(a,b) || egalii(a,c);
! 70: }
! 71:
! 72: /* returns an equation for the Hilbert class field of the imaginary
! 73: * quadratic field of discriminant D if flag=0, a vector of
! 74: * two-component vectors [form,g(form)] where g() is the root of the equation
! 75: * if flag is non-zero.
! 76: */
! 77: static GEN
! 78: quadhilbertimag(GEN D, GEN flag)
! 79: {
! 80: long av=avma,a,b,c,d,dover3,b2,t,h,h2,ell,l,i,i1,i2,ex,prec;
! 81: GEN z,form,L,LG,y,res,ga1,ga2,ga3,ga4,wp,court,p1,p2,qf1,qf2;
! 82: GEN u1,u2,u,w,ag,bg,al,ag2,wlf;
! 83: byteptr p = diffptr;
! 84: int raw = ((typ(flag)==t_INT && signe(flag)));
! 85:
! 86: if (DEBUGLEVEL>=2) timer2();
! 87: if (gcmpgs(D,-11)>=0) return polx[0];
! 88: d=itos(D); L=cgetg(1,t_VEC);
! 89: b2 = b = (d&1)?1:0; h=h2=0; z=gun; dover3=labs(d)/3;
! 90: while (b2 <= dover3)
! 91: {
! 92: t=(b2-d)/4;
! 93: for (a=b?b:1; a*a<=t; a++)
! 94: if (t%a==0)
! 95: {
! 96: h++; c = t/a; z = mulsi(a,z);
! 97: L = concatsp(L, qfi(stoi(a),stoi(b),stoi(c)));
! 98: if (b && a != b && a*a != t)
! 99: {
! 100: h++;
! 101: L = concatsp(L, qfi(stoi(a),stoi(-b),stoi(c)));
! 102: }
! 103: else h2++;
! 104: }
! 105: b+=2; b2=b*b;
! 106: }
! 107: if (h==1) {avma=av; return polx[0];}
! 108: if (DEBUGLEVEL>=2) msgtimer("class number = %ld",h);
! 109: wp=cgetg(1,t_VEC); wlf=cgetg(1,t_VEC); court=stoi(5);
! 110: if (typ(flag)==t_VEC)
! 111: {
! 112: for (i=1; i<lg(flag); i++)
! 113: {
! 114: ell=itos((GEN)flag[i]);
! 115: if (smodis(z,ell) && kross(d,ell) > 0)
! 116: {
! 117: court[2]=ell; form=redimag(primeform(D,court,0));
! 118: if (!gcmp1((GEN)form[1]))
! 119: {
! 120: wp = concat(wp,court); wlf = concat(wlf,form);
! 121: }
! 122: }
! 123: }
! 124: }
! 125: else
! 126: {
! 127: ell=0; ell += *p++; ell+= *p++;
! 128: while (lg(wp)<=2 || ell<=300)
! 129: {
! 130: ell += *p++; if (!*p) err(primer1);
! 131: if (smodis(z,ell) && kross(d,ell) > 0)
! 132: {
! 133: court[2]=ell; form=redimag(primeform(D,court,0));
! 134: if (!gcmp1((GEN)form[1]))
! 135: {
! 136: wp = concat(wp,court); wlf = concat(wlf,form);
! 137: }
! 138: }
! 139: }
! 140: }
! 141: l = lg(wp)-1;
! 142: if (l<2) { avma=av; return gzero; }
! 143: if (typ(flag)==t_VEC) { i1=1; i2=2; p1=(GEN)wp[1]; }
! 144: else
! 145: {
! 146: for(i=1; i<=l; i++)
! 147: if (smodis((GEN)wp[i],3) == 1) break;
! 148: i1=(i>l)?1:i; p1=(GEN)wp[i1]; form=(GEN)wlf[i1];
! 149: if (isoforder2(form))
! 150: {
! 151: if (smodis(p1,4)==3)
! 152: {
! 153: for (i=1; i<=l && (smodis((GEN)wp[i],4) == 3 ||
! 154: (isoforder2((GEN)wlf[i]) && !gegal((GEN)wlf[i],form))); i++);
! 155: if (i>l)
! 156: {
! 157: for (i=1; i<=l && isoforder2((GEN)wlf[i]) && !gegal((GEN)wlf[i],form) ;i++);
! 158: if (i>l) { avma=av; return gzero; }
! 159: }
! 160: }
! 161: else
! 162: {
! 163: for (i=1; i<=l && isoforder2((GEN)wlf[i]) && !gegal((GEN)wlf[i],form); i++);
! 164: if (i>l) { avma=av; return gzero; }
! 165: }
! 166: }
! 167: else
! 168: {
! 169: if (smodis(p1,4)==3)
! 170: {
! 171: for(i=1; i<=l; i++)
! 172: if (smodis((GEN)wp[i],4) == 1) break;
! 173: if (i>l) i=1;
! 174: }
! 175: else i=1;
! 176: }
! 177: i2=i;
! 178: }
! 179: qf1 = primeform(D,p1,0); u1 = gmodulcp((GEN)qf1[2],shifti(p1,1));
! 180: p2 = (GEN)wp[i2];
! 181: qf2 = primeform(D,p2,0); u2 = gmodulcp((GEN)qf2[2],shifti(p2,1));
! 182: ex=24/itos(ggcd(mulii(subis(p1,1),subis(p2,1)),stoi(24)));
! 183: if(DEBUGLEVEL>=2)
! 184: fprintferr("p1 = %Z, p2 = %Z, ex = %ld\n",p1,p2,ex);
! 185: if (!egalii(p1,p2)) u=lift(chinois(u1,u2));
! 186: else
! 187: {
! 188: if (!gegal(qf1,qf2)) err(bugparier,"quadhilbertimag (p1=p1, qf1!=qf2)");
! 189: u=(GEN)compimagraw(qf1,qf2)[2];
! 190: }
! 191: u = gmodulcp(u, shifti(mulii(p1,p2),1));
! 192: LG = cgetg(h+1,t_VEC);
! 193: prec = raw? DEFAULTPREC: 3;
! 194: for(;;)
! 195: {
! 196: long av0 = avma, e, emax = 0;
! 197: GEN lead, sqd = gsqrt(negi(D),prec);
! 198: for (i=1; i<=h; i++)
! 199: {
! 200: form=(GEN)L[i];
! 201: ag=(GEN)form[1]; ag2=shifti(ag,1);
! 202: bg=(GEN)form[2];
! 203: w = lift(chinois(gmodulcp(negi(bg),ag2), u));
! 204: al=cgetg(3,t_COMPLEX);
! 205: al[1]=lneg(gdiv(w,ag2));
! 206: al[2]=ldiv(sqd,ag2);
! 207: ga1 = trueeta(gdiv(al,p1),prec);
! 208: ga2 = trueeta(gdiv(al,p2),prec);
! 209: ga3 = trueeta(gdiv(al,mulii(p1,p2)),prec);
! 210: ga4 = trueeta(al,prec);
! 211: LG[i] = lpowgs(gdiv(gmul(ga1,ga2),gmul(ga3,ga4)), ex);
! 212: e = gexpo((GEN)LG[i]); if (e > 0) emax += e;
! 213: if (DEBUGLEVEL > 2) fprintferr("%ld ",i);
! 214: }
! 215: if (DEBUGLEVEL > 2) fprintferr("\n");
! 216: if (raw)
! 217: {
! 218: y=cgetg(h+1,t_VEC);
! 219: for(i=1; i<=h; i++)
! 220: {
! 221: res=cgetg(3,t_VEC); y[i]=(long)res;
! 222: res[1]=lcopy((GEN)L[i]);
! 223: res[2]=lcopy((GEN)LG[i]);
! 224: }
! 225: break;
! 226: }
! 227: if (DEBUGLEVEL>=2) msgtimer("roots");
! 228: /* to avoid integer overflow (1 + 0.) */
! 229: lead = (emax < bit_accuracy(prec))? gun: realun(prec);
! 230:
! 231: y = greal(roots_to_pol_intern(lead,LG,0,0));
! 232: y = grndtoi(y,&emax);
! 233: if (DEBUGLEVEL>=2) msgtimer("product, error bits = %ld",emax);
! 234: if (emax <= -10)
! 235: {
! 236: if (typ(flag)==t_VEC)
! 237: {
! 238: long av1 = avma;
! 239: e = degree(modulargcd(y,derivpol(y)));
! 240: avma = av1; if (e > 0) { avma=av; return gzero; }
! 241: }
! 242: break;
! 243: }
! 244: avma = av0; prec += (DEFAULTPREC-2) + (1 + (emax >> TWOPOTBITS_IN_LONG));
! 245: if (DEBUGLEVEL) err(warnprec,"quadhilbertimag",prec);
! 246: }
! 247: return gerepileupto(av,y);
! 248: }
! 249:
! 250: GEN quadhilbertreal(GEN D, long prec);
! 251:
! 252: GEN
! 253: quadhilbert(GEN D, GEN flag, long prec)
! 254: {
! 255: if (typ(D)!=t_INT)
! 256: {
! 257: D = checkbnf(D);
! 258: if (degree(gmael(D,7,1))!=2)
! 259: err(talker,"not a polynomial of degree 2 in quadhilbert");
! 260: D=gmael(D,7,3);
! 261: }
! 262: else
! 263: {
! 264: if (!isfundamental(D))
! 265: err(talker,"quadhilbert needs a fundamental discriminant");
! 266: }
! 267: if (signe(D)>0) return quadhilbertreal(D,prec);
! 268: if (!flag) flag = gzero;
! 269: return quadhilbertimag(D,flag);
! 270: }
! 271:
! 272: /* AUXILLIARY ROUTINES FOR QUADRAYIMAGWEI */
! 273:
! 274: static GEN
! 275: getal(GEN nf, GEN b, GEN a, long prec)
! 276: {
! 277: GEN p1,D,os;
! 278:
! 279: p1=idealcoprime(nf,idealdiv(nf,b,a),b);
! 280: D=(GEN)nf[3];
! 281: os=mpodd(D) ? gun : gzero; os=gmul2n(gadd(os,gsqrt(D,prec)),-1);
! 282: return gadd((GEN)p1[1],gmul((GEN)p1[2],os));
! 283: }
! 284:
! 285: static GEN
! 286: epseta(GEN D, long p, long q, GEN tau, long prec)
! 287: {
! 288: GEN p1,p2;
! 289:
! 290: if (gcmpgs(D,-4)<0)
! 291: {
! 292: p1=trueeta(gdivgs(tau,p),prec);
! 293: p2=(p==q) ? p1 : trueeta(gdivgs(tau,q),prec);
! 294: p1=gdiv(gmul(p1,p2),trueeta(gdivgs(tau,p*q),prec));
! 295: return gmul(p1,gpuigs(trueeta(tau,prec),3));
! 296: }
! 297: else return gpuigs(trueeta(tau,prec),4);
! 298: }
! 299:
! 300: static GEN
! 301: pppfun(GEN D, GEN z, GEN a, GEN den, long prec)
! 302: {
! 303: GEN om, res, y, os;
! 304:
! 305: os=mpodd(D) ? gun : gzero; os=gmul2n(gadd(os,gsqrt(D,prec)),-1);
! 306: om=cgetg(3,t_VEC);
! 307: om[1]=ladd(gcoeff(a,1,2),gmul(gcoeff(a,2,2),os));
! 308: om[2]=coeff(a,1,1);
! 309: res=gdiv(ellwp0(om,z,0,prec,0),den); y=res;
! 310: if (gcmpgs(D,-4)>=0) y=gmul(y,res);
! 311: if (gcmpgs(D,-3)==0) y=gmul(y,res);
! 312: return y;
! 313: }
! 314:
! 315: static GEN
! 316: schertzc(GEN nf, GEN a, GEN den, long prec)
! 317: {
! 318: GEN D,al,id,p1;
! 319: long k2,k3,ell,j;
! 320: byteptr p = diffptr;
! 321:
! 322: D=(GEN)nf[3];
! 323:
! 324: if (gcmpgs(D,-3)==0)
! 325: {
! 326: id=idealmul(nf,gdeux,(GEN)(primedec(nf,stoi(3))[1]));
! 327: al=getal(nf,id,a,prec);
! 328: return pppfun(D,al,a,den,prec);
! 329: }
! 330: if (gcmpgs(D,-4)==0)
! 331: {
! 332: id=idealmul(nf,(GEN)(primedec(nf,gdeux)[1]),(GEN)(primedec(nf,stoi(5))[1]));
! 333: al=getal(nf,id,a,prec);
! 334: return pppfun(D,al,a,den,prec);
! 335: }
! 336: k2=krogs(D,2); k3=krogs(D,3);
! 337: if (k2==-1)
! 338: {
! 339: if (k3==-1) return gzero;
! 340: else
! 341: {
! 342: ell=0; ell += *p++; ell += *p++;
! 343: do
! 344: {
! 345: ell += *p++;
! 346: if (!*p) err(primer1);
! 347: }
! 348: while (ell%3!=2 || krogs(D,ell)==1);
! 349: al=getal(nf,idealhermite(nf,(GEN)(primedec(nf,stoi(ell))[1])),a,prec);
! 350: p1=gzero;
! 351: for (j=1; j<=((ell-1)>>1); j++)
! 352: p1=gadd(p1,pppfun(D,gmulsg(j,al),a,den,prec));
! 353: return gneg(p1);
! 354: }
! 355: }
! 356: else
! 357: {
! 358: if (k3!=-1)
! 359: {
! 360: id=idealmul(nf,(GEN)(primedec(nf,gdeux)[1]),(GEN)(primedec(nf,stoi(3))[1]));
! 361: al=getal(nf,id,a,prec);
! 362: return pppfun(D,al,a,den,prec);
! 363: }
! 364: else
! 365: {
! 366: if (k2==1)
! 367: {
! 368: al=getal(nf,idealhermite(nf,gdeux),a,prec);
! 369: return pppfun(D,al,a,den,prec);
! 370: }
! 371: else
! 372: {
! 373: ell=0; ell += *p++; ell += *p++;
! 374: do
! 375: {
! 376: ell += *p++;
! 377: if (!*p) err(primer1);
! 378: }
! 379: while (ell%4!=3 || krogs(D,ell)==1);
! 380: al=getal(nf,idealhermite(nf,(GEN)(primedec(nf,stoi(ell))[1])),a,prec);
! 381: p1=gzero;
! 382: for (j=1; j<=((ell-1)>>1); j++)
! 383: p1=gadd(p1,pppfun(D,gmulsg(j,al),a,den,prec));
! 384: return gmulsg(-krogs(gdeux,ell),p1);
! 385: }
! 386: }
! 387: }
! 388: }
! 389:
! 390: static GEN
! 391: getallelts(GEN nf, GEN clgp)
! 392: {
! 393: GEN cyc,gen,listl,res;
! 394: long lc,i,j,k,no,k1,pro;
! 395:
! 396: cyc=(GEN)clgp[2]; gen=(GEN)clgp[3]; lc=lg(cyc)-1;
! 397: no=itos((GEN)clgp[1]);
! 398: listl=cgetg(no+1,t_VEC);
! 399: listl[1] = (long)idealhermite(nf,gun);
! 400: for (j=1; j<no; j++)
! 401: {
! 402: k = j; res = gun;
! 403: for (i=lc; k; i--)
! 404: {
! 405: pro=((GEN)cyc[i])[2]; /* attention: 1er et seul mot no code de cyc[i] */
! 406: k1 = k%pro;
! 407: if (k1) res=idealmul(nf,res,idealpows(nf,(GEN)gen[i],k1));
! 408: k /= pro;
! 409: }
! 410: listl[j+1] = (long)res;
! 411: }
! 412: return listl;
! 413: }
! 414:
! 415: /* If error and flag = 0 return error message, otherwise return empty vector */
! 416: static GEN
! 417: findbezk(GEN nf, GEN be, long flag, long prec)
! 418: {
! 419: GEN a0,b0,a,b,D,pol,y;
! 420: GEN eps=gpuigs(stoi(10),-8);
! 421: long d0,ea,eb;
! 422:
! 423: D=(GEN)nf[3]; pol=(GEN)nf[1];
! 424: a0=gmul2n(greal(be),1); a=grndtoi(a0,&ea);
! 425: b0=gdiv(gmul2n(gimag(be),1),gsqrt(negi(D),prec)); b=grndtoi(b0,&eb);
! 426: if (ea>-10 || eb>-10)
! 427: {
! 428: if (flag) return cgetg(1,t_VEC);
! 429: else err(talker,"insufficient precision in findbezk");
! 430: }
! 431: if (gcmp(gadd(gabs(gsub(a,a0),prec),gabs(gsub(b,b0),prec)),eps)>0 || mpodd(addii(a,mulii(b,D))))
! 432: {
! 433: if (flag) return cgetg(1,t_VEC);
! 434: else {outerr(be); err(talker," is not in ZK");}
! 435: }
! 436: y=cgetg(3,t_POLMOD);
! 437: y[1]=(long)pol;
! 438: d0=mpodd(D) ? -1 : 0;
! 439: y[2]=ladd(gmul(b,polx[varn(pol)]),gmul2n(gadd(a,gmulgs(b,d0)),-1));
! 440: return y;
! 441: }
! 442:
! 443: /* returns an equation for the ray class field of modulus f of the imaginary
! 444: * quadratic field bnf if flag=0, a vector of
! 445: * two-component vectors [id,g(id)] where g() is the root of the equation
! 446: * if flag is non-zero.
! 447: */
! 448: static GEN
! 449: quadrayimagwei(GEN bnr, GEN flag, long prec)
! 450: {
! 451: long av=avma,tetpil,vpol,clno,clrayno,lc,i,j,res,ell,inda,fl;
! 452: byteptr p = diffptr;
! 453: GEN allf,f,clray,bnf,nf,D,pol,fa,P2,P2new,pp,pi,pial,os,clgp,cyc,gen,listl;
! 454: GEN listray,lista,listla,pp1,la,z,pr2,listden,listc,p1,pii2,ida,ap2;
! 455: GEN om1,om2,tau,d,al,s,vpro;
! 456:
! 457: allf=conductor(bnr,gzero,1,prec);
! 458: f=gmael(allf,1,1); clray=(GEN)allf[2];
! 459: bnf=(GEN)bnr[1]; nf=(GEN)bnf[7]; D=(GEN)nf[3];
! 460: pol=(GEN)nf[1]; vpol=varn(pol);
! 461: fa=(GEN)idealfactor(nf,f)[1];
! 462: fl=itos(flag);
! 463: if (lg(fa)==1)
! 464: {
! 465: P2=quadhilbertimag(D,flag);
! 466: if (fl)
! 467: {
! 468: /* convertir les formes en ideaux */
! 469: }
! 470: tetpil=avma; return gerepile(av,tetpil,gcopy(P2));
! 471: }
! 472: os=mpodd(D) ? gun : gzero; os=gmul2n(gadd(os,gsqrt(D,prec)),-1);
! 473: if (lg(fa)==2)
! 474: {
! 475: pp=(GEN)fa[1]; pi=(GEN)pp[1];
! 476: if (fl) pial=gadd(gmul(gmael(pp,2,2),os),gmael(pp,2,1));
! 477: else pial=basistoalg(nf,(GEN)pp[2]);
! 478: }
! 479: else { pi=gun; pial=gun; }
! 480: clgp=gmael(bnf,8,1);
! 481: clno=itos((GEN)clgp[1]); cyc=(GEN)clgp[2]; gen=(GEN)clgp[3];
! 482: lc=lg(gen);
! 483: listl = getallelts(nf,clgp);
! 484: listray = getallelts(nf,clray);
! 485: clrayno=itos((GEN)clray[1]);
! 486: lista = cgetg(clrayno+1,t_VECSMALL);
! 487: listla = cgetg(clrayno+1,t_VEC);
! 488: for (i=1; i<=clrayno; i++)
! 489: {
! 490: pp = isprincipalgenforce(bnf,idealinv(nf,(GEN)listray[i]));
! 491: pp1 = (GEN)pp[1];
! 492: for (res=0,j=1; j<lc; j++)
! 493: res = res*itos((GEN)cyc[j]) + itos((GEN)pp1[j]);
! 494: lista[i] = res+1;
! 495: la = gmul((GEN)nf[7],(GEN)pp[2]);
! 496: listla[i] = lsubst(la,vpol,os);
! 497: }
! 498: z = dethnf(gmael3(bnr,2,1,1));
! 499: for (i=1; i<=clno; i++) z=mulii(z,dethnf((GEN)listl[i]));
! 500: if (gcmpgs(D,-4)<0)
! 501: {
! 502: GEN court=cgeti(3);
! 503:
! 504: court[1]=evallgefint(3) | evalsigne(1);
! 505: ell=0;
! 506: do
! 507: {
! 508: ell += *p++; court[2]=ell;
! 509: if (!*p) err(primer1);
! 510: }
! 511: while (ell%12!=11 || !gcmp1(ggcd(court,z)) || krogs(D,ell)!=1);
! 512: pr2=idealpows(nf,(GEN)(primedec(nf,stoi(ell))[1]),2);
! 513: }
! 514: else { pr2=idmat(2); ell=1; }
! 515: listden=cgetg(clno+1,t_VEC); listc=cgetg(clno+1,t_VEC);
! 516: p1=mppi(prec); setexpo(p1,2);
! 517: pii2=cgetg(3,t_COMPLEX); pii2[1]=zero; pii2[2]=(long)p1;
! 518: for (i=1; i<=clno; i++)
! 519: {
! 520: ida=(GEN)listl[i]; ap2=idealmul(nf,ida,pr2);
! 521: om2=gcoeff(ida,1,1);
! 522: om1=gadd(gcoeff(ap2,1,2),gmul(gcoeff(ap2,2,2),os));
! 523: tau=gdiv(om1,om2);
! 524: d=gmul(gsqr(gdiv(pii2,om2)),epseta(D,ell,ell,tau,prec));
! 525: listden[i]=(long)d;
! 526: listc[i]=(long)schertzc(nf,(GEN)listl[i],d,prec);
! 527: }
! 528: al = gsubst(gmul((GEN)nf[7],idealcoprime(nf,f,f)),vpol,os);
! 529: P2 = fl? cgetg(clrayno+1,t_VEC): gun;
! 530: for (j=1; j<=clrayno; j++)
! 531: {
! 532: inda=lista[j];
! 533: s=pppfun(D,gdiv(al,(GEN)listla[j]),(GEN)listl[inda],(GEN)listden[inda],prec);
! 534: s=gsub(s,(GEN)listc[inda]);
! 535:
! 536: if (fl)
! 537: {
! 538: s=gmul(pial,s);
! 539: vpro=cgetg(3,t_VEC);
! 540: vpro[1]=(long)listray[j];
! 541: vpro[2]=(long)s;
! 542: P2[j]=(long)vpro;
! 543: }
! 544: else P2=gmul(P2,gsub(polx[0],gmul(pi,s)));
! 545: }
! 546: if (DEBUGLEVEL)
! 547: {
! 548: fprintferr("P2 = "); outerr(P2);
! 549: }
! 550: if (!fl)
! 551: {
! 552: P2new=gzero;
! 553: for (i=clrayno; i>=0; i--)
! 554: {
! 555: p1=findbezk(nf,truecoeff(P2,i),1,prec);
! 556: if (typ(p1)==t_VEC) {avma=av; return cgetg(1,t_VEC);}
! 557: else P2new=gadd(p1,gmul(polx[0],P2new));
! 558: }
! 559: P2=gsubst(P2new,0,gmul(gdiv(pi,pial),polx[0]));
! 560: P2=gmul(P2,gpuigs(gdiv(pial,pi),clrayno));
! 561: }
! 562: tetpil=avma;
! 563: return gerepile(av,tetpil,gcopy(P2));
! 564: }
! 565:
! 566: /* AUXILLIARY ROUTINES FOR QUADRAYSIGMA */
! 567:
! 568: /* Computes values 2*I*Pi, (om1_*om2-om1*om2_)/(2*I) and
! 569: om1_*eta2-om2_*eta1 necessary for ellphist */
! 570:
! 571: static GEN
! 572: ellphistinit(GEN om, long prec)
! 573: {
! 574: GEN p1,p2,et,om1,om2,ar,pii2,res;
! 575:
! 576: p1=mppi(prec); setexpo(p1,2);
! 577: pii2=cgetg(3,t_COMPLEX); pii2[1]=zero; pii2[2]=(long)p1;
! 578: om1=(GEN)om[1]; om2=(GEN)om[2];
! 579: if (gsigne(gimag(gdiv(om1,om2)))<0)
! 580: {
! 581: p1=om1; om1=om2; om2=p1;
! 582: p1=cgetg(3,t_VEC); p1[1]=(long)om1; p1[2]=(long)om2;
! 583: }
! 584: et=elleta(om,prec);
! 585: ar=gimag(gmul(p2=gconj(om1),om2));
! 586: p1=gsub(gmul(p2,(GEN)et[2]),gmul(gconj(om2),(GEN)et[1]));
! 587: res=cgetg(4,t_VEC);
! 588: res[1]=(long)pii2; res[2]=(long)ar; res[3]=(long)p1;
! 589: return res;
! 590: }
! 591:
! 592: /* Computes log(phi^*(z,om)), using res computed by ellphistinit */
! 593:
! 594: static GEN
! 595: ellphist(GEN om, GEN res, GEN z, long prec)
! 596: {
! 597: GEN zst;
! 598:
! 599: zst=gdiv(gsub(gmul(z,(GEN)res[3]),gmul(gconj(z),(GEN)res[1])),gmul2n(gmul(gi,(GEN)res[2]),1));
! 600: return gsub(ellsigma(om,z,1,prec),gmul2n(gmul(z,zst),-1));
! 601: }
! 602:
! 603: /* Computes phi^*(la,om)/phi^*(1,om) where om is an oriented basis of the
! 604: ideal gf*gc^{-1} */
! 605:
! 606: static GEN
! 607: computeth2(GEN nf, GEN gf, GEN gc, GEN la, long prec)
! 608: {
! 609: GEN D,os,p1,p2,fdiv,omdiv,lanum,res;
! 610:
! 611: D=(GEN)nf[3];
! 612: os=mpodd(D) ? gun : gzero; os=gmul2n(gadd(os,gsqrt(D,prec)),-1);
! 613: fdiv=idealdiv(nf,gf,gc);
! 614: omdiv=cgetg(3,t_VEC); omdiv[2]=coeff(fdiv,1,1);
! 615: omdiv[1]=ladd(gmul(gcoeff(fdiv,2,2),os),gcoeff(fdiv,1,2));
! 616: la=lift(la);
! 617: lanum=gadd(gmul(truecoeff(la,1),os),truecoeff(la,0));
! 618: res=ellphistinit(omdiv,prec);
! 619: p1=gsub(ellphist(omdiv,res,lanum,prec),ellphist(omdiv,res,gun,prec));
! 620: p2=gimag(p1);
! 621: if (gexpo(greal(p1))>20 || gexpo(p2)> bit_accuracy(min(prec,lg(p2)))-10)
! 622: return cgetg(1,t_VEC);
! 623: else return gexp(p1,prec);
! 624: }
! 625:
! 626: /* Computes P_2(X)=polynomial in Z_K[X] closest to prod_gc(X-th2(gc)) where
! 627: the product is over the ray class group bnr.*/
! 628:
! 629: static GEN
! 630: computeP2(GEN bnr, GEN la, GEN flag, long prec)
! 631: {
! 632: long av=avma,tetpil,clrayno,j,fl;
! 633: GEN bnf,listray,nf,P,s,Pnew,gc,vpro,p1,gf;
! 634:
! 635: bnf=(GEN)bnr[1]; nf=(GEN)bnf[7]; gf=gmael3(bnr,2,1,1);
! 636: listray=getallelts(nf,(GEN)bnr[5]);
! 637: clrayno=lg(listray)-1;
! 638: fl=itos(flag);
! 639: if (fl) P=cgetg(clrayno+1,t_VEC);
! 640: else P=gun;
! 641: for (j=1; j<=clrayno; j++)
! 642: {
! 643: gc=(GEN)listray[j];
! 644: s=computeth2(nf,gf,gc,la,prec);
! 645: if (typ(s)==t_VEC) {avma=av; return cgetg(1,t_VEC);}
! 646: if (fl)
! 647: {
! 648: vpro=cgetg(3,t_VEC);
! 649: vpro[1]=(long)listray[j];
! 650: vpro[2]=(long)s;
! 651: P[j]=(long)vpro;
! 652: }
! 653: else P=gmul(P,gsub(polx[0],s));
! 654: }
! 655: if (!fl)
! 656: {
! 657: Pnew=gzero;
! 658: for (j=clrayno; j>=0; j--)
! 659: {
! 660: p1=findbezk(nf,truecoeff(P,j),1,prec);
! 661: if (typ(p1)==t_VEC)
! 662: {
! 663: prec=(prec<<1)-2; avma=av;
! 664: if (DEBUGLEVEL) err(warnprec,"computeP2",prec);
! 665: return computeP2(bnr,la,flag,prec);
! 666: }
! 667: Pnew=gadd(p1,gmul(polx[0],Pnew));
! 668: }
! 669: P=Pnew;
! 670: }
! 671: tetpil=avma; return gerepile(av,tetpil,gcopy(P));
! 672: }
! 673:
! 674: static GEN
! 675: compocyclo(GEN nf, long m, long d, long prec)
! 676: {
! 677: GEN p1,p2,p3,D,res,pol4,nf4;
! 678: long ell,vx,ph;
! 679:
! 680: D=(GEN)nf[3];
! 681: p1=quadhilbertimag(D, gzero);
! 682: p2=cyclo(m,0);
! 683: if (d==1)
! 684: {
! 685: ph=degree(p2);
! 686: p2=gmul(gpuigs(polx[0],ph),gsubst(p2,0,gdiv(polx[MAXVARN],polx[0])));
! 687: return gsubst(subres(p1,p2),MAXVARN,polx[0]);
! 688: }
! 689: ell = m%2 ? m : (m>>2);
! 690: if (!signe(addsi(ell,D)))
! 691: {
! 692: p2=gcoeff(nffactor(nf,p2),1,1);
! 693: ph=degree(p2);
! 694: p2=gmul(gpuigs(polx[0],ph),gsubst(p2,0,gdiv(polx[MAXVARN],polx[0])));
! 695: return gsubst(subres(p1,p2),MAXVARN,polx[0]);
! 696: }
! 697: if (ell%4==3) ell= -ell;
! 698: p3=cgetg(5,t_POL);
! 699: p3[1]=evalsigne(1)|evallgef(5)|evalvarn(0);
! 700: p3[2]=lstoi((1-ell)>>2);
! 701: p3[3]=p3[4]=un;
! 702: res=rnfequation2(nf,p3);
! 703: vx=varn((GEN)nf[1]);
! 704: pol4=gsubst((GEN)res[1],0,polx[vx]);
! 705: nf4=initalg(pol4,prec);
! 706: p1=gcoeff(nffactor(nf4,p1),1,1);
! 707: p2=gcoeff(nffactor(nf4,p2),1,1);
! 708: ph=degree(p2);
! 709: p2=gmul(gpuigs(polx[0],ph),gsubst(p2,0,gdiv(polx[MAXVARN],polx[0])));
! 710: p3=gsubst(subres(p1,p2),MAXVARN,polx[0]);
! 711: p1=gmodulcp(gsubst(lift((GEN)res[2]),0,polx[vx]),pol4);
! 712: return gsubst(lift0(p3,vx),vx,p1);
! 713: }
! 714:
! 715: static GEN
! 716: retflag(GEN x, GEN flag)
! 717: {
! 718: if (itos(flag)) err(impl,"some special cases in quadray (flag=1)");
! 719: /* to be done */
! 720: return x;
! 721: }
! 722:
! 723: /* Treat special cases directly. Exit with 0 if not special case. Internal,
! 724: no stack treatment. */
! 725: static GEN
! 726: treatspecialsigma(GEN nf, GEN gf, GEN flag, long prec)
! 727: {
! 728: GEN D,p1,p2,tryf,fa;
! 729: long Ds,flf,lfa,i;
! 730:
! 731: D=(GEN)nf[3];
! 732: if (cmpis(D,-3)==0)
! 733: {
! 734: p1=idmat(2); p2=gcoeff(gf,1,1);
! 735: if (gegal(gf,gmul(p1,p2)) && (cmpis(p2,4)==0 || cmpis(p2,5)==0 || cmpis(p2,7)==0))
! 736: return retflag(cyclo(itos(p2),0),flag);
! 737: p1=idealpows(nf,(GEN)primedec(nf,stoi(3))[1],3);
! 738: if (gegal(gf,p1))
! 739: {
! 740: p1=gcoeff(nffactor(nf,cyclo(3,0)),1,1);
! 741: p1=gneg(polcoeff0(p1,0,0)); /* should be zeta_3 */
! 742: p2=cgetg(6,t_POL);
! 743: p2[1]=evalsigne(1)|evallgef(6)|evalvarn(0);
! 744: p2[2]=(long)p1; p2[3]=p2[4]=zero; p2[5]=un;
! 745: return retflag(p2,flag);
! 746: }
! 747: return gzero;
! 748: }
! 749: if (cmpis(D,-4)==0)
! 750: {
! 751: p1=idmat(2); p2=gcoeff(gf,1,1);
! 752: if (gegal(gf,gmul(p1,p2)))
! 753: {
! 754: if (cmpis(p2,3)==0 || cmpis(p2,5)==0)
! 755: return retflag(cyclo(itos(p2),0),flag);
! 756: if (cmpis(p2,4)==0)
! 757: {
! 758: p1=gcoeff(nffactor(nf,cyclo(4,0)),1,1);
! 759: p1=gneg(polcoeff0(p1,0,0)); /* should be zeta_4=I */
! 760: p2=cgetg(5,t_POL);
! 761: p2[1]=evalsigne(1)|evallgef(5)|evalvarn(0);
! 762: p2[2]=(long)p1; p2[3]=zero; p2[4]=un;
! 763: return retflag(p2,flag);
! 764: }
! 765: }
! 766: return gzero;
! 767: }
! 768: p1=idmat(2); p2=gcoeff(gf,1,1); Ds=itos(modis(D,48));
! 769: if (gegal(gf,gmul(p1,p2)))
! 770: {
! 771: if (cmpis(p2,2)==0 && Ds%16==8)
! 772: return retflag(compocyclo(nf,4,1,prec),flag);
! 773: if (cmpis(p2,3)==0 && Ds%3==1)
! 774: return retflag(compocyclo(nf,3,1,prec),flag);
! 775: if (cmpis(p2,4)==0 && Ds%8==1)
! 776: return retflag(compocyclo(nf,4,1,prec),flag);
! 777: if (cmpis(p2,6)==0 && Ds%48==40)
! 778: return retflag(compocyclo(nf,12,1,prec),flag);
! 779: return gzero;
! 780: }
! 781: p1=gcoeff(gf,2,2);
! 782: if (gcmp1(p1)) {flf=1; tryf=p2;}
! 783: else
! 784: {
! 785: if (cmpis(p1,2) || mpodd(p2) || mpodd(gcoeff(gf,1,2))) return gzero;
! 786: flf=2; tryf=gmul2n(p2,-1);
! 787: }
! 788: fa=(GEN)factor(D)[1]; lfa=lg(fa);
! 789: for (i=1; i<lfa; i++)
! 790: if (cmpis((GEN)fa[i],3)>0 && gegal((GEN)fa[i],tryf))
! 791: {
! 792: if (flf==1) return retflag(compocyclo(nf,itos(tryf),2,prec),flag);
! 793: if (Ds%16==8) return retflag(compocyclo(nf,4*itos(tryf),2,prec),flag);
! 794: return gzero;
! 795: }
! 796: return gzero;
! 797: }
! 798:
! 799: /* Compute ray class field polynomial using sigma; if flag=1, pairs
! 800: [ideals,roots] are given instead so that congruence subgroups can be used */
! 801:
! 802: static GEN
! 803: quadrayimagsigma(GEN bnr, GEN flag, long prec)
! 804: {
! 805: long av=avma,tetpil,a,b,f2;
! 806: GEN allf,bnf,nf,pol,w,wbas,gf,la,p1,p2,y,labas,gfi;
! 807:
! 808: allf=conductor(bnr,gzero,2,prec);
! 809: bnr=(GEN)allf[2]; gf=gmael(allf,1,1);
! 810: if (gcmp1(dethnf(gf)))
! 811: {
! 812: if (typ(flag)!=t_INT) flag=(GEN)flag[2];
! 813: p1=quadhilbertimag(gmael3(bnr,1,7,3),flag);
! 814: if (itos(flag))
! 815: {
! 816: /* convertir les formes en ideaux */
! 817: }
! 818: tetpil=avma; return gerepile(av,tetpil,gcopy(p1));
! 819: }
! 820: bnf=(GEN)bnr[1]; nf=(GEN)bnf[7]; pol=(GEN)nf[1];
! 821: p1=treatspecialsigma(nf,gf,flag,prec);
! 822: if (!gcmp0(p1)) {tetpil=avma; return gerepile(av,tetpil,gcopy(p1));}
! 823: w=gmodulcp(polx[varn(pol)],pol);
! 824: wbas=algtobasis(nf,w);
! 825: f2=itos(gmul2n(gcoeff(gf,1,1),1));
! 826: gfi=invmat(gf);
! 827: for (a=0; a<f2; a++)
! 828: {
! 829: for (b=0; b<f2; b++)
! 830: {
! 831: if (DEBUGLEVEL>=2) fprintferr("[%ld,%ld] ",a,b);
! 832: la=gaddgs(gmulsg(a,w),b);
! 833: p1=gnorm(la);
! 834: if (gcmp1(modis(p1,f2)))
! 835: {
! 836: labas=gadd(gmulsg(a,wbas),algtobasis(nf,stoi(b)));
! 837: if (gcmp1(denom(gmul(gfi,gadd(labas,algtobasis(nf,stoi(-1))))))) continue;
! 838: if (gcmp1(denom(gmul(gfi,gadd(labas,algtobasis(nf,gun)))))) continue;
! 839: if (!cmpis((GEN)nf[3],-4))
! 840: {
! 841: p1=gcoeff(nffactor(nf,cyclo(4,0)),1,1);
! 842: p1=algtobasis(nf,polcoeff0(p1,0,0)); /* should be -I */
! 843: if (gcmp1(denom(gmul(gfi,gadd(labas,p1))))) continue;
! 844: if (gcmp1(denom(gmul(gfi,gsub(labas,p1))))) continue;
! 845: }
! 846: if (!cmpis((GEN)nf[3],-3))
! 847: {
! 848: p1=(GEN)nffactor(nf,cyclo(3,0))[1];
! 849: p2=algtobasis(nf,polcoeff0((GEN)p1[1],0,0)); /* -zeta_3^2 */
! 850: p1=algtobasis(nf,polcoeff0((GEN)p1[2],0,0)); /* should be -zeta_3 */
! 851: if (gcmp1(denom(gmul(gfi,gadd(labas,p1))))) continue;
! 852: if (gcmp1(denom(gmul(gfi,gsub(labas,p1))))) continue;
! 853: if (gcmp1(denom(gmul(gfi,gadd(labas,p2))))) continue;
! 854: if (gcmp1(denom(gmul(gfi,gsub(labas,p2))))) continue;
! 855: }
! 856: if (DEBUGLEVEL)
! 857: {
! 858: if (DEBUGLEVEL>=2) fprintferr("\n");
! 859: fprintferr("lambda = ");
! 860: outerr(la);
! 861: }
! 862: tetpil=avma;
! 863: y=computeP2(bnr,la,flag,prec);
! 864: return gerepile(av,tetpil,y);
! 865: }
! 866: }
! 867: }
! 868: err(talker,"bug in quadrayimagsigma, please report");
! 869: return gzero;
! 870: }
! 871:
! 872: GEN
! 873: quadray(GEN D, GEN f, GEN flag, long prec)
! 874: {
! 875: long av=avma,tetpil;
! 876: GEN bnr,y,p1,pol,bnf,flagnew;
! 877:
! 878: if (typ(D)!=t_INT)
! 879: {
! 880: bnf = checkbnf(D);
! 881: if (degree(gmael(bnf,7,1))!=2)
! 882: err(talker,"not a polynomial of degree 2 in quadray");
! 883: D=gmael(bnf,7,3);
! 884: }
! 885: else
! 886: {
! 887: if (!isfundamental(D))
! 888: err(talker,"quadray needs a fundamental discriminant");
! 889: pol=quadpoly(D); setvarn(pol, fetch_user_var("y"));
! 890: bnf=bnfinit0(pol,0,NULL,prec);
! 891: }
! 892: bnr=bnrinit0(bnf,f,1,prec);
! 893: if (gcmp1(gmael(bnr,5,1)))
! 894: {
! 895: avma=av; if (!flag || gcmp0(flag)) return polx[0];
! 896: y=cgetg(2,t_VEC); p1=cgetg(3,t_VEC); y[1]=(long)p1;
! 897: p1[1]=(long)idmat(2); p1[2]=(long)polx[0];
! 898: return y;
! 899: }
! 900: tetpil=avma;
! 901: if (signe(D)>0)
! 902: {
! 903: if (flag && !gcmp0(flag)) err(warner,"ignoring flag in quadray");
! 904: y=bnrstark(bnr,gzero,1,prec);
! 905: }
! 906: else
! 907: {
! 908: if (!flag) flag = gzero;
! 909: flagnew=flag;
! 910: if (typ(flagnew)==t_INT)
! 911: {
! 912: flagnew=absi(flagnew);
! 913: if (cmpis(flagnew,1)<=0) y=quadrayimagsigma(bnr,flagnew,prec);
! 914: else y=quadrayimagwei(bnr,mpodd(flagnew) ? gun : gzero,prec);
! 915: }
! 916: else
! 917: {
! 918: if (typ(flagnew)!=t_VEC || lg(flagnew)<=2) err(flagerr,"quadray");
! 919: y=computeP2(bnr,(GEN)flagnew[1],(GEN)flagnew[2],prec);
! 920: }
! 921: if (typ(y)==t_VEC && lg(y)==1)
! 922: {
! 923: prec=(prec<<1)-2; avma=av;
! 924: if (DEBUGLEVEL) err(warnprec,"quadray",prec);
! 925: return quadray(D,f,flag,prec);
! 926: }
! 927: }
! 928: return gerepile(av,tetpil,y);
! 929: }
! 930:
! 931: /*******************************************************************/
! 932: /* */
! 933: /* Routines related to binary quadratic forms (for internal use) */
! 934: /* */
! 935: /*******************************************************************/
! 936:
! 937: static void
! 938: rhoreal_aux2(GEN x, GEN y)
! 939: {
! 940: GEN p1,p2;
! 941: long s = signe(x[3]);
! 942:
! 943: y[1]=x[3]; setsigne(y[1],1);
! 944: p2 = (cmpii(isqrtD,(GEN)y[1]) >= 0)? isqrtD: (GEN) y[1];
! 945: p1 = shifti((GEN)y[1],1);
! 946: p2 = divii(addii(p2,(GEN)x[2]), p1);
! 947: y[2] = lsubii(mulii(p2,p1),(GEN)x[2]);
! 948:
! 949: setsigne(y[1],s);
! 950: p1 = shifti(subii(sqri((GEN)y[2]),Disc),-2);
! 951: y[3] = ldivii(p1,(GEN)y[1]);
! 952: }
! 953:
! 954: static GEN
! 955: rhoreal_aux(GEN x)
! 956: {
! 957: GEN y = cgetg(6,t_VEC);
! 958: long e;
! 959:
! 960: rhoreal_aux2(x,y);
! 961: switch(lg(x))
! 962: {
! 963: case 4: case 5: setlg(y,4); break;
! 964: case 6:
! 965: y[5]=lmulrr(divrr(addir((GEN)x[2],sqrtD),subir((GEN)x[2],sqrtD)),
! 966: (GEN)x[5]);
! 967: e = expo(y[5]);
! 968: if (e < EXP220) y[4]=x[4];
! 969: else
! 970: {
! 971: y[4]=laddsi(1,(GEN)x[4]);
! 972: setexpo(y[5], e - EXP220);
! 973: }
! 974: }
! 975: return y;
! 976: }
! 977:
! 978: static GEN
! 979: rhorealform(GEN x)
! 980: {
! 981: long av=avma,tetpil;
! 982: x = rhoreal_aux(x); tetpil=avma;
! 983: return gerepile(av,tetpil,gcopy(x));
! 984: }
! 985:
! 986: static GEN
! 987: redrealform(GEN x)
! 988: {
! 989: long l;
! 990: GEN p1;
! 991:
! 992: for(;;)
! 993: {
! 994: if (signe(x[2]) > 0 && cmpii((GEN)x[2],isqrtD) <= 0)
! 995: {
! 996: p1 = subii(isqrtD, shifti(absi((GEN)x[1]),1));
! 997: l = absi_cmp((GEN)x[2],p1);
! 998: if (l>0 || (l==0 && signe(p1)<0)) break;
! 999: }
! 1000: x = rhoreal_aux(x);
! 1001: }
! 1002: if (signe(x[1]) < 0)
! 1003: {
! 1004: if (sens || (signe(x[3])>0 && !absi_cmp((GEN)x[1],(GEN)x[3])))
! 1005: return rhoreal_aux(x); /* narrow class group, or a = -c */
! 1006: setsigne(x[1],1); setsigne(x[3],-1);
! 1007: }
! 1008: return x;
! 1009: }
! 1010:
! 1011: static GEN
! 1012: redrealform_init(GEN x)
! 1013: {
! 1014: long av=avma, tetpil;
! 1015: GEN y = cgetg(6,t_VEC);
! 1016:
! 1017: y[1]=x[1]; y[2]=x[2]; y[3]=x[3]; y[4]=zero;
! 1018: y[5]=(long)realun(PRECREG);
! 1019: y = redrealform(y); tetpil=avma;
! 1020: return gerepile(av,tetpil,gcopy(y));
! 1021: }
! 1022:
! 1023: static void
! 1024: compreal_aux(GEN x, GEN y, GEN z)
! 1025: {
! 1026: GEN s,n,d,d1,x1,x2,y1,y2,v1,v2,b3,c3,m,p1,r;
! 1027:
! 1028: s=shifti(addii((GEN)x[2],(GEN)y[2]),-1);
! 1029: n=subii((GEN)y[2],s);
! 1030: d=bezout((GEN)y[1],(GEN)x[1],&y1,&x1);
! 1031: d1=bezout(s,d,&x2,&y2);
! 1032: v1=divii((GEN)x[1],d1);
! 1033: v2=divii((GEN)y[1],d1);
! 1034: m=addii(mulii(mulii(y1,y2),n),mulii((GEN)y[3],x2));
! 1035: setsigne(m,-signe(m));
! 1036: r=modii(m,v1); p1=mulii(v2,r); b3=shifti(p1,1);
! 1037: c3=addii(mulii((GEN)y[3],d1),mulii(r,addii((GEN)y[2],p1)));
! 1038:
! 1039: z[1]=lmulii(v1,v2);
! 1040: z[2]=laddii((GEN)y[2],b3);
! 1041: z[3]=ldivii(c3,v1);
! 1042: }
! 1043:
! 1044: static GEN
! 1045: comprealform3(GEN x, GEN y)
! 1046: {
! 1047: long av = avma, tetpil;
! 1048: GEN z = cgetg(4,t_VEC);
! 1049: compreal_aux(x,y,z); z=redrealform(z); tetpil=avma;
! 1050: return gerepile(av,tetpil,gcopy(z));
! 1051: }
! 1052:
! 1053: static GEN
! 1054: comprealform5(GEN x, GEN y)
! 1055: {
! 1056: long av = avma,tetpil,e;
! 1057: GEN p1, z = cgetg(6,t_VEC);
! 1058:
! 1059: compreal_aux(x,y,z);
! 1060: z[5]=lmulrr((GEN)x[5],(GEN)y[5]);
! 1061: e=expo(z[5]); p1 = addii((GEN)x[4],(GEN)y[4]);
! 1062: if (e < EXP220) z[4] = (long)p1;
! 1063: else
! 1064: {
! 1065: z[4] = laddsi(1,p1);
! 1066: setexpo(z[5], e-EXP220);
! 1067: }
! 1068: z=redrealform(z); tetpil=avma;
! 1069: return gerepile(av,tetpil,gcopy(z));
! 1070: }
! 1071:
! 1072: static GEN
! 1073: initializeform5(long *ex)
! 1074: {
! 1075: long av = avma, i;
! 1076: GEN form = powsubfactorbase[1][ex[1]];
! 1077:
! 1078: for (i=2; i<=lgsub; i++)
! 1079: form = comprealform5(form, powsubfactorbase[i][ex[i]]);
! 1080: i=avma; return gerepile(av,i,gcopy(form));
! 1081: }
! 1082:
! 1083: /*******************************************************************/
! 1084: /* */
! 1085: /* Common subroutines */
! 1086: /* */
! 1087: /*******************************************************************/
! 1088: static void
! 1089: buch_init(void)
! 1090: {
! 1091: if (DEBUGLEVEL) timer2();
! 1092: primfact = new_chunk(100);
! 1093: primfact1 = new_chunk(100);
! 1094: exprimfact = new_chunk(100);
! 1095: exprimfact1 = new_chunk(100);
! 1096: badprim = new_chunk(100);
! 1097: hashtab = (long**) new_chunk(HASHT);
! 1098: }
! 1099:
! 1100: double
! 1101: check_bach(double cbach, double B)
! 1102: {
! 1103: if (cbach > B)
! 1104: err(talker,"sorry, buchxxx couldn't deal with this field PLEASE REPORT!");
! 1105: cbach *= 2; if (cbach > B) cbach = B;
! 1106: if (DEBUGLEVEL) fprintferr("\n*** Bach constant: %f\n", cbach);
! 1107: return cbach;
! 1108: }
! 1109:
! 1110: static long
! 1111: factorisequad(GEN f, long kcz, long limp)
! 1112: {
! 1113: long i,p,k,av,lo;
! 1114: GEN q,r, x = (GEN)f[1];
! 1115:
! 1116: if (is_pm1(x)) { primfact[0]=0; return 1; }
! 1117: av=avma; lo=0;
! 1118: if (signe(x) < 0) x = absi(x);
! 1119: for (i=1; ; i++)
! 1120: {
! 1121: p=factorbase[i]; q=dvmdis(x,p,&r);
! 1122: if (!signe(r))
! 1123: {
! 1124: k=0; while (!signe(r)) { x=q; k++; q=dvmdis(x,p,&r); }
! 1125: lo++; primfact[lo]=p; exprimfact[lo]=k;
! 1126: }
! 1127: if (cmpis(q,p)<=0) break;
! 1128: if (i==kcz) { avma=av; return 0; }
! 1129: }
! 1130: p = x[2]; avma=av;
! 1131: /* p = itos(x) if lgefint(x)=3 */
! 1132: if (lgefint(x)!=3 || p > limhash) return 0;
! 1133:
! 1134: if (p != 1 && p <= limp)
! 1135: {
! 1136: for (i=1; i<=badprim[0]; i++)
! 1137: if (p % badprim[i] == 0) return 0;
! 1138: lo++; primfact[lo]=p; exprimfact[lo]=1;
! 1139: p = 1;
! 1140: }
! 1141: primfact[0]=lo; return p;
! 1142: }
! 1143:
! 1144: static long *
! 1145: largeprime(long q, long *ex, long np, long nrho)
! 1146: {
! 1147: const long hashv = ((q&2047)-1)>>1;
! 1148: long *pt, i;
! 1149:
! 1150: for (pt = hashtab[hashv]; ; pt = (long*) pt[0])
! 1151: {
! 1152: if (!pt)
! 1153: {
! 1154: pt = (long*) gpmalloc((lgsub+4)<<TWOPOTBYTES_IN_LONG);
! 1155: *pt++ = nrho; /* nrho = pt[-3] */
! 1156: *pt++ = np; /* np = pt[-2] */
! 1157: *pt++ = q; /* q = pt[-1] */
! 1158: pt[0] = (long)hashtab[hashv];
! 1159: for (i=1; i<=lgsub; i++) pt[i]=ex[i];
! 1160: hashtab[hashv]=pt; return NULL;
! 1161: }
! 1162: if (pt[-1] == q) break;
! 1163: }
! 1164: for(i=1; i<=lgsub; i++)
! 1165: if (pt[i] != ex[i]) return pt;
! 1166: return (pt[-2]==np)? (GEN)NULL: pt;
! 1167: }
! 1168:
! 1169: static long
! 1170: badmod8(GEN x)
! 1171: {
! 1172: long r = mod8(x);
! 1173: if (!r) return 1;
! 1174: if (signe(Disc) < 0) r = 8-r;
! 1175: return (r < 4);
! 1176: }
! 1177:
! 1178: /* cree factorbase, numfactorbase, vectbase; affecte badprim */
! 1179: static void
! 1180: factorbasequad(GEN Disc, long n2, long n)
! 1181: {
! 1182: long i,p,bad, av = avma;
! 1183: byteptr d=diffptr;
! 1184:
! 1185: numfactorbase = (long*) gpmalloc(sizeof(long)*(n2+1));
! 1186: factorbase = (long*) gpmalloc(sizeof(long)*(n2+1));
! 1187: KC=0; bad=0; i=0; p = *d++;
! 1188: while (p<=n2)
! 1189: {
! 1190: switch(krogs(Disc,p))
! 1191: {
! 1192: case -1: break; /* inert */
! 1193: case 0: /* ramified */
! 1194: {
! 1195: GEN p1 = divis(Disc,p);
! 1196: if (smodis(p1,p) == 0)
! 1197: if (p!=2 || badmod8(p1)) { badprim[++bad]=p; break; }
! 1198: i++; numfactorbase[p]=i; factorbase[i] = -p; break;
! 1199: }
! 1200: default: /* split */
! 1201: i++; numfactorbase[p]=i; factorbase[i] = p;
! 1202: }
! 1203: p += *d++; if (!*d) err(primer1);
! 1204: if (KC == 0 && p>n) KC = i;
! 1205: }
! 1206: if (!KC) { free(factorbase); free(numfactorbase); return; }
! 1207: KC2 = i;
! 1208: vectbase = (long*) gpmalloc(sizeof(long)*(KC2+1));
! 1209: for (i=1; i<=KC2; i++)
! 1210: {
! 1211: p = factorbase[i];
! 1212: vectbase[i]=p; factorbase[i]=labs(p);
! 1213: }
! 1214: if (DEBUGLEVEL)
! 1215: {
! 1216: msgtimer("factor base");
! 1217: if (DEBUGLEVEL>7)
! 1218: {
! 1219: fprintferr("factorbase:\n");
! 1220: for (i=1; i<=KC; i++) fprintferr("%ld ",factorbase[i]);
! 1221: fprintferr("\n"); flusherr();
! 1222: }
! 1223: }
! 1224: avma=av; badprim[0] = bad;
! 1225: }
! 1226:
! 1227: /* cree vectbase and subfactorbase. Affecte lgsub */
! 1228: static long
! 1229: subfactorbasequad(double ll, long KC)
! 1230: {
! 1231: long i,j,k,nbidp,p,pro[100], ss;
! 1232: GEN p1,y;
! 1233: double prod;
! 1234:
! 1235: i=0; ss=0; prod=1;
! 1236: for (j=1; j<=KC && prod<=ll; j++)
! 1237: {
! 1238: p = vectbase[j];
! 1239: if (p>0) { pro[++i]=p; prod*=p; vperm[i]=j; } else ss++;
! 1240: }
! 1241: if (prod<=ll) return -1;
! 1242: nbidp=i;
! 1243: for (k=1; k<j; k++)
! 1244: if (vectbase[k]<=0) vperm[++i]=k;
! 1245:
! 1246: y=cgetg(nbidp+1,t_COL);
! 1247: if (PRECREG) /* real */
! 1248: for (j=1; j<=nbidp; j++)
! 1249: {
! 1250: p1=primeform(Disc,stoi(pro[j]),PRECREG);
! 1251: y[j] = (long) redrealform_init(p1);
! 1252: }
! 1253: else
! 1254: for (j=1; j<=nbidp; j++) /* imaginary */
! 1255: {
! 1256: p1=primeform(Disc,stoi(pro[j]),0);
! 1257: y[j] = (long)p1;
! 1258: }
! 1259: subbase = (long*) gpmalloc(sizeof(long)*(nbidp+1));
! 1260: lgsub = nbidp; for (j=1; j<=lgsub; j++) subbase[j]=pro[j];
! 1261: if (DEBUGLEVEL>7)
! 1262: {
! 1263: fprintferr("subfactorbase: ");
! 1264: for (i=1; i<=lgsub; i++)
! 1265: { fprintferr("%ld: ",subbase[i]); outerr((GEN)y[i]); }
! 1266: fprintferr("\n"); flusherr();
! 1267: }
! 1268: subfactorbase = y; return ss;
! 1269: }
! 1270:
! 1271: static void
! 1272: powsubfact(long n, long a)
! 1273: {
! 1274: GEN unform, **x = (GEN**) gpmalloc(sizeof(GEN*)*(n+1));
! 1275: long i,j;
! 1276:
! 1277: for (i=1; i<=n; i++)
! 1278: x[i] = (GEN*) gpmalloc(sizeof(GEN)*(a+1));
! 1279: if (PRECREG) /* real */
! 1280: {
! 1281: unform=cgetg(6,t_VEC);
! 1282: unform[1]=un;
! 1283: unform[2]=(mod2(Disc) == mod2(isqrtD))? (long)isqrtD: laddsi(-1,isqrtD);
! 1284: unform[3]=lshifti(subii(sqri((GEN)unform[2]),Disc),-2);
! 1285: unform[4]=zero;
! 1286: unform[5]=(long)realun(PRECREG);
! 1287: for (i=1; i<=n; i++)
! 1288: {
! 1289: x[i][0] = unform;
! 1290: for (j=1; j<=a; j++)
! 1291: x[i][j]=comprealform5(x[i][j-1],(GEN)subfactorbase[i]);
! 1292: }
! 1293: }
! 1294: else /* imaginary */
! 1295: {
! 1296: unform=cgetg(4,t_QFI);
! 1297: unform[1]=un;
! 1298: unform[2]=mod2(Disc)? un: zero;
! 1299: unform[3]=lshifti(absi(Disc),-2);
! 1300: for (i=1; i<=n; i++)
! 1301: {
! 1302: x[i][0] = unform;
! 1303: for (j=1; j<=a; j++)
! 1304: x[i][j]=compimag(x[i][j-1],(GEN)subfactorbase[i]);
! 1305: }
! 1306: }
! 1307: if (DEBUGLEVEL) msgtimer("powsubfact");
! 1308: powsubfactorbase = x;
! 1309: }
! 1310:
! 1311: static void
! 1312: desalloc(long **mat)
! 1313: {
! 1314: long i,*p,*q;
! 1315:
! 1316: free(vectbase); free(factorbase); free(numfactorbase);
! 1317: if (mat)
! 1318: {
! 1319: free(subbase);
! 1320: for (i=1; i<lg(subfactorbase); i++) free(powsubfactorbase[i]);
! 1321: for (i=1; i<lg(mat); i++) free(mat[i]);
! 1322: free(mat); free(powsubfactorbase);
! 1323: for (i=1; i<HASHT; i++)
! 1324: for (p = hashtab[i]; p; p = q) { q=(long*)p[0]; free(p-3); }
! 1325: }
! 1326: }
! 1327:
! 1328: /* L-function */
! 1329: static GEN
! 1330: lfunc(GEN Disc)
! 1331: {
! 1332: long av=avma, p;
! 1333: GEN y=realun(DEFAULTPREC);
! 1334: byteptr d=diffptr;
! 1335:
! 1336: for(p = *d++; p<=30000; p += *d++)
! 1337: {
! 1338: if (!*d) err(primer1);
! 1339: y = mulsr(p, divrs(y, p-krogs(Disc,p)));
! 1340: }
! 1341: return gerepileupto(av,y);
! 1342: }
! 1343:
! 1344: #define comp(x,y) x? (PRECREG? compreal(x,y): compimag(x,y)): y
! 1345: static GEN
! 1346: get_clgp(GEN Disc, GEN W, GEN *ptmet, long prec)
! 1347: {
! 1348: GEN p1,p2,res,*init, u1u2=smith2(W), u1=(GEN)u1u2[1], met=(GEN)u1u2[3];
! 1349: long c,i,j, l = lg(met);
! 1350:
! 1351: u1 = reducemodmatrix(ginv(u1), W);
! 1352: for (c=1; c<l; c++)
! 1353: if (gcmp1(gcoeff(met,c,c))) break;
! 1354: if (DEBUGLEVEL) msgtimer("smith/class group");
! 1355: res=cgetg(c,t_VEC); init = (GEN*)cgetg(l,t_VEC);
! 1356: for (i=1; i<l; i++)
! 1357: init[i] = primeform(Disc,stoi(labs(vectbase[vperm[i]])),prec);
! 1358: for (j=1; j<c; j++)
! 1359: {
! 1360: p1 = NULL;
! 1361: for (i=1; i<l; i++)
! 1362: {
! 1363: p2 = gpui(init[i], gcoeff(u1,i,j), prec);
! 1364: p1 = comp(p1,p2);
! 1365: }
! 1366: res[j] = (long)p1;
! 1367: }
! 1368: if (DEBUGLEVEL) msgtimer("generators");
! 1369: *ptmet = met; return res;
! 1370: }
! 1371:
! 1372: static GEN
! 1373: extra_relations(long LIMC, long *ex, long nlze, GEN extramatc)
! 1374: {
! 1375: long av,fpc,p,ep,i,j,k,nlze2, *col, *colg, s = 0, extrarel = nlze+2;
! 1376: long MAXRELSUP = min(50,4*KC);
! 1377: GEN p1,form, extramat = cgetg(extrarel+1,t_MAT);
! 1378:
! 1379: if (DEBUGLEVEL)
! 1380: {
! 1381: fprintferr("looking for %ld extra relations\n",extrarel);
! 1382: flusherr();
! 1383: }
! 1384: for (j=1; j<=extrarel; j++) extramat[j]=lgetg(KC+1,t_COL);
! 1385: nlze2 = PRECREG? max(nlze,lgsub): min(nlze+1,KC);
! 1386: if (nlze2 < 3 && KC > 2) nlze2 = 3;
! 1387: av = avma;
! 1388: while (s<extrarel)
! 1389: {
! 1390: form = NULL;
! 1391: for (i=1; i<=nlze2; i++)
! 1392: {
! 1393: ex[i]=mymyrand()>>randshift;
! 1394: if (ex[i])
! 1395: {
! 1396: p1 = primeform(Disc,stoi(factorbase[vperm[i]]),PRECREG);
! 1397: p1 = gpuigs(p1,ex[i]); form = comp(form,p1);
! 1398: }
! 1399: }
! 1400: if (!form) continue;
! 1401:
! 1402: fpc = factorisequad(form,KC,LIMC);
! 1403: if (fpc==1)
! 1404: {
! 1405: s++; col = (GEN)extramat[s];
! 1406: for (i=1; i<=nlze2; i++) col[vperm[i]] = -ex[i];
! 1407: for ( ; i<=KC; i++) col[vperm[i]]= 0;
! 1408: for (j=1; j<=primfact[0]; j++)
! 1409: {
! 1410: p=primfact[j]; ep=exprimfact[j];
! 1411: if (smodis((GEN)form[2], p<<1) > p) ep = -ep;
! 1412: col[numfactorbase[p]] += ep;
! 1413: }
! 1414: for (i=1; i<=KC; i++)
! 1415: if (col[i]) break;
! 1416: if (i>KC)
! 1417: {
! 1418: s--; avma = av;
! 1419: if (--MAXRELSUP == 0) return NULL;
! 1420: }
! 1421: else { av = avma; if (PRECREG) coeff(extramatc,1,s) = form[4]; }
! 1422: }
! 1423: else avma = av;
! 1424: if (DEBUGLEVEL)
! 1425: {
! 1426: if (fpc == 1) fprintferr(" %ld",s);
! 1427: else if (DEBUGLEVEL>1) fprintferr(".");
! 1428: flusherr();
! 1429: }
! 1430: }
! 1431: for (j=1; j<=extrarel; j++)
! 1432: {
! 1433: colg = cgetg(KC+1,t_COL);
! 1434: col = (GEN)extramat[j]; extramat[j] = (long) colg;
! 1435: for (k=1; k<=KC; k++)
! 1436: colg[k] = lstoi(col[vperm[k]]);
! 1437: }
! 1438: if (DEBUGLEVEL)
! 1439: {
! 1440: fprintferr("\n");
! 1441: msgtimer("extra relations");
! 1442: }
! 1443: return extramat;
! 1444: }
! 1445: #undef comp
! 1446:
! 1447: /*******************************************************************/
! 1448: /* */
! 1449: /* Imaginary Quadratic fields */
! 1450: /* */
! 1451: /*******************************************************************/
! 1452:
! 1453: static GEN
! 1454: imag_random_form(long current, long *ex)
! 1455: {
! 1456: long av = avma,i;
! 1457: GEN form,pc;
! 1458:
! 1459: for(;;)
! 1460: {
! 1461: form = pc = primeform(Disc,stoi(factorbase[current]),PRECREG);
! 1462: for (i=1; i<=lgsub; i++)
! 1463: {
! 1464: ex[i] = mymyrand()>>randshift;
! 1465: if (ex[i])
! 1466: form = compimag(form,powsubfactorbase[i][ex[i]]);
! 1467: }
! 1468: if (form != pc) return form;
! 1469: avma = av; /* ex = 0, try again */
! 1470: }
! 1471: }
! 1472:
! 1473: static void
! 1474: imag_relations(long lim, long s, long LIMC, long *ex, long **mat)
! 1475: {
! 1476: static long nbtest;
! 1477: long av = avma, i,j,pp,fpc,b1,b2,ep,current, first = (s==0);
! 1478: long *col,*fpd,*oldfact,*oldexp;
! 1479: GEN pc,form,form1;
! 1480:
! 1481: if (first) nbtest = 0 ;
! 1482: while (s<lim)
! 1483: {
! 1484: avma=av; nbtest++; current = first? 1+(s%KC): 1+s-RELSUP;
! 1485: form = imag_random_form(current,ex);
! 1486: fpc = factorisequad(form,KC,LIMC);
! 1487: if (!fpc)
! 1488: {
! 1489: if (DEBUGLEVEL>1) { fprintferr("."); flusherr(); }
! 1490: continue;
! 1491: }
! 1492: if (fpc > 1)
! 1493: {
! 1494: fpd = largeprime(fpc,ex,current,0);
! 1495: if (!fpd)
! 1496: {
! 1497: if (DEBUGLEVEL>1) { fprintferr("."); flusherr(); }
! 1498: continue;
! 1499: }
! 1500: form1 = powsubfactorbase[1][fpd[1]];
! 1501: for (i=2; i<=lgsub; i++)
! 1502: form1 = compimag(form1,powsubfactorbase[i][fpd[i]]);
! 1503: pc=primeform(Disc,stoi(factorbase[fpd[-2]]),0);
! 1504: form1=compimag(form1,pc);
! 1505: pp = fpc << 1;
! 1506: b1=smodis((GEN)form1[2], pp);
! 1507: b2=smodis((GEN)form[2], pp);
! 1508: if (b1 != b2 && b1+b2 != pp) continue;
! 1509:
! 1510: s++; col = mat[s];
! 1511: if (DEBUGLEVEL) { fprintferr(" %ld",s); flusherr(); }
! 1512: oldfact = primfact; oldexp = exprimfact;
! 1513: primfact = primfact1; exprimfact = exprimfact1;
! 1514: factorisequad(form1,KC,LIMC);
! 1515:
! 1516: if (b1==b2)
! 1517: {
! 1518: for (i=1; i<=lgsub; i++)
! 1519: col[numfactorbase[subbase[i]]] = fpd[i]-ex[i];
! 1520: col[fpd[-2]]++;
! 1521: for (j=1; j<=primfact[0]; j++)
! 1522: {
! 1523: pp=primfact[j]; ep=exprimfact[j];
! 1524: if (smodis((GEN)form1[2], pp<<1) > pp) ep = -ep;
! 1525: col[numfactorbase[pp]] -= ep;
! 1526: }
! 1527: }
! 1528: else
! 1529: {
! 1530: for (i=1; i<=lgsub; i++)
! 1531: col[numfactorbase[subbase[i]]] = -fpd[i]-ex[i];
! 1532: col[fpd[-2]]--;
! 1533: for (j=1; j<=primfact[0]; j++)
! 1534: {
! 1535: pp=primfact[j]; ep=exprimfact[j];
! 1536: if (smodis((GEN)form1[2], pp<<1) > pp) ep = -ep;
! 1537: col[numfactorbase[pp]] += ep;
! 1538: }
! 1539: }
! 1540: primfact = oldfact; exprimfact = oldexp;
! 1541: }
! 1542: else
! 1543: {
! 1544: s++; col = mat[s];
! 1545: if (DEBUGLEVEL) { fprintferr(" %ld",s); flusherr(); }
! 1546: for (i=1; i<=lgsub; i++)
! 1547: col[numfactorbase[subbase[i]]] = -ex[i];
! 1548: }
! 1549: for (j=1; j<=primfact[0]; j++)
! 1550: {
! 1551: pp=primfact[j]; ep=exprimfact[j];
! 1552: if (smodis((GEN)form[2], pp<<1) > pp) ep = -ep;
! 1553: col[numfactorbase[pp]] += ep;
! 1554: }
! 1555: col[current]--;
! 1556: if (!first && fpc == 1 && col[current] == 0)
! 1557: {
! 1558: s--; for (i=1; i<=KC; i++) col[i]=0;
! 1559: }
! 1560: }
! 1561: if (DEBUGLEVEL)
! 1562: {
! 1563: fprintferr("\nnbrelations/nbtest = %ld/%ld\n",s,nbtest);
! 1564: msgtimer("%s relations", first? "initial": "random");
! 1565: }
! 1566: }
! 1567:
! 1568: static int
! 1569: imag_be_honest(long *ex)
! 1570: {
! 1571: long p,fpc, s = KC, nbtest = 0, av = avma;
! 1572: GEN form;
! 1573:
! 1574: while (s<KC2)
! 1575: {
! 1576: p = factorbase[s+1];
! 1577: if (DEBUGLEVEL) { fprintferr(" %ld",p); flusherr(); }
! 1578: form = imag_random_form(s+1,ex);
! 1579: fpc = factorisequad(form,s,p-1);
! 1580: if (fpc == 1) { nbtest=0; s++; }
! 1581: else
! 1582: {
! 1583: nbtest++; if (nbtest>20) return 0;
! 1584: }
! 1585: avma = av;
! 1586: }
! 1587: return 1;
! 1588: }
! 1589:
! 1590: /*******************************************************************/
! 1591: /* */
! 1592: /* Real Quadratic fields */
! 1593: /* */
! 1594: /*******************************************************************/
! 1595:
! 1596: static GEN
! 1597: real_random_form(long *ex)
! 1598: {
! 1599: long av = avma, i;
! 1600: GEN p1,form = NULL;
! 1601:
! 1602: for(;;)
! 1603: {
! 1604: for (i=1; i<=lgsub; i++)
! 1605: {
! 1606: ex[i] = mymyrand()>>randshift;
! 1607: /* if (ex[i]) KB: BUG if I put this in. Why ??? */
! 1608: {
! 1609: p1 = powsubfactorbase[i][ex[i]];
! 1610: form = form? comprealform3(form,p1): p1;
! 1611: }
! 1612: }
! 1613: if (form) return form;
! 1614: avma = av;
! 1615: }
! 1616: }
! 1617:
! 1618: static void
! 1619: real_relations(long lim, long s, long LIMC, long *ex, long **mat, GEN glog2,
! 1620: GEN vecexpo)
! 1621: {
! 1622: static long nbtest;
! 1623: long av = avma,av1,av2,tetpil,i,j,p,fpc,b1,b2,ep,current, first = (s==0);
! 1624: long *col,*fpd,*oldfact,*oldexp,limstack;
! 1625: long findecycle,nbrhocumule,nbrho;
! 1626: GEN p1,p2,form,form0,form1,form2;
! 1627:
! 1628: limstack=stack_lim(av,1);
! 1629: if (first) { nbtest = 0; current = 0; }
! 1630: while (s<lim)
! 1631: {
! 1632: form = real_random_form(ex);
! 1633: if (!first)
! 1634: {
! 1635: current = 1+s-RELSUP;
! 1636: p1=redrealform(primeform(Disc,stoi(factorbase[current]),PRECREG));
! 1637: form = comprealform3(form,p1);
! 1638: }
! 1639: form0 = form; form1 = NULL;
! 1640: findecycle = nbrhocumule = 0;
! 1641: nbrho = -1; av1 = avma;
! 1642: while (s<lim)
! 1643: {
! 1644: if (low_stack(limstack, stack_lim(av,1)))
! 1645: {
! 1646: tetpil=avma;
! 1647: if(DEBUGMEM>1) err(warnmem,"real_relations [1]");
! 1648: if (!form1) form=gerepile(av1,tetpil,gcopy(form));
! 1649: else
! 1650: {
! 1651: GEN *gptr[2]; gptr[0]=&form1; gptr[1]=&form;
! 1652: gerepilemany(av1,gptr,2);
! 1653: }
! 1654: }
! 1655: if (nbrho < 0) nbrho = 0; /* first time in */
! 1656: else
! 1657: {
! 1658: if (findecycle) break;
! 1659: form = rhorealform(form);
! 1660: nbrho++; nbrhocumule++;
! 1661: if (first)
! 1662: {
! 1663: if (absi_equal((GEN)form[1],(GEN)form0[1])
! 1664: && egalii((GEN)form[2],(GEN)form0[2])
! 1665: && (!sens || signe(form0[1])==signe(form[1]))) findecycle=1;
! 1666: }
! 1667: else
! 1668: {
! 1669: if (sens || !signe(addii((GEN)form[1],(GEN)form[3])))
! 1670: { form=rhorealform(form); nbrho++; }
! 1671: else
! 1672: { setsigne(form[1],1); setsigne(form[3],-1); }
! 1673: if (egalii((GEN)form[1],(GEN)form0[1]) &&
! 1674: egalii((GEN)form[2],(GEN)form0[2])) break;
! 1675: }
! 1676: }
! 1677: nbtest++; fpc = factorisequad(form,KC,LIMC);
! 1678: if (!fpc)
! 1679: {
! 1680: if (DEBUGLEVEL>1) { fprintferr("."); flusherr(); }
! 1681: continue;
! 1682: }
! 1683: if (fpc > 1)
! 1684: {
! 1685: fpd = largeprime(fpc,ex,current,nbrhocumule);
! 1686: if (!fpd)
! 1687: {
! 1688: if (DEBUGLEVEL>1) { fprintferr("."); flusherr(); }
! 1689: continue;
! 1690: }
! 1691: if (!form1) form1 = initializeform5(ex);
! 1692: if (!first)
! 1693: {
! 1694: p1 = primeform(Disc,stoi(factorbase[current]),PRECREG);
! 1695: p1 = redrealform_init(p1); form1=comprealform5(form1,p1);
! 1696: }
! 1697: av2=avma;
! 1698: for (i=1; i<=nbrho; i++)
! 1699: {
! 1700: form1 = rhorealform(form1);
! 1701: if (low_stack(limstack, stack_lim(av,1)))
! 1702: {
! 1703: if(DEBUGMEM>1) err(warnmem,"real_relations [2]");
! 1704: tetpil=avma; form1=gerepile(av2,tetpil,gcopy(form1));
! 1705: }
! 1706: }
! 1707: nbrho = 0;
! 1708:
! 1709: form2=powsubfactorbase[1][fpd[1]];
! 1710: for (i=2; i<=lgsub; i++)
! 1711: form2 = comprealform5(form2,powsubfactorbase[i][fpd[i]]);
! 1712: if (fpd[-2])
! 1713: {
! 1714: p1 = primeform(Disc,stoi(factorbase[fpd[-2]]), PRECREG);
! 1715: p1 = redrealform_init(p1); form2=comprealform5(form2,p1);
! 1716: }
! 1717: av2=avma;
! 1718: for (i=1; i<=fpd[-3]; i++)
! 1719: {
! 1720: form2 = rhorealform(form2);
! 1721: if (low_stack(limstack, stack_lim(av,1)))
! 1722: {
! 1723: if(DEBUGMEM>1) err(warnmem,"real_relations [3]");
! 1724: tetpil=avma; form2=gerepile(av2,tetpil,gcopy(form2));
! 1725: }
! 1726: }
! 1727: if (!sens && signe(addii((GEN)form2[1],(GEN)form2[3])))
! 1728: {
! 1729: setsigne(form2[1],1);
! 1730: setsigne(form2[3],-1);
! 1731: }
! 1732: p = fpc << 1;
! 1733: b1=smodis((GEN)form2[2], p);
! 1734: b2=smodis((GEN)form1[2], p);
! 1735: if (b1 != b2 && b1+b2 != p) continue;
! 1736:
! 1737: s++; col = mat[s]; if (DEBUGLEVEL) fprintferr(" %ld",s);
! 1738: oldfact = primfact; oldexp = exprimfact;
! 1739: primfact = primfact1; exprimfact = exprimfact1;
! 1740: factorisequad(form2,KC,LIMC);
! 1741: if (b1==b2)
! 1742: {
! 1743: for (i=1; i<=lgsub; i++)
! 1744: col[numfactorbase[subbase[i]]] = fpd[i]-ex[i];
! 1745: for (j=1; j<=primfact[0]; j++)
! 1746: {
! 1747: p=primfact[j]; ep=exprimfact[j];
! 1748: if (smodis((GEN)form2[2], p<<1) > p) ep = -ep;
! 1749: col[numfactorbase[p]] -= ep;
! 1750: }
! 1751: if (fpd[-2]) col[fpd[-2]]++; /* implies !first */
! 1752: p1 = subii((GEN)form1[4],(GEN)form2[4]);
! 1753: p2 = divrr((GEN)form1[5],(GEN)form2[5]);
! 1754: }
! 1755: else
! 1756: {
! 1757: for (i=1; i<=lgsub; i++)
! 1758: col[numfactorbase[subbase[i]]] = -fpd[i]-ex[i];
! 1759: for (j=1; j<=primfact[0]; j++)
! 1760: {
! 1761: p=primfact[j]; ep=exprimfact[j];
! 1762: if (smodis((GEN)form2[2], p<<1) > p) ep = -ep;
! 1763: col[numfactorbase[p]] += ep;
! 1764: }
! 1765: if (fpd[-2]) col[fpd[-2]]--;
! 1766: p1 = addii((GEN)form1[4],(GEN)form2[4]);
! 1767: p2 = mulrr((GEN)form1[5],(GEN)form2[5]);
! 1768: }
! 1769: primfact = oldfact; exprimfact = oldexp;
! 1770: }
! 1771: else
! 1772: {
! 1773: if (!form1) form1 = initializeform5(ex);
! 1774: if (!first)
! 1775: {
! 1776: p1 = primeform(Disc,stoi(factorbase[current]),PRECREG);
! 1777: p1 = redrealform_init(p1); form1=comprealform5(form1,p1);
! 1778: }
! 1779: av2=avma;
! 1780: for (i=1; i<=nbrho; i++)
! 1781: {
! 1782: form1 = rhorealform(form1);
! 1783: if (low_stack(limstack, stack_lim(av,1)))
! 1784: {
! 1785: if(DEBUGMEM>1) err(warnmem,"real_relations [4]");
! 1786: tetpil=avma; form1=gerepile(av2,tetpil,gcopy(form1));
! 1787: }
! 1788: }
! 1789: nbrho = 0;
! 1790:
! 1791: s++; col = mat[s]; if (DEBUGLEVEL) fprintferr(" %ld",s);
! 1792: for (i=1; i<=lgsub; i++)
! 1793: col[numfactorbase[subbase[i]]] = -ex[i];
! 1794: p1 = (GEN) form1[4];
! 1795: p2 = (GEN) form1[5];
! 1796: }
! 1797: for (j=1; j<=primfact[0]; j++)
! 1798: {
! 1799: p=primfact[j]; ep=exprimfact[j];
! 1800: if (smodis((GEN)form1[2], p<<1) > p) ep = -ep;
! 1801: col[numfactorbase[p]] += ep;
! 1802: }
! 1803: p1 = mpadd(mulir(mulsi(EXP220,p1), glog2), mplog(absr(p2)));
! 1804: affrr(shiftr(p1,-1), (GEN)vecexpo[s]);
! 1805: if (!first)
! 1806: {
! 1807: col[current]--;
! 1808: if (fpc == 1 && col[current] == 0)
! 1809: { s--; for (i=1; i<=KC; i++) col[i]=0; }
! 1810: break;
! 1811: }
! 1812: }
! 1813: avma = av;
! 1814: }
! 1815: if (DEBUGLEVEL)
! 1816: {
! 1817: fprintferr("\nnbrelations/nbtest = %ld/%ld\n",s,nbtest);
! 1818: msgtimer("%s relations", first? "initial": "random");
! 1819: }
! 1820: }
! 1821:
! 1822: static int
! 1823: real_be_honest(long *ex)
! 1824: {
! 1825: long p,fpc,s = KC,nbtest = 0,av = avma;
! 1826: GEN p1,form,form0;
! 1827:
! 1828: while (s<KC2)
! 1829: {
! 1830: p = factorbase[s+1];
! 1831: if (DEBUGLEVEL) { fprintferr(" %ld",p); flusherr(); }
! 1832: form = real_random_form(ex);
! 1833: p1 = redrealform(primeform(Disc,stoi(p),PRECREG));
! 1834: form = comprealform3(form,p1); form0=form;
! 1835: for(;;)
! 1836: {
! 1837: fpc = factorisequad(form,s,p-1);
! 1838: if (fpc == 1) { nbtest=0; s++; break; }
! 1839: form = rhorealform(form);
! 1840: nbtest++; if (nbtest>20) return 0;
! 1841: if (sens || !signe(addii((GEN)form[1],(GEN)form[3])))
! 1842: form = rhorealform(form);
! 1843: else
! 1844: {
! 1845: setsigne(form[1],1);
! 1846: setsigne(form[3],-1);
! 1847: }
! 1848: if (egalii((GEN)form[1],(GEN)form0[1])
! 1849: && egalii((GEN)form[2],(GEN)form0[2])) break;
! 1850: }
! 1851: avma=av;
! 1852: }
! 1853: return 1;
! 1854: }
! 1855:
! 1856: static GEN
! 1857: gcdrealnoer(GEN a,GEN b,long *pte)
! 1858: {
! 1859: long e;
! 1860: GEN k1,r;
! 1861:
! 1862: if (typ(a)==t_INT)
! 1863: {
! 1864: if (typ(b)==t_INT) return mppgcd(a,b);
! 1865: k1=cgetr(lg(b)); affir(a,k1); a=k1;
! 1866: }
! 1867: else if (typ(b)==t_INT)
! 1868: { k1=cgetr(lg(a)); affir(b,k1); b=k1; }
! 1869: if (expo(a)<-5) return absr(b);
! 1870: if (expo(b)<-5) return absr(a);
! 1871: a=absr(a); b=absr(b);
! 1872: while (expo(b) >= -5 && signe(b))
! 1873: {
! 1874: k1=gcvtoi(divrr(a,b),&e);
! 1875: if (e > 0) return NULL;
! 1876: r=subrr(a,mulir(k1,b)); a=b; b=r;
! 1877: }
! 1878: *pte=expo(b); return absr(a);
! 1879: }
! 1880:
! 1881: static GEN
! 1882: get_reg(GEN matc, long sreg)
! 1883: {
! 1884: long i,e,maxe;
! 1885: GEN reg = mpabs(gcoeff(matc,1,1));
! 1886:
! 1887: e = maxe = 0;
! 1888: for (i=2; i<=sreg; i++)
! 1889: {
! 1890: reg = gcdrealnoer(gcoeff(matc,1,i),reg,&e);
! 1891: if (!reg) return NULL;
! 1892: maxe = maxe? max(maxe,e): e;
! 1893: }
! 1894: if (DEBUGLEVEL)
! 1895: {
! 1896: if (DEBUGLEVEL>7) { fprintferr("reg = "); outerr(reg); }
! 1897: msgtimer("regulator");
! 1898: }
! 1899: return reg;
! 1900: }
! 1901:
! 1902: GEN
! 1903: buchquad(GEN D, double cbach, double cbach2, long RELSUP0, long flag, long prec)
! 1904: {
! 1905: long av0 = avma,av,tetpil,KCCO,KCCOPRO,i,j,s, *ex,**mat;
! 1906: long extrarel,nrelsup,nreldep,LIMC,LIMC2,cp,nbram,nlze;
! 1907: GEN p1,h,W,met,res,basecl,dr,c_1,pdep,C,B,extramat,extraC;
! 1908: GEN reg,vecexpo,glog2,cst;
! 1909: double drc,lim,LOGD;
! 1910:
! 1911: Disc = D; if (typ(Disc)!=t_INT) err(typeer,"buchquad");
! 1912: s=mod4(Disc);
! 1913: switch(signe(Disc))
! 1914: {
! 1915: case -1:
! 1916: if (cmpis(Disc,-4) >= 0)
! 1917: {
! 1918: p1=cgetg(6,t_VEC); p1[1]=p1[4]=p1[5]=un;
! 1919: p1[2]=p1[3]=lgetg(1,t_VEC); return p1;
! 1920: }
! 1921: if (s==2 || s==1) err(funder2,"buchquad");
! 1922: PRECREG=0; break;
! 1923:
! 1924: case 1:
! 1925: if (s==2 || s==3) err(funder2,"buchquad");
! 1926: if (flag)
! 1927: err(talker,"sorry, narrow class group not implemented. Use bnfnarrow");
! 1928: PRECREG=1; break;
! 1929:
! 1930: default: err(talker,"zero discriminant in quadclassunit");
! 1931: }
! 1932: if (carreparfait(Disc)) err(talker,"square argument in quadclassunit");
! 1933: if (!isfundamental(Disc))
! 1934: err(warner,"not a fundamental discriminant in quadclassunit");
! 1935: buch_init(); RELSUP = RELSUP0; sens = flag;
! 1936: dr=cgetr(3); affir(Disc,dr); drc=fabs(rtodbl(dr)); LOGD=log(drc);
! 1937: lim=sqrt(drc); cst = mulrr(lfunc(Disc), dbltor(lim));
! 1938: if (!PRECREG) lim /= sqrt(3.);
! 1939: cp = (long)exp(sqrt(LOGD*log(LOGD)/8.0));
! 1940: if (cp < 13) cp = 13;
! 1941: av = avma; cbach /= 2;
! 1942:
! 1943: INCREASE: avma = av; cbach = check_bach(cbach,6.);
! 1944: nreldep = nrelsup = 0;
! 1945: LIMC = (long)(cbach*LOGD*LOGD);
! 1946: if (LIMC < cp) LIMC=cp;
! 1947: LIMC2 = max(20, (long)(max(cbach,cbach2)*LOGD*LOGD));
! 1948: if (LIMC2 < LIMC) LIMC2 = LIMC;
! 1949: if (PRECREG)
! 1950: {
! 1951: PRECREG = max(prec+1, MEDDEFAULTPREC + 2*(expi(Disc)>>TWOPOTBITS_IN_LONG));
! 1952: glog2 = glog(gdeux,PRECREG);
! 1953: sqrtD = gsqrt(Disc,PRECREG);
! 1954: isqrtD = gfloor(sqrtD);
! 1955: }
! 1956: factorbasequad(Disc,LIMC2,LIMC);
! 1957: if (!KC) goto INCREASE;
! 1958:
! 1959: vperm = cgetg(KC+1,t_VECSMALL); for (i=1; i<=KC; i++) vperm[i]=i;
! 1960: nbram = subfactorbasequad(lim,KC);
! 1961: if (nbram == -1) { desalloc(NULL); goto INCREASE; }
! 1962: KCCO = KC + RELSUP;
! 1963: if (DEBUGLEVEL) { fprintferr("KC = %ld, KCCO = %ld\n",KC,KCCO); flusherr(); }
! 1964: powsubfact(lgsub,CBUCH+7);
! 1965:
! 1966: mat = (long**) gpmalloc((KCCO+1)*sizeof(long*));
! 1967: setlg(mat, KCCO+1);
! 1968: for (i=1; i<=KCCO; i++)
! 1969: {
! 1970: mat[i] = (long*) gpmalloc((KC+1)*sizeof(long));
! 1971: for (j=1; j<=KC; j++) mat[i][j]=0;
! 1972: }
! 1973: ex = new_chunk(lgsub+1);
! 1974: limhash = (LIMC<(MAXHALFULONG>>1))? LIMC*LIMC: HIGHBIT>>1;
! 1975: for (i=0; i<HASHT; i++) hashtab[i]=NULL;
! 1976:
! 1977: s = lgsub+nbram+RELSUP;
! 1978: if (PRECREG)
! 1979: {
! 1980: vecexpo=cgetg(KCCO+1,t_VEC);
! 1981: for (i=1; i<=KCCO; i++) vecexpo[i]=lgetr(PRECREG);
! 1982: real_relations(s,0,LIMC,ex,mat,glog2,vecexpo);
! 1983: real_relations(KCCO,s,LIMC,ex,mat,glog2,vecexpo);
! 1984: }
! 1985: else
! 1986: {
! 1987: imag_relations(s,0,LIMC,ex,mat);
! 1988: imag_relations(KCCO,s,LIMC,ex,mat);
! 1989: }
! 1990: if (KC2 > KC)
! 1991: {
! 1992: if (DEBUGLEVEL)
! 1993: fprintferr("be honest for primes from %ld to %ld\n",
! 1994: factorbase[KC+1],factorbase[KC2]);
! 1995: s = PRECREG? real_be_honest(ex): imag_be_honest(ex);
! 1996: if (DEBUGLEVEL)
! 1997: {
! 1998: fprintferr("\n");
! 1999: msgtimer("be honest");
! 2000: }
! 2001: if (!s) { desalloc(mat); goto INCREASE; }
! 2002: }
! 2003: C=cgetg(KCCO+1,t_MAT);
! 2004: if (PRECREG)
! 2005: {
! 2006: for (i=1; i<=KCCO; i++)
! 2007: {
! 2008: C[i]=lgetg(2,t_COL); coeff(C,1,i)=vecexpo[i];
! 2009: }
! 2010: if (DEBUGLEVEL>7) { fprintferr("C: "); outerr(C); flusherr(); }
! 2011: }
! 2012: else
! 2013: for (i=1; i<=KCCO; i++) C[i]=lgetg(1,t_COL);
! 2014: W = hnfspec(mat,vperm,&pdep,&B,&C,lgsub);
! 2015: nlze = lg(pdep)>1? lg(pdep[1])-1: lg(B[1])-1;
! 2016:
! 2017: KCCOPRO=KCCO;
! 2018: if (nlze)
! 2019: {
! 2020: EXTRAREL:
! 2021: s = PRECREG? 2: 1; extrarel=nlze+2;
! 2022: extraC=cgetg(extrarel+1,t_MAT);
! 2023: for (i=1; i<=extrarel; i++) extraC[i]=lgetg(s,t_COL);
! 2024: extramat = extra_relations(LIMC,ex,nlze,extraC);
! 2025: if (!extramat) { desalloc(mat); goto INCREASE; }
! 2026: W = hnfadd(W,vperm,&pdep,&B,&C, extramat,extraC);
! 2027: nlze = lg(pdep)>1? lg(pdep[1])-1: lg(B[1])-1;
! 2028: KCCOPRO += extrarel;
! 2029: if (nlze)
! 2030: {
! 2031: if (++nreldep > 5) { desalloc(mat); goto INCREASE; }
! 2032: goto EXTRAREL;
! 2033: }
! 2034: }
! 2035: /* tentative class number */
! 2036: h=gun; for (i=1; i<lg(W); i++) h=mulii(h,gcoeff(W,i,i));
! 2037: if (PRECREG)
! 2038: {
! 2039: /* tentative regulator */
! 2040: reg = get_reg(C, KCCOPRO - (lg(B)-1) - (lg(W)-1));
! 2041: if (!reg)
! 2042: {
! 2043: desalloc(mat);
! 2044: prec = (PRECREG<<1)-2; goto INCREASE;
! 2045: }
! 2046: if (gexpo(reg)<=-3)
! 2047: {
! 2048: if (++nrelsup <= 7)
! 2049: {
! 2050: if (DEBUGLEVEL) { fprintferr("regulateur nul\n"); flusherr(); }
! 2051: nlze=min(KC,nrelsup); goto EXTRAREL;
! 2052: }
! 2053: desalloc(mat); goto INCREASE;
! 2054: }
! 2055: c_1 = divrr(gmul2n(gmul(h,reg),1), cst);
! 2056: }
! 2057: else
! 2058: {
! 2059: reg = gun;
! 2060: c_1 = divrr(gmul(h,mppi(DEFAULTPREC)), cst);
! 2061: }
! 2062:
! 2063: if (gcmpgs(gmul2n(c_1,2),3)<0) { c_1=stoi(10); nrelsup=7; }
! 2064: if (gcmpgs(gmul2n(c_1,1),3)>0)
! 2065: {
! 2066: nrelsup++;
! 2067: if (nrelsup<=7)
! 2068: {
! 2069: if (DEBUGLEVEL)
! 2070: { fprintferr("***** check = %f\n\n",gtodouble(c_1)); flusherr(); }
! 2071: nlze=min(KC,nrelsup); goto EXTRAREL;
! 2072: }
! 2073: if (cbach < 5.99) { desalloc(mat); goto INCREASE; }
! 2074: err(warner,"suspicious check. Suggest increasing extra relations.");
! 2075: }
! 2076: basecl = get_clgp(Disc,W,&met,PRECREG);
! 2077: s = lg(basecl); desalloc(mat); tetpil=avma;
! 2078:
! 2079: res=cgetg(6,t_VEC);
! 2080: res[1]=lcopy(h); p1=cgetg(s,t_VEC);
! 2081: for (i=1; i<s; i++) p1[i] = (long)icopy(gcoeff(met,i,i));
! 2082: res[2]=(long)p1;
! 2083: res[3]=lcopy(basecl);
! 2084: res[4]=lcopy(reg);
! 2085: res[5]=lcopy(c_1); return gerepile(av0,tetpil,res);
! 2086: }
! 2087:
! 2088: GEN
! 2089: buchimag(GEN D, GEN c, GEN c2, GEN REL)
! 2090: {
! 2091: return buchquad(D,gtodouble(c),gtodouble(c2),itos(REL), 0,0);
! 2092: }
! 2093:
! 2094: GEN
! 2095: buchreal(GEN D, GEN sens0, GEN c, GEN c2, GEN REL, long prec)
! 2096: {
! 2097: return buchquad(D,gtodouble(c),gtodouble(c2),itos(REL), itos(sens0),prec);
! 2098: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>