Annotation of OpenXM_contrib/pari/src/modules/elliptic.c, Revision 1.1
1.1 ! maekawa 1: /********************************************************************/
! 2: /** **/
! 3: /** ELLIPTIC CURVES **/
! 4: /** **/
! 5: /********************************************************************/
! 6: /* $Id: elliptic.c,v 1.2 1999/09/23 17:50:57 karim Exp $ */
! 7: #include "pari.h"
! 8:
! 9: void
! 10: checkpt(GEN z)
! 11: {
! 12: if (typ(z)!=t_VEC) err(elliper1);
! 13: }
! 14:
! 15: long
! 16: checkell(GEN e)
! 17: {
! 18: long lx=lg(e);
! 19: if (typ(e)!=t_VEC || lx<14) err(elliper1);
! 20: return lx;
! 21: }
! 22:
! 23: void
! 24: checkbell(GEN e)
! 25: {
! 26: if (typ(e)!=t_VEC || lg(e)<20) err(elliper1);
! 27: }
! 28:
! 29: void
! 30: checksell(GEN e)
! 31: {
! 32: if (typ(e)!=t_VEC || lg(e)<6) err(elliper1);
! 33: }
! 34:
! 35: static void
! 36: checkch(GEN z)
! 37: {
! 38: if (typ(z)!=t_VEC || lg(z)!=5) err(elliper1);
! 39: }
! 40:
! 41: /* 4 X^3 + b2 X^2 + 2b4 X + b6 */
! 42: static GEN
! 43: RHSpol(GEN e)
! 44: {
! 45: GEN z = cgetg(6, t_POL); z[1] = evalsigne(1)|evallgef(6);
! 46: z[2] = e[8];
! 47: z[3] = lmul2n((GEN)e[7],1);
! 48: z[4] = e[6];
! 49: z[5] = lstoi(4); return z;
! 50: }
! 51:
! 52: /* x^3 + a2 x^2 + a4 x + a6 */
! 53: static GEN
! 54: ellRHS(GEN e, GEN x)
! 55: {
! 56: GEN p1;
! 57: p1 = gadd((GEN)e[2],x);
! 58: p1 = gadd((GEN)e[4], gmul(x,p1));
! 59: p1 = gadd((GEN)e[5], gmul(x,p1));
! 60: return p1;
! 61: }
! 62:
! 63: /* a1 x + a3 */
! 64: static GEN
! 65: ellLHS0(GEN e, GEN x)
! 66: {
! 67: return gcmp0((GEN)e[1])? (GEN)e[3]: gadd((GEN)e[3], gmul(x,(GEN)e[1]));
! 68: }
! 69:
! 70: static GEN
! 71: ellLHS0_i(GEN e, GEN x)
! 72: {
! 73: return signe(e[1])? addii((GEN)e[3], mulii(x, (GEN)e[1])): (GEN)e[3];
! 74: }
! 75:
! 76: /* y^2 + a1 xy + a3 y */
! 77: static GEN
! 78: ellLHS(GEN e, GEN z)
! 79: {
! 80: GEN y = (GEN)z[2];
! 81: return gmul(y, gadd(y, ellLHS0(e,(GEN)z[1])));
! 82: }
! 83:
! 84: /* 2y + a1 x + a3 */
! 85: static GEN
! 86: d_ellLHS(GEN e, GEN z)
! 87: {
! 88: return gadd(ellLHS0(e, (GEN)z[1]), gmul2n((GEN)z[2],1));
! 89: }
! 90:
! 91:
! 92: static void
! 93: smallinitell0(GEN x, GEN y)
! 94: {
! 95: GEN b2,b4,b6,b8,d,j,a11,a13,a33,a64,b81,b22,c4,c6;
! 96: long i;
! 97:
! 98: checksell(x); for (i=1; i<=5; i++) y[i]=x[i];
! 99:
! 100: b2=gadd(a11=gsqr((GEN)y[1]),gmul2n((GEN)y[2],2));
! 101: y[6]=(long)b2;
! 102:
! 103: b4=gadd(a13=gmul((GEN)y[1],(GEN)y[3]),gmul2n((GEN)y[4],1));
! 104: y[7]=(long)b4;
! 105:
! 106: b6=gadd(a33=gsqr((GEN)y[3]),a64=gmul2n((GEN)y[5],2));
! 107: y[8]=(long)b6;
! 108:
! 109: b81=gadd(gadd(gmul(a11,(GEN)y[5]),gmul(a64,(GEN)y[2])),gmul((GEN)y[2],a33));
! 110: b8=gsub(b81,gmul((GEN)y[4],gadd((GEN)y[4],a13)));
! 111: y[9]=(long)b8;
! 112:
! 113: c4=gadd(b22=gsqr(b2),gmulsg(-24,b4));
! 114: y[10]=(long)c4;
! 115:
! 116: c6=gadd(gmul(b2,gsub(gmulsg(36,b4),b22)),gmulsg(-216,b6));
! 117: y[11]=(long)c6;
! 118:
! 119: b81=gadd(gmul(b22,b8),gmulsg(27,gsqr(b6)));
! 120: d=gsub(gmul(b4,gadd(gmulsg(9,gmul(b2,b6)),gmulsg(-8,gsqr(b4)))),b81);
! 121: y[12]=(long)d;
! 122:
! 123: if (gcmp0(d)) err(talker,"singular curve in ellinit");
! 124:
! 125: j = gdiv(gmul(gsqr(c4),c4),d);
! 126: y[13]=(long)j;
! 127: }
! 128:
! 129: GEN
! 130: smallinitell(GEN x)
! 131: {
! 132: GEN y;
! 133: long av,tetpil;
! 134:
! 135: av=avma; y=cgetg(14,t_VEC);
! 136: smallinitell0(x,y); tetpil=avma;
! 137: return gerepile(av,tetpil,gcopy(y));
! 138: }
! 139:
! 140: GEN
! 141: ellinit0(GEN x, long flag,long prec)
! 142: {
! 143: switch(flag)
! 144: {
! 145: case 0: return initell(x,prec);
! 146: case 1: return smallinitell(x);
! 147: default: err(flagerr,"ellinit");
! 148: }
! 149: return NULL; /* not reached */
! 150: }
! 151:
! 152: void
! 153: ellprint(GEN e)
! 154: {
! 155: long av = avma;
! 156: long vx = fetch_var();
! 157: long vy = fetch_var();
! 158: GEN z = cgetg(3,t_VEC);
! 159: if (typ(e) != t_VEC || lg(e) < 6)
! 160: err(talker, "not an elliptic curve in ellprint");
! 161: z[1] = lpolx[vx]; name_var(vx, "X");
! 162: z[2] = lpolx[vy]; name_var(vy, "Y");
! 163: fprintferr("%Z = %Z\n", ellLHS(e, z), ellRHS(e, polx[vx]));
! 164: (void)delete_var();
! 165: (void)delete_var(); avma = av;
! 166: }
! 167:
! 168: static GEN
! 169: do_agm(GEN *ptx1, GEN a1, GEN b1, long prec, long sw)
! 170: {
! 171: GEN p1,r1,a,b,x,x1;
! 172: long G;
! 173:
! 174: x1 = gmul2n(gsub(a1,b1),-2);
! 175: if (gcmp0(x1))
! 176: err(talker,"precision too low in initell");
! 177: G = 6 - bit_accuracy(prec);
! 178: for(;;)
! 179: {
! 180: a=a1; b=b1; x=x1;
! 181: b1=gsqrt(gmul(a,b),prec); setsigne(b1,sw);
! 182: a1=gmul2n(gadd(gadd(a,b),gmul2n(b1,1)),-2);
! 183: r1=gsub(a1,b1);
! 184: p1=gsqrt(gdiv(gadd(x,r1),x),prec);
! 185: x1=gmul(x,gsqr(gmul2n(gaddsg(1,p1),-1)));
! 186: if (gexpo(r1) <= G + gexpo(b1)) break;
! 187: }
! 188: if (gprecision(x1)*2 <= (prec+2))
! 189: err(talker,"precision too low in initell");
! 190: *ptx1 = x1; return ginv(gmul2n(a1,2));
! 191: }
! 192:
! 193: static GEN
! 194: do_padic_agm(GEN *ptx1, GEN a1, GEN b1, GEN p)
! 195: {
! 196: GEN p1,r1,a,b,x,bmod1, bmod = modii((GEN)b1[4],p), x1 = *ptx1;
! 197:
! 198: if (!x1) x1 = gmul2n(gsub(a1,b1),-2);
! 199: for(;;)
! 200: {
! 201: a=a1; b=b1; x=x1;
! 202: b1=gsqrt(gmul(a,b),0); bmod1=modii((GEN)b1[4],p);
! 203: if (!egalii(bmod1,bmod)) b1 = gneg_i(b1);
! 204: a1=gmul2n(gadd(gadd(a,b),gmul2n(b1,1)),-2);
! 205: r1=gsub(a1,b1);
! 206: p1=gsqrt(gdiv(gadd(x,r1),x),0);
! 207: if (! gcmp1(modii((GEN)p1[4],p))) p1 = gneg_i(p1);
! 208: x1=gmul(x,gsqr(gmul2n(gaddsg(1,p1),-1)));
! 209: if (gcmp0(r1)) break;
! 210: }
! 211: *ptx1 = x1; return ginv(gmul2n(a1,2));
! 212: }
! 213:
! 214: static GEN
! 215: padic_initell(GEN y, GEN p, long prec)
! 216: {
! 217: GEN b2,b4,c4,c6,p1,p2,w,pv,a1,b1,x1,u2,q,e0,e1;
! 218: long i,alpha;
! 219:
! 220: if (valp(y[13]) >= 0) /* p | j */
! 221: err(talker,"valuation of j must be negative in p-adic ellinit");
! 222: if (egalii(p,gdeux))
! 223: err(impl,"initell for 2-adic numbers"); /* pv=stoi(4); */
! 224:
! 225: pv=p; q=ggrandocp(p,prec);
! 226: for (i=1; i<=5; i++) y[i]=ladd(q,(GEN)y[i]);
! 227: b2= (GEN)y[6];
! 228: b4= (GEN)y[7];
! 229: c4= (GEN)y[10];
! 230: c6= (GEN)y[11];
! 231: alpha=valp(c4)>>1;
! 232: setvalp(c4,0);
! 233: setvalp(c6,0); e1=gdivgs(gdiv(c6,c4),6);
! 234: c4=gdivgs(c4,48); c6=gdivgs(c6,864);
! 235: do
! 236: {
! 237: e0=e1; p2=gsqr(e0);
! 238: e1=gdiv(gadd(gmul2n(gmul(e0,p2),1),c6), gsub(gmulsg(3,p2),c4));
! 239: }
! 240: while (!gegal(e0,e1));
! 241: setvalp(e1,valp(e1)+alpha);
! 242:
! 243: e1=gsub(e1,gdivgs(b2,12));
! 244: w=gsqrt(gmul2n(gadd(b4,gmul(e1,gadd(b2,gmulsg(6,e1)))),1),0);
! 245:
! 246: p1=gaddgs(gdiv(gmulsg(3,e0),w),1);
! 247: if (valp(p1)<=0) w=gneg_i(w);
! 248: y[18]=(long)w;
! 249:
! 250: a1=gmul2n(gsub(w,gadd(gmulsg(3,e1),gmul2n(b2,-2))),-2);
! 251: b1=gmul2n(w,-1); x1=NULL;
! 252: u2 = do_padic_agm(&x1,a1,b1,pv);
! 253:
! 254: w=gaddsg(1,ginv(gmul2n(gmul(u2,x1),1)));
! 255: q=ginv(gadd(w,gsqrt(gaddgs(gsqr(w),-1),0)));
! 256: if (valp(q)<0) q=ginv(q);
! 257:
! 258: p1=cgetg(2,t_VEC); p1[1]=(long)e1;
! 259: y[14]=(long)p1;
! 260: y[15]=(long)u2;
! 261: y[16] = (kronecker((GEN)u2[4],p) <= 0 || (valp(u2)&1))? zero: lsqrt(u2,0);
! 262: y[17]=(long)q;
! 263: y[19]=zero; return y;
! 264: }
! 265:
! 266: static int
! 267: invcmp(GEN x, GEN y) { return -gcmp(x,y); }
! 268:
! 269: static GEN
! 270: initell0(GEN x, long prec)
! 271: {
! 272: GEN y,b2,b4,D,p1,p2,p,u,w,a1,b1,x1,u2,q,e1,pi,pi2,tau,w2;
! 273: long ty,i,e,sw;
! 274:
! 275: y=cgetg(20,t_VEC);
! 276: smallinitell0(x,y);
! 277:
! 278: e = BIGINT; p = NULL;
! 279: for (i=1; i<=5; i++)
! 280: {
! 281: q = (GEN)y[i];
! 282: if (typ(q)==t_PADIC)
! 283: {
! 284: long e2 = signe(q[4])? precp(q)+valp(q): valp(q);
! 285: if (e2 < e) e = e2;
! 286: if (!p) p = (GEN)q[2];
! 287: else if (!egalii(p,(GEN)q[2]))
! 288: err(talker,"incompatible p-adic numbers in initell");
! 289: }
! 290: }
! 291: if (e<BIGINT) return padic_initell(y,p,e);
! 292:
! 293: b2= (GEN)y[6];
! 294: b4= (GEN)y[7];
! 295: D = (GEN)y[12]; ty = typ(D);
! 296: if (!prec || !is_const_t(ty) || ty==t_INTMOD)
! 297: { y[14]=y[15]=y[16]=y[17]=y[18]=y[19]=zero; return y; }
! 298:
! 299: pi=mppi(prec); pi2=gmul2n(pi,1);
! 300: p1 = roots(RHSpol(y),prec);
! 301: if (gsigne(D) < 0) p1[1] = lreal((GEN)p1[1]);
! 302: else /* sort roots in decreasing order */
! 303: p1 = gen_sort(greal(p1), 0, invcmp);
! 304: y[14]=(long)p1;
! 305:
! 306: e1=(GEN)p1[1];
! 307: w = gsqrt(gmul2n(gadd(b4,gmul(e1,gadd(b2,gmulsg(6,e1)))),1),prec);
! 308: p2=gadd(gmulsg(3,e1), gmul2n(b2,-2));
! 309: if (gsigne(p2)>0) w = gneg_i(w);
! 310: a1=gmul2n(gsub(w,p2),-2);
! 311: b1=gmul2n(w,-1); sw=signe(w);
! 312: u2 = do_agm(&x1,a1,b1,prec,sw);
! 313:
! 314: w = gaddsg(1,ginv(gmul2n(gmul(u2,x1),1)));
! 315: q = gsqrt(gaddgs(gsqr(w),-1),prec);
! 316: if (gsigne(greal(w))>0)
! 317: q = ginv(gadd(w,q));
! 318: else
! 319: q = gsub(w,q);
! 320: if (gexpo(q)>=0) q=ginv(q);
! 321: tau=gmul(gdiv(glog(q,prec),pi2), gneg_i(gi));
! 322:
! 323: y[19]=lmul(gmul(gsqr(pi2),gabs(u2,prec)),gimag(tau));
! 324: u=gmul(pi2,gsqrt(gneg_i(u2),prec)); w2=gmul(tau,u);
! 325: if (sw<0)
! 326: {
! 327: y[15]=(long)u;
! 328: q=gsqrt(q,prec);
! 329: }
! 330: else
! 331: {
! 332: y[15]=lmul2n(gabs((GEN)w2[1],prec),1);
! 333: q=gexp(gmul2n(gmul(gmul(pi2,gi),gdiv(w2,(GEN)y[15])), -1), prec);
! 334: }
! 335: y[16]=(long)w2;
! 336: p1 = gdiv(gsqr(pi),gmulsg(6,(GEN)y[15]));
! 337: p2 = thetanullk(q,1,prec);
! 338: if (gcmp0(p2)) err(talker,"precision too low in initell");
! 339: y[17]=lmul(p1,gdiv(thetanullk(q,3,prec),p2));
! 340: y[18]=ldiv(gsub(gmul((GEN)y[17],(GEN)y[16]),gmul(gi,pi)),(GEN)y[15]);
! 341: return y;
! 342: }
! 343:
! 344: GEN
! 345: initell(GEN x, long prec)
! 346: {
! 347: long av=avma;
! 348: return gerepileupto(av, gcopy(initell0(x,prec)));
! 349: }
! 350:
! 351: GEN
! 352: coordch(GEN e, GEN ch)
! 353: {
! 354: GEN y,p1,p2,v,v2,v3,v4,v6,r,s,t,u;
! 355: long av,tetpil,i,lx = checkell(e);
! 356:
! 357: checkch(ch);
! 358: u=(GEN)ch[1]; r=(GEN)ch[2]; s=(GEN)ch[3]; t=(GEN)ch[4];
! 359: av=avma; y=cgetg(lx,t_VEC);
! 360: v=ginv(u); v2=gsqr(v); v3=gmul(v,v2);v4=gsqr(v2); v6=gsqr(v3);
! 361: y[1] = lmul(v,gadd((GEN)e[1],gmul2n(s,1)));
! 362: y[2] = lmul(v2,gsub(gadd((GEN)e[2],gmulsg(3,r)),gmul(s,gadd((GEN)e[1],s))));
! 363: p2 = ellLHS0(e,r);
! 364: p1 = gadd(gmul2n(t,1), p2);
! 365: y[3] = lmul(v3,p1);
! 366: p1 = gsub((GEN)e[4],gadd(gmul(t,(GEN)e[1]),gmul(s,p1)));
! 367: y[4] = lmul(v4,gadd(p1,gmul(r,gadd(gmul2n((GEN)e[2],1),gmulsg(3,r)))));
! 368: p2 = gmul(t,gadd(t, p2));
! 369: y[5] = lmul(v6,gsub(ellRHS(e,r),p2));
! 370: y[6] = lmul(v2,gadd((GEN)e[6],gmulsg(12,r)));
! 371: y[7] = lmul(v4,gadd((GEN)e[7],gmul(r,gadd((GEN)e[6],gmulsg(6,r)))));
! 372: y[8] = lmul(v6,gadd((GEN)e[8],gmul(r,gadd(gmul2n((GEN)e[7],1),gmul(r,gadd((GEN)e[6],gmul2n(r,2)))))));
! 373: p1 = gadd(gmulsg(3,(GEN)e[7]),gmul(r,gadd((GEN)e[6],gmulsg(3,r))));
! 374: y[9] = lmul(gsqr(v4),gadd((GEN)e[9],gmul(r,gadd(gmulsg(3,(GEN)e[8]),gmul(r,p1)))));
! 375: y[10] = lmul(v4,(GEN)e[10]);
! 376: y[11] = lmul(v6,(GEN)e[11]);
! 377: y[12] = lmul(gsqr(v6),(GEN)e[12]);
! 378: y[13] = e[13];
! 379: if (lx>14)
! 380: {
! 381: p1=(GEN)e[14];
! 382: if (gcmp0(p1))
! 383: {
! 384: y[14] = y[15] = y[16] = y[17] = y[18] = y[19] = zero;
! 385: }
! 386: else
! 387: {
! 388: if (typ(e[1])==t_PADIC)
! 389: {
! 390: p2=cgetg(2,t_VEC); p2[1]=lmul(v2,gsub((GEN)p1[1],r));
! 391: y[14]=(long)p2;
! 392: y[15]=lmul(gsqr(u),(GEN)e[15]);
! 393: y[16]=lmul(u,(GEN)e[16]);
! 394: /* FIXME: how do q and w change ??? */
! 395: y[17]=e[17];
! 396: y[18]=e[18];
! 397: y[19]=zero;
! 398: }
! 399: else
! 400: {
! 401: p2=cgetg(4,t_COL);
! 402: for (i=1; i<=3; i++) p2[i]=lmul(v2,gsub((GEN)p1[i],r));
! 403: y[14]=(long)p2;
! 404: y[15]=lmul(u,(GEN)e[15]);
! 405: y[16]=lmul(u,(GEN)e[16]);
! 406: y[17]=ldiv((GEN)e[17],u);
! 407: y[18]=ldiv((GEN)e[18],u);
! 408: y[19]=lmul(gsqr(u),(GEN)e[19]);
! 409: }
! 410: }
! 411: }
! 412: tetpil=avma; return gerepile(av,tetpil,gcopy(y));
! 413: }
! 414:
! 415: static GEN
! 416: pointch0(GEN x, GEN v2, GEN v3, GEN mor, GEN s, GEN t)
! 417: {
! 418: GEN p1,z;
! 419:
! 420: if (lg(x) < 3) return x;
! 421:
! 422: z = cgetg(3,t_VEC); p1=gadd((GEN)x[1],mor);
! 423: z[1] = lmul(v2,p1);
! 424: z[2] = lmul(v3,gsub((GEN)x[2],gadd(gmul(s,p1),t)));
! 425: return z;
! 426: }
! 427:
! 428: GEN
! 429: pointch(GEN x, GEN ch)
! 430: {
! 431: GEN y,v,v2,v3,mor,r,s,t,u;
! 432: long av,tetpil,tx,lx=lg(x),i;
! 433:
! 434: checkpt(x); checkch(ch);
! 435: if (lx < 2) return gcopy(x);
! 436: av=avma; u=(GEN)ch[1]; r=(GEN)ch[2]; s=(GEN)ch[3]; t=(GEN)ch[4];
! 437: tx=typ(x[1]); v=ginv(u); v2=gsqr(v); v3=gmul(v,v2); mor=gneg_i(r);
! 438: if (is_matvec_t(tx))
! 439: {
! 440: y=cgetg(lx,tx);
! 441: for (i=1; i<lx; i++)
! 442: y[i]=(long) pointch0((GEN)x[i],v2,v3,mor,s,t);
! 443: }
! 444: else
! 445: y = pointch0(x,v2,v3,mor,s,t);
! 446: tetpil=avma; return gerepile(av,tetpil,gcopy(y));
! 447: }
! 448:
! 449: static long
! 450: ellexpo(GEN e)
! 451: {
! 452: long i,k2, k = gexpo((GEN)e[1]);
! 453: for (i=2; i<6; i++)
! 454: {
! 455: k2 = gexpo((GEN)e[i]);
! 456: if (k<k2) k = k2;
! 457: }
! 458: return k;
! 459: }
! 460:
! 461: /* Exactness of lhs and rhs in the following depends in non-obvious ways
! 462: on the coeffs of the curve as well as on the components of the point z.
! 463: Thus if e is exact, with a1==0, and z has exact y coordinate only, the
! 464: lhs will be exact but the rhs won't. */
! 465: int
! 466: oncurve(GEN e, GEN z)
! 467: {
! 468: GEN p1,p2,x;
! 469: long av=avma,p,q;
! 470:
! 471: checksell(e); checkpt(z); if (lg(z)<3) return 1; /* oo */
! 472: p1 = ellLHS(e,z);
! 473: p2 = ellRHS(e,(GEN)z[1]); x = gsub(p1,p2);
! 474: if (gcmp0(x)) { avma=av; return 1; }
! 475: p = precision(p1);
! 476: q = precision(p2);
! 477: if (!p && !q) { avma=av; return 0; } /* both of p1, p2 are exact */
! 478: if (!q || (p && p < q)) q = p; /* min among nonzero elts of {p,q} */
! 479: /* the constant 0.93 is arbitrary */
! 480: q = (gexpo(x)-ellexpo(e) < - bit_accuracy(q) * 0.93);
! 481: avma = av; return q;
! 482: }
! 483:
! 484: GEN
! 485: addell(GEN e, GEN z1, GEN z2)
! 486: {
! 487: GEN p1,p2,x,y,x1,x2,y1,y2;
! 488: long av=avma,tetpil;
! 489:
! 490: checksell(e); checkpt(z1); checkpt(z2);
! 491: if (lg(z1)<3) return gcopy(z2);
! 492: if (lg(z2)<3) return gcopy(z1);
! 493:
! 494: x1=(GEN)z1[1]; y1=(GEN)z1[2];
! 495: x2=(GEN)z2[1]; y2=(GEN)z2[2];
! 496: if (x1 == x2 || gegal(x1,x2))
! 497: { /* y1 = y2 or -LHS0-y2 */
! 498: if (y1 != y2)
! 499: {
! 500: int eq;
! 501: if (precision(y1) || precision(y2))
! 502: eq = (gexpo(gadd(ellLHS0(e,x1),gadd(y1,y2))) >= gexpo(y1));
! 503: else
! 504: eq = gegal(y1,y2);
! 505: if (!eq) { avma=av; y=cgetg(2,t_VEC); y[1]=zero; return y; }
! 506: }
! 507: p2 = d_ellLHS(e,z1);
! 508: if (gcmp0(p2)) { avma=av; y=cgetg(2,t_VEC); y[1]=zero; return y; }
! 509: p1 = gadd(gsub((GEN)e[4],gmul((GEN)e[1],y1)),
! 510: gmul(x1,gadd(gmul2n((GEN)e[2],1),gmulsg(3,x1))));
! 511: }
! 512: else { p1=gsub(y2,y1); p2=gsub(x2,x1); }
! 513: p1 = gdiv(p1,p2);
! 514: x = gsub(gmul(p1,gadd(p1,(GEN)e[1])), gadd(gadd(x1,x2),(GEN)e[2]));
! 515: y = gadd(gadd(y1, ellLHS0(e,x)), gmul(p1,gsub(x,x1)));
! 516: tetpil=avma; p1=cgetg(3,t_VEC); p1[1]=lcopy(x); p1[2]=lneg(y);
! 517: return gerepile(av,tetpil,p1);
! 518: }
! 519:
! 520: static GEN
! 521: invell(GEN e, GEN z)
! 522: {
! 523: GEN p1;
! 524:
! 525: if (lg(z)<3) return z;
! 526: p1=cgetg(3,t_VEC); p1[1]=z[1];
! 527: p1[2]=(long)gneg_i(gadd((GEN)z[2], ellLHS0(e,(GEN)z[1])));
! 528: return p1;
! 529: }
! 530:
! 531: GEN
! 532: subell(GEN e, GEN z1, GEN z2)
! 533: {
! 534: long av=avma,tetpil;
! 535:
! 536: checksell(e); checkpt(z2);
! 537: z2=invell(e,z2); tetpil=avma;
! 538: return gerepile(av,tetpil,addell(e,z1,z2));
! 539: }
! 540:
! 541: GEN
! 542: ordell(GEN e, GEN x, long prec)
! 543: {
! 544: long av=avma,td,i,lx,tx=typ(x);
! 545: GEN D,a,b,d,pd,p1,y;
! 546:
! 547: checksell(e);
! 548: if (is_matvec_t(tx))
! 549: {
! 550: lx=lg(x); y=cgetg(lx,tx);
! 551: for (i=1; i<lx; i++) y[i]=(long)ordell(e,(GEN)x[i],prec);
! 552: return y;
! 553: }
! 554:
! 555: a=ellRHS(e,x);
! 556: b=ellLHS0(e,x); /* y*(y+b) = a */
! 557: D=gadd(gsqr(b),gmul2n(a,2)); td=typ(D);
! 558: if (gcmp0(D))
! 559: {
! 560: b = gneg_i(b);
! 561: y = cgetg(2,t_VEC);
! 562: if (td == t_INTMOD && egalii((GEN)D[1], gdeux))
! 563: y[1] = (long)gmodulss(gcmp0(a)?0:1, 2);
! 564: else
! 565: y[1] = lmul2n(b,-1);
! 566: return gerepileupto(av,y);
! 567: }
! 568:
! 569: if (td==t_INT || is_frac_t(td))
! 570: {
! 571: pd = (td==t_INT)? NULL: (GEN)D[2];
! 572: if (pd) D = mulii((GEN)D[1],pd);
! 573: if (!carrecomplet(D,&d)) { avma=av; return cgetg(1,t_VEC); }
! 574: if (pd) d = gdiv(d,pd);
! 575: }
! 576: else
! 577: {
! 578: if (td==t_INTMOD)
! 579: {
! 580: if (egalii((GEN)D[1],gdeux))
! 581: {
! 582: avma=av;
! 583: if (!gcmp0(a)) return cgetg(1,t_VEC);
! 584: y = cgetg(3,t_VEC);
! 585: y[1] = (long)gmodulss(0,2);
! 586: y[2] = (long)gmodulss(1,2); return y;
! 587: }
! 588: if (kronecker((GEN)D[2],(GEN)D[1]) == -1)
! 589: { avma=av; return cgetg(1,t_VEC); }
! 590: }
! 591: d = gsqrt(D,prec);
! 592: }
! 593: p1=gsub(d,b); y = cgetg(3,t_VEC);
! 594: y[1] = lmul2n(p1,-1);
! 595: y[2] = lsub((GEN)y[1],d);
! 596: return gerepileupto(av,y);
! 597: }
! 598:
! 599: static GEN
! 600: CM_powell(GEN e, GEN z, GEN n)
! 601: {
! 602: GEN x,y,p0,p1,q0,q1,p2,q2,z1,z2,pol,grdx;
! 603: long av=avma,tetpil,ln,ep,vn;
! 604:
! 605: if (lg(z)<3) return gcopy(z);
! 606: pol=(GEN)n[1];
! 607: if (signe(discsr(pol))>=0)
! 608: err(talker,"not a negative quadratic discriminant in CM");
! 609: if (!gcmp1(denom((GEN)n[2])) || !gcmp1(denom((GEN)n[3])))
! 610: err(impl,"powell for nonintegral CM exponent");
! 611:
! 612: p1=gaddgs(gmul2n(gnorm(n),2),4);
! 613: if (gcmpgs(p1,(((ulong)MAXULONG)>>1)) > 0)
! 614: err(talker,"norm too large in CM");
! 615: ln=itos(p1); vn=(ln-4)>>2;
! 616: z1 = weipell(e,ln);
! 617: z2 = gsubst(z1,0,gmul(n,polx[0]));
! 618: grdx=gadd((GEN)z[1],gdivgs((GEN)e[6],12));
! 619: p0=gzero; p1=gun;
! 620: q0=gun; q1=gzero;
! 621: do
! 622: {
! 623: GEN ss=gzero;
! 624: do
! 625: {
! 626: ep=(-valp(z2))>>1; ss=gadd(ss,gmul((GEN)z2[2],gpuigs(polx[0],ep)));
! 627: z2=gsub(z2,gmul((GEN)z2[2],gpuigs(z1,ep)));
! 628: }
! 629: while (valp(z2)<=0);
! 630: p2=gadd(p0,gmul(ss,p1)); p0=p1; p1=p2;
! 631: q2=gadd(q0,gmul(ss,q1)); q0=q1; q1=q2;
! 632: if (!signe(z2)) break;
! 633: z2=ginv(z2);
! 634: }
! 635: while (lgef(p1)-3 < vn);
! 636: if (lgef(p1)-3 > vn || signe(z2))
! 637: err(talker,"not a complex multiplication in powell");
! 638: x=gdiv(p1,q1); y=gdiv(deriv(x,0),n);
! 639: x=gsub(poleval(x,grdx), gdivgs((GEN)e[6],12));
! 640: y=gsub(gmul(d_ellLHS(e,z),poleval(y,grdx)), ellLHS0(e,x));
! 641: tetpil=avma; z=cgetg(3,t_VEC); z[1]=lcopy(x); z[2]=lmul2n(y,-1);
! 642: return gerepile(av,tetpil,z);
! 643: }
! 644:
! 645: GEN
! 646: powell(GEN e, GEN z, GEN n)
! 647: {
! 648: GEN y;
! 649: long av=avma,i,j,tetpil,s;
! 650: ulong m;
! 651:
! 652: checksell(e); checkpt(z);
! 653: if (typ(n)==t_QUAD) return CM_powell(e,z,n);
! 654: if (typ(n)!=t_INT)
! 655: err(impl,"powell for nonintegral or non CM exponents");
! 656: if (lg(z)<3) return gcopy(z);
! 657: s=signe(n);
! 658: if (!s) { y=cgetg(2,t_VEC); y[1]=zero; return y; }
! 659: if (s < 0) { n=negi(n); z = invell(e,z); }
! 660: if (is_pm1(n)) { tetpil=avma; return gerepile(av,tetpil,gcopy(z)); }
! 661:
! 662: y=cgetg(2,t_VEC); y[1]=zero;
! 663: for (i=lgefint(n)-1; i>2; i--)
! 664: for (m=n[i],j=0; j<BITS_IN_LONG; j++,m>>=1)
! 665: {
! 666: if (m&1) y = addell(e,y,z);
! 667: z = addell(e,z,z);
! 668: }
! 669: for (m=n[2]; m>1; m>>=1)
! 670: {
! 671: if (m&1) y = addell(e,y,z);
! 672: z = addell(e,z,z);
! 673: }
! 674: tetpil=avma; return gerepile(av,tetpil,addell(e,y,z));
! 675: }
! 676:
! 677: GEN
! 678: mathell(GEN e, GEN x, long prec)
! 679: {
! 680: GEN y,p1,p2, *pdiag;
! 681: long av=avma,tetpil,lx=lg(x),i,j,tx=typ(x);
! 682:
! 683: if (!is_vec_t(tx)) err(elliper1);
! 684: lx=lg(x); y=cgetg(lx,t_MAT); pdiag=(GEN*) new_chunk(lx);
! 685: for (i=1; i<lx; i++)
! 686: {
! 687: pdiag[i]=ghell(e,(GEN)x[i],prec);
! 688: y[i]=lgetg(lx,t_COL);
! 689: }
! 690: for (i=1; i<lx; i++)
! 691: {
! 692: p1=(GEN)y[i]; p1[i]=lmul2n(pdiag[i],1);
! 693: for (j=i+1; j<lx; j++)
! 694: {
! 695: p2=ghell(e,addell(e,(GEN)x[i],(GEN)x[j]),prec);
! 696: p2=gsub(p2, gadd(pdiag[i],pdiag[j]));
! 697: p1[j]=(long)p2; coeff(y,i,j)=(long)p2;
! 698: }
! 699: }
! 700: tetpil=avma; return gerepile(av,tetpil,gcopy(y));
! 701: }
! 702:
! 703: static GEN
! 704: bilhells(GEN e, GEN z1, GEN z2, GEN h2, long prec)
! 705: {
! 706: long lz1=lg(z1),tx,av=avma,tetpil,i;
! 707: GEN y,p1,p2;
! 708:
! 709: if (lz1==1) return cgetg(1,typ(z1));
! 710:
! 711: tx=typ(z1[1]);
! 712: if (!is_matvec_t(tx))
! 713: {
! 714: p1 = ghell(e,addell(e,z1,z2),prec);
! 715: p2 = gadd(ghell(e,z1,prec),h2);
! 716: tetpil=avma; return gerepile(av,tetpil,gsub(p1,p2));
! 717: }
! 718: y=cgetg(lz1,typ(z1));
! 719: for (i=1; i<lz1; i++)
! 720: y[i]=(long)bilhells(e,(GEN)z1[i],z2,h2,prec);
! 721: return y;
! 722: }
! 723:
! 724: GEN
! 725: bilhell(GEN e, GEN z1, GEN z2, long prec)
! 726: {
! 727: GEN p1,h2;
! 728: long av=avma,tetpil,tz1=typ(z1),tz2=typ(z2);
! 729:
! 730: if (!is_matvec_t(tz1) || !is_matvec_t(tz2)) err(elliper1);
! 731: if (lg(z1)==1) return cgetg(1,tz1);
! 732: if (lg(z2)==1) return cgetg(1,tz2);
! 733:
! 734: tz1=typ(z1[1]); tz2=typ(z2[1]);
! 735: if (is_matvec_t(tz2))
! 736: {
! 737: if (is_matvec_t(tz1))
! 738: err(talker,"two vector/matrix types in bilhell");
! 739: p1=z1; z1=z2; z2=p1;
! 740: }
! 741: h2=ghell(e,z2,prec); tetpil=avma;
! 742: return gerepile(av,tetpil,bilhells(e,z1,z2,h2,prec));
! 743: }
! 744:
! 745: static GEN
! 746: new_coords(GEN e, GEN x, GEN *pta, GEN *ptb, long prec)
! 747: {
! 748: GEN a,b,r0,r1,p1,p2,w, e1 = gmael(e,14,1), b2 = (GEN)e[6];
! 749: long ty = typ(e[12]);
! 750:
! 751: r0 = gmul2n(b2,-2);
! 752: p2 = gadd(gmulsg(3,e1),r0);
! 753: if (ty == t_PADIC)
! 754: w = (GEN)e[18];
! 755: else
! 756: {
! 757: GEN b4 = (GEN)e[7];
! 758: if (!is_const_t(ty)) err(typeer,"zell");
! 759:
! 760: w = gsqrt(gmul2n(gadd(b4, gmul(e1,gadd(b2,gmulsg(6,e1)))),1),prec);
! 761: if (gsigne(greal(p2)) > 0) w = gneg_i(w);
! 762: }
! 763: a = gmul2n(gsub(w,p2),-2);
! 764: b = gmul2n(w,-1);
! 765: r1 = gsub(a,b);
! 766: p1 = gadd(x, gmul2n(gadd(e1,r0),-1));
! 767: if (gcmp0(p1)) p1=gsqrt(gneg_i(gmul(a,r1)),prec);
! 768: else
! 769: {
! 770: GEN delta=gdiv(gmul(a,r1),gsqr(p1));
! 771: p1=gmul2n(gmul(p1,gaddsg(1,gsqrt(gsubsg(1,gmul2n(delta,2)),prec))),-1);
! 772: }
! 773: *pta = a; *ptb = b;
! 774: return gmul(p1,gsqr(gmul2n(gaddsg(1,gsqrt(gdiv(gadd(p1,r1),p1),prec)),-1)));
! 775: }
! 776:
! 777: GEN
! 778: zell(GEN e, GEN z, long prec)
! 779: {
! 780: long av=avma,ty,sw,fl;
! 781: GEN t,u,p1,p2,r1,a,b,x1,u2,D = (GEN)e[12];
! 782:
! 783: checkbell(e);
! 784: if (!oncurve(e,z)) err(heller1);
! 785: ty=typ(D);
! 786: if (ty==t_INTMOD) err(typeer,"zell");
! 787: if (lg(z)<3) return (ty==t_PADIC)? gun: gzero;
! 788:
! 789: x1 = new_coords(e,(GEN)z[1],&a,&b,prec);
! 790: if (ty==t_PADIC)
! 791: {
! 792: u2 = do_padic_agm(&x1,a,b,(GEN)D[2]);
! 793: if (!gcmp0((GEN)e[16]))
! 794: {
! 795: t=gsqrt(gaddsg(1,gdiv(x1,a)),prec);
! 796: t=gdiv(gaddsg(-1,t),gaddsg(1,t));
! 797: }
! 798: else t=gaddsg(2,ginv(gmul(u2,x1)));
! 799: return gerepileupto(av,t);
! 800: }
! 801:
! 802: sw=gsigne(greal(b)); fl=0;
! 803: for(;;) /* agm */
! 804: {
! 805: GEN a0=a, b0=b, x0=x1;
! 806:
! 807: b=gsqrt(gmul(a0,b0),prec);
! 808: if (gsigne(greal(b)) != sw) b = gneg_i(b);
! 809: a=gmul2n(gadd(gadd(a0,b0),gmul2n(b,1)),-2);
! 810: r1=gsub(a,b);
! 811: p1=gsqrt(gdiv(gadd(x0,r1),x0),prec);
! 812: x1=gmul(x0,gsqr(gmul2n(gaddsg(1,p1),-1)));
! 813: if (gexpo(gsub(x1,x0)) < gexpo(x1) - bit_accuracy(prec) + 5)
! 814: {
! 815: if (fl) break;
! 816: fl = 1;
! 817: }
! 818: else fl = 0;
! 819: }
! 820: u=gdiv(x1,a); t=gaddsg(1,u);
! 821: if (gexpo(t) < 5 - bit_accuracy(prec))
! 822: t = negi(gun);
! 823: else
! 824: t = gdiv(u,gsqr(gaddsg(1,gsqrt(t,prec))));
! 825: u=gsqrt(ginv(gmul2n(a,2)),prec);
! 826: t=glog(t,prec); t=gmul(t,u);
! 827:
! 828: /* which square root? test the reciprocal function (pointell) */
! 829: if (!gcmp0(t))
! 830: {
! 831: GEN x1;
! 832: long bad;
! 833:
! 834: u = pointell(e,t,3); /* we don't need much precision */
! 835: /* Either z = u (ok: keep t), or z = invell(e,u) (bad: t <-- -t) */
! 836: x1 = gsub(z,u); bad = (gexpo((GEN)x1[1]) >= gexpo((GEN)u[1])
! 837: || gexpo((GEN)x1[2]) >= gexpo((GEN)u[2]));
! 838: if (bad) t = gneg(t);
! 839: if (DEBUGLEVEL)
! 840: {
! 841: if (DEBUGLEVEL>4)
! 842: {
! 843: fprintferr(" z = %Z\n",z);
! 844: fprintferr(" u = %Z\n",u);
! 845: fprintferr(" x1 = %Z\n",x1);
! 846: }
! 847: fprintferr("ellpointtoz: %s square root\n", bad? "bad": "good");
! 848: flusherr();
! 849: }
! 850: }
! 851: /* send t to the fundamental domain if necessary */
! 852: p2 = gdiv(gimag(t),gmael(e,16,2));
! 853: p1 = gsub(p2, gmul2n(gun,-2));
! 854: if (gcmp(gabs(p1,prec),ghalf) >= 0)
! 855: t = gsub(t, gmul((GEN)e[16],gfloor(gadd(p2,dbltor(0.1)))));
! 856: if (gsigne(greal(t)) < 0) t = gadd(t,(GEN)e[15]);
! 857: return gerepileupto(av,t);
! 858: }
! 859:
! 860: /* compute gamma in SL_2(Z) and t'=gamma(t) so that t' is in the usual
! 861: fundamental domain. Internal function no check, no garbage. */
! 862: static GEN
! 863: getgamma(GEN t)
! 864: {
! 865: GEN a,b,c,d,n,m,y,p1,unapprox;
! 866:
! 867: unapprox=gsub(gun,gpuigs(stoi(10),-8));
! 868: a=d=gun;b=c=gzero;
! 869: for(;;)
! 870: {
! 871: n=ground(greal(t));
! 872: if (signe(n))
! 873: {
! 874: n=negi(n); t=gadd(t,n);
! 875: a=addii(a,mulii(n,c));
! 876: b=addii(b,mulii(n,d));
! 877: }
! 878: m=gnorm(t); if (gcmp(m,unapprox)>=0) break;
! 879: t=gneg_i(gdiv(gconj(t),m));
! 880: p1=negi(c); c=a; a=p1;
! 881: p1=negi(d); d=b; b=p1;
! 882: }
! 883: y=cgetg(3,t_VEC);
! 884: m=cgetg(3,t_MAT); y[1]=(long)m;
! 885: p1=cgetg(3,t_COL); m[1]=(long)p1;
! 886: p1[1]=(long)a; p1[2]=(long)c;
! 887: p1=cgetg(3,t_COL); m[2]=(long)p1;
! 888: p1[1]=(long)b; p1[2]=(long)d;
! 889: y[2]=(long)t;
! 890: return y;
! 891: }
! 892:
! 893: static int
! 894: get_periods(GEN e, GEN *om1, GEN *om2)
! 895: {
! 896: long tx = typ(e);
! 897: if (is_vec_t(tx))
! 898: switch(lg(e))
! 899: {
! 900: case 3: *om1=(GEN)e[1]; *om2=(GEN)e[2]; return 1;
! 901: case 20: *om1=(GEN)e[16]; *om2=(GEN)e[15]; return 1;
! 902: }
! 903: return 0;
! 904: }
! 905:
! 906: /* computes the numerical values of eisenstein series. k is equal to a positive
! 907: even integer. If k=4 or 6, computes g2 or g3. If k=2, or k>6 even,
! 908: compute (2iPi/om2)^k*(1+2/zeta(1-k)*sum(n>=1,n^(k-1)q^n/(1-q^n)) with no
! 909: constant factor. */
! 910: GEN
! 911: elleisnum(GEN om, long k, long flag, long prec)
! 912: {
! 913: long av=avma,lim,av1,fl,si;
! 914: GEN om1,om2,p1,pii2,tau,q,y,qn,v,ga,court,asub;
! 915:
! 916: if (k%2 || k<=0) err(talker,"k not a positive even integer in elleisnum");
! 917: if (!get_periods(om, &om1, &om2)) err(typeer,"elleisnum");
! 918: p1=mppi(prec); setexpo(p1,2);
! 919: pii2=cgetg(3,t_COMPLEX); pii2[1]=zero; pii2[2]=(long)p1;
! 920: tau=gdiv(om1,om2); si=gsigne(gimag(tau));
! 921: if (si==0)
! 922: err(talker,"omega1 and omega2 are R-linearly dependent in elleisnum");
! 923: if (si<0) { p1=om1; om1=om2; om2=p1; tau=ginv(tau); }
! 924: v=getgamma(tau); tau=(GEN)v[2]; ga=(GEN)v[1];
! 925: if (k==2) asub=gdiv(gmul(pii2,gmulsg(12,gcoeff(ga,2,1))),om2);
! 926: om2=gadd(gmul(gcoeff(ga,2,1),om1),gmul(gcoeff(ga,2,2),om2));
! 927: if (k==2) asub=gdiv(asub,om2);
! 928: q=gexp(gmul(pii2,tau),prec);
! 929: y=gzero; court=stoi(3);
! 930: av1=avma; lim=stack_lim(av1,1); qn=gun; court[2]=0;
! 931: do
! 932: {
! 933: court[2]++; qn=gmul(q,qn);
! 934: p1=gdiv(gmul(gpuigs(court,k-1),qn),gsub(gun,qn));
! 935: y=gadd(y,p1);
! 936: fl=(gexpo(p1) > - bit_accuracy(prec) - 5);
! 937: if (low_stack(lim, stack_lim(av1,1)))
! 938: {
! 939: GEN *gptr[2]; gptr[0]=&y; gptr[1]=&qn;
! 940: if(DEBUGMEM>1) err(warnmem,"elleisnum");
! 941: gerepilemany(av1,gptr,2);
! 942: }
! 943: }
! 944: while (fl);
! 945:
! 946: y=gadd(gun,gmul(gdiv(gdeux,gzeta(stoi(1-k),prec)),y));
! 947: p1=gpuigs(gdiv(pii2,om2),k);
! 948: y = gmul(p1,y);
! 949: if (k==2) y=gsub(y,asub);
! 950: else if (k==4 && flag) y=gdivgs(y,12);
! 951: else if (k==6 && flag) y=gdivgs(y,216);
! 952: return gerepileupto(av,y);
! 953: }
! 954:
! 955: /* compute eta1, eta2 */
! 956:
! 957: GEN
! 958: elleta(GEN om, long prec)
! 959: {
! 960: long av=avma,tetpil;
! 961: GEN e2,p1,pii2,y1,y2,y;
! 962:
! 963: e2=gdivgs(elleisnum(om,2,0,prec),12);
! 964: p1=mppi(prec); setexpo(p1,2);
! 965: pii2=cgetg(3,t_COMPLEX); pii2[1]=zero; pii2[2]=(long)p1;
! 966: y2=gmul((GEN)om[2],e2);
! 967: y1=gadd(gdiv(pii2,(GEN)om[2]),gmul((GEN)om[1],e2));
! 968: tetpil=avma;
! 969: y=cgetg(3,t_VEC); y[1]=lneg(y1); y[2]=lneg(y2);
! 970: return gerepile(av,tetpil,y);
! 971: }
! 972:
! 973: /* computes the numerical value of wp(z | om1 Z + om2 Z),
! 974: If flall=1, compute also wp'. Reduce to the fundamental domain first. */
! 975: static GEN
! 976: weipellnumall(GEN om1, GEN om2, GEN z, long flall, long prec)
! 977: {
! 978: long av=avma,tetpil,lim,av1,si,toadd;
! 979: GEN p1,pii2,pii4,a,tau,q,u,y,yp,u1,u2,qn,v,ga;
! 980:
! 981: p1=mppi(prec); setexpo(p1,2);
! 982: pii2=cgetg(3,t_COMPLEX); pii2[1]=zero; pii2[2]=(long)p1;
! 983: tau=gdiv(om1,om2); si=gsigne(gimag(tau));
! 984: if (si==0)
! 985: err(talker,"omega1 and omega2 are R-linearly dependent in ellwpnum");
! 986: if (si<0) { p1=om1; om1=om2; om2=p1; tau=ginv(tau); }
! 987: v=getgamma(tau); tau=(GEN)v[2]; ga=(GEN)v[1];
! 988: om2=gadd(gmul(gcoeff(ga,2,1),om1),gmul(gcoeff(ga,2,2),om2));
! 989: z=gdiv(z,om2);
! 990: a=ground(gdiv(gimag(z),gimag(tau))); z=gsub(z,gmul(a,tau));
! 991: a=ground(greal(z)); z=gsub(z,a);
! 992: if (gexpo(z) < 5 - bit_accuracy(prec))
! 993: {
! 994: avma=av; v=cgetg(2,t_VEC); v[1]=zero; return v;
! 995: }
! 996:
! 997: q=gexp(gmul(pii2,tau),prec);
! 998: u=gexp(gmul(pii2,z),prec);
! 999: u1=gsub(gun,u); u2=gsqr(u1);
! 1000: y=gadd(gdivgs(gun,12),gdiv(u,u2));
! 1001: if (flall) yp=gdiv(gadd(gun,u),gmul(u1,u2));
! 1002: toadd=(long)ceil(9.065*gtodouble(gimag(z)));
! 1003:
! 1004: av1=avma; lim=stack_lim(av1,1); qn=q;
! 1005: do
! 1006: {
! 1007: GEN p2,qnu,qnu1,qnu2,qnu3,qnu4;
! 1008:
! 1009: qnu=gmul(qn,u); qnu1=gsub(gun,qnu); qnu2=gsqr(qnu1);
! 1010: qnu3=gsub(qn,u); qnu4=gsqr(qnu3);
! 1011: p1=gsub(gmul(u,gadd(ginv(qnu2),ginv(qnu4))),
! 1012: gmul2n(ginv(gsqr(gsub(gun,qn))),1));
! 1013: p1=gmul(qn,p1);
! 1014: y=gadd(y,p1);
! 1015: if (flall)
! 1016: {
! 1017: p2=gadd(gdiv(gadd(gun,qnu),gmul(qnu1,qnu2)),
! 1018: gdiv(gadd(qn,u),gmul(qnu3,qnu4)));
! 1019: p2=gmul(qn,p2);
! 1020: yp=gadd(yp,p2);
! 1021: }
! 1022: qn=gmul(q,qn);
! 1023: if (low_stack(lim, stack_lim(av1,1)))
! 1024: {
! 1025: GEN *gptr[3]; gptr[0]=&y; gptr[1]=&qn; gptr[2]=&yp;
! 1026: if(DEBUGMEM>1) err(warnmem,"weipellnum");
! 1027: gerepilemany(av1,gptr,flall?3:2);
! 1028: }
! 1029: }
! 1030: while (gexpo(qn) > - bit_accuracy(prec) - 5 - toadd);
! 1031:
! 1032: pii2=gdiv(pii2,om2);
! 1033: pii4=gsqr(pii2);
! 1034: y = gmul(pii4,y);
! 1035: if (flall) yp=gmul(u,gmul(gmul(pii4,pii2),yp));
! 1036: tetpil=avma;
! 1037: if (flall) { v=cgetg(3,t_VEC); v[1]=lcopy(y); v[2]=lmul2n(yp,-1); }
! 1038: else v=gcopy(y);
! 1039: return gerepile(av,tetpil,v);
! 1040: }
! 1041:
! 1042: GEN
! 1043: ellzeta(GEN om, GEN z, long prec)
! 1044: {
! 1045: long av=avma,tetpil,lim,av1,si,toadd;
! 1046: GEN zinit,om1,om2,p1,pii2,tau,q,u,y,u1,qn,v,ga,x1,x2,et;
! 1047:
! 1048: if (!get_periods(om, &om1, &om2)) err(typeer,"ellzeta");
! 1049: p1=mppi(prec); setexpo(p1,2);
! 1050: pii2=cgetg(3,t_COMPLEX); pii2[1]=zero; pii2[2]=(long)p1;
! 1051: tau=gdiv(om1,om2); si=gsigne(gimag(tau));
! 1052: if (si==0)
! 1053: err(talker,"omega1 and omega2 are R-linearly dependent in ellzeta");
! 1054: if (si<0) { p1=om1; om1=om2; om2=p1; tau=ginv(tau); }
! 1055: v=getgamma(tau); tau=(GEN)v[2]; ga=(GEN)v[1];
! 1056: om2=gadd(gmul(gcoeff(ga,2,1),om1),gmul(gcoeff(ga,2,2),om2));
! 1057: om1=gmul(tau,om2); om=cgetg(3,t_VEC); om[1]=(long)om1; om[2]=(long)om2;
! 1058: z=gdiv(z,om2);
! 1059:
! 1060: x1=ground(gdiv(gimag(z),gimag(tau))); z=gsub(z,gmul(x1,tau));
! 1061: x2=ground(greal(z)); z=gsub(z,x2); zinit=gmul(z,om2);
! 1062: et=elleta(om,prec);
! 1063: et=gadd(gmul(x1,(GEN)et[1]),gmul(x2,(GEN)et[2]));
! 1064: if (gexpo(z) < 5 - bit_accuracy(prec))
! 1065: {
! 1066: p1=ginv(zinit); tetpil=avma; return gerepile(av,tetpil,gadd(p1,et));
! 1067: }
! 1068: q=gexp(gmul(pii2,tau),prec);
! 1069: u=gexp(gmul(pii2,z),prec);
! 1070: u1=gsub(u,gun);
! 1071: y=gdiv(gmul(gsqr(om2),elleisnum(om,2,0,prec)),pii2);
! 1072: y=gadd(ghalf,gdivgs(gmul(z,y),-12));
! 1073: y=gadd(y,ginv(u1));
! 1074: toadd=(long)ceil(9.065*gtodouble(gimag(z)));
! 1075: av1=avma; lim=stack_lim(av1,1); qn=q;
! 1076: do
! 1077: {
! 1078: p1=gadd(gdiv(u,gsub(gmul(qn,u),gun)),ginv(gsub(u,qn)));
! 1079: p1=gmul(qn,p1);
! 1080: y=gadd(y,p1);
! 1081: qn=gmul(q,qn);
! 1082: if (low_stack(lim, stack_lim(av1,1)))
! 1083: {
! 1084: GEN *gptr[2]; gptr[0]=&y; gptr[1]=&qn;
! 1085: if(DEBUGMEM>1) err(warnmem,"ellzeta");
! 1086: gerepilemany(av1,gptr,2);
! 1087: }
! 1088: }
! 1089: while (gexpo(qn) > - bit_accuracy(prec) - 5 - toadd);
! 1090:
! 1091: y=gmul(gdiv(pii2,om2),y);
! 1092: tetpil=avma;
! 1093: return gerepile(av,tetpil,gadd(y,et));
! 1094: }
! 1095:
! 1096: /* if flag=0, return ellsigma, otherwise return log(ellsigma) */
! 1097:
! 1098: static GEN
! 1099: ellsigmasum(GEN om, GEN z, long flag, long prec)
! 1100: {
! 1101: long av=avma,tetpil,lim,av1,si,toadd,n;
! 1102: GEN zinit,om1,om2,p1,pii2,tau,q,u,y,y1,qn,qn2,urn,urninv,v,ga;
! 1103: GEN uinv,x1,x2,et,etnew,uhalf,q8;
! 1104:
! 1105: if (!get_periods(om, &om1, &om2)) err(typeer,"ellsigmasum");
! 1106: p1=mppi(prec); setexpo(p1,2);
! 1107: pii2=cgetg(3,t_COMPLEX); pii2[1]=zero; pii2[2]=(long)p1;
! 1108: tau=gdiv(om1,om2); si=gsigne(gimag(tau));
! 1109: if (si==0)
! 1110: err(talker,"omega1 and omega2 are R-linearly dependent in ellsigma");
! 1111: if (si<0) { p1=om1; om1=om2; om2=p1; tau=ginv(tau); }
! 1112: v=getgamma(tau); tau=(GEN)v[2]; ga=(GEN)v[1];
! 1113: om2=gadd(gmul(gcoeff(ga,2,1),om1),gmul(gcoeff(ga,2,2),om2));
! 1114: om1=gmul(tau,om2); om=cgetg(3,t_VEC); om[1]=(long)om1; om[2]=(long)om2;
! 1115: z=gdiv(z,om2);
! 1116:
! 1117: x1=ground(gdiv(gimag(z),gimag(tau))); z=gsub(z,gmul(x1,tau));
! 1118: x2=ground(greal(z)); z=gsub(z,x2); zinit=gmul(z,om2);
! 1119: et=elleta(om,prec);
! 1120: etnew=gadd(gmul(x1,(GEN)et[1]),gmul(x2,(GEN)et[2]));
! 1121: etnew=gmul(etnew,gadd(gmul2n(gadd(gmul(x1,om1),gmul(x2,om2)),-1),zinit));
! 1122: if (mpodd(x1) || mpodd(x2)) etnew=gadd(etnew,gmul2n(pii2,-1));
! 1123: if (gexpo(z) < 5 - bit_accuracy(prec))
! 1124: {
! 1125: if (flag)
! 1126: {
! 1127: y=glog(zinit,prec);
! 1128: tetpil=avma;
! 1129: return gerepile(av,tetpil,gadd(etnew,y));
! 1130: }
! 1131: else
! 1132: {
! 1133: et=gexp(et,prec);
! 1134: tetpil=avma;
! 1135: return gerepile(av,tetpil,gmul(etnew,zinit));
! 1136: }
! 1137: }
! 1138:
! 1139: y1=gadd(etnew,gmul2n(gmul(gmul(z,zinit),(GEN)et[2]),-1));
! 1140:
! 1141: q8=gexp(gmul2n(gmul(pii2,tau),-3),prec);
! 1142: q=gpuigs(q8,8);
! 1143: uhalf=gexp(gmul(gmul2n(pii2,-1),z),prec);
! 1144: u=gneg_i(gsqr(uhalf)); uinv=ginv(u);
! 1145: y=gzero;
! 1146: toadd=(long)ceil(9.065*gtodouble(gabs(gimag(z),prec)));
! 1147: /* 9.065 = 2*Pi/log(2) */
! 1148: av1=avma; lim=stack_lim(av1,1); qn=q; qn2=gun;
! 1149: urn=uhalf; urninv=ginv(uhalf); n=0;
! 1150: do
! 1151: {
! 1152: y=gadd(y,gmul(qn2,gsub(urn,urninv)));
! 1153: qn2=gmul(qn,qn2);
! 1154: qn=gmul(q,qn);
! 1155: urn=gmul(urn,u); urninv=gmul(urninv,uinv);
! 1156: n++;
! 1157: if (low_stack(lim, stack_lim(av1,1)))
! 1158: {
! 1159: GEN *gptr[5]; gptr[0]=&y; gptr[1]=&qn; gptr[2]=&qn2; gptr[3]=&urn;
! 1160: gptr[4]=&urninv;
! 1161: if(DEBUGMEM>1) err(warnmem,"ellsigma");
! 1162: gerepilemany(av1,gptr,5);
! 1163: }
! 1164: }
! 1165: while (gexpo(qn2) + (n-1)*toadd > - bit_accuracy(prec) - 5);
! 1166:
! 1167: p1=gmul(q8,gmul(gdiv(gdiv((GEN)om[2],pii2),gpuigs(trueeta(tau,prec),3)),y));
! 1168: if (flag)
! 1169: {
! 1170: p1=glog(p1,prec); tetpil=avma;
! 1171: return gerepile(av,tetpil,gadd(y1,p1));
! 1172: }
! 1173: else
! 1174: {
! 1175: y=gexp(y1,prec); tetpil=avma;
! 1176: return gerepile(av,tetpil,gmul(p1,y));
! 1177: }
! 1178: }
! 1179:
! 1180: /* if flag=0, return ellsigma, otherwise return log(ellsigma) */
! 1181:
! 1182: static GEN
! 1183: ellsigmaprod(GEN om, GEN z, long flag, long prec)
! 1184: {
! 1185: long av=avma,tetpil,lim,av1,si,toadd;
! 1186: GEN zinit,om1,om2,p1,pii2,tau,q,u,y,y1,u1,qn,v,ga,negu,uinv,x1,x2,et,etnew,uhalf;
! 1187:
! 1188: if (!get_periods(om, &om1, &om2)) err(typeer,"ellsigmaprod");
! 1189: p1=mppi(prec); setexpo(p1,2);
! 1190: pii2=cgetg(3,t_COMPLEX); pii2[1]=zero; pii2[2]=(long)p1;
! 1191: tau=gdiv(om1,om2); si=gsigne(gimag(tau));
! 1192: if (si==0)
! 1193: err(talker,"omega1 and omega2 are R-linearly dependent in ellsigma");
! 1194: if (si<0) { p1=om1; om1=om2; om2=p1; tau=ginv(tau); }
! 1195: v=getgamma(tau); tau=(GEN)v[2]; ga=(GEN)v[1];
! 1196: om2=gadd(gmul(gcoeff(ga,2,1),om1),gmul(gcoeff(ga,2,2),om2));
! 1197: om1=gmul(tau,om2); om=cgetg(3,t_VEC); om[1]=(long)om1; om[2]=(long)om2;
! 1198: z=gdiv(z,om2);
! 1199:
! 1200: x1=ground(gdiv(gimag(z),gimag(tau))); z=gsub(z,gmul(x1,tau));
! 1201: x2=ground(greal(z)); z=gsub(z,x2); zinit=gmul(z,om2);
! 1202: et=elleta(om,prec);
! 1203: etnew=gadd(gmul(x1,(GEN)et[1]),gmul(x2,(GEN)et[2]));
! 1204: etnew=gmul(etnew,gadd(gmul2n(gadd(gmul(x1,om1),gmul(x2,om2)),-1),zinit));
! 1205: if (mpodd(x1) || mpodd(x2)) etnew=gadd(etnew,gmul2n(pii2,-1));
! 1206: if (gexpo(z) < 5 - bit_accuracy(prec))
! 1207: {
! 1208: if (flag)
! 1209: {
! 1210: y=glog(zinit,prec);
! 1211: tetpil=avma;
! 1212: return gerepile(av,tetpil,gadd(etnew,y));
! 1213: }
! 1214: else
! 1215: {
! 1216: et=gexp(et,prec);
! 1217: tetpil=avma;
! 1218: return gerepile(av,tetpil,gmul(etnew,zinit));
! 1219: }
! 1220: }
! 1221:
! 1222: y1=gadd(etnew,gmul2n(gmul(gmul(z,zinit),(GEN)et[2]),-1));
! 1223:
! 1224: q=gexp(gmul(pii2,tau),prec);
! 1225: uhalf=gexp(gmul(gmul2n(pii2,-1),z),prec); u=gsqr(uhalf);
! 1226: uinv=ginv(u);
! 1227: u1=gsub(uhalf,ginv(uhalf));
! 1228: y=gdiv(gmul(om2,u1),pii2);
! 1229: toadd=(long)ceil(9.065*gtodouble(gabs(gimag(z),prec)));
! 1230: /* 9.065 = 2*Pi/log(2) */
! 1231: av1=avma; lim=stack_lim(av1,1); qn=q;
! 1232: negu=stoi(-1);
! 1233: do
! 1234: {
! 1235: p1=gmul(gadd(gmul(qn,u),negu),gadd(gmul(qn,uinv),negu));
! 1236: p1=gdiv(p1,gsqr(gadd(qn,negu)));
! 1237: y=gmul(y,p1);
! 1238: qn=gmul(q,qn);
! 1239: if (low_stack(lim, stack_lim(av1,1)))
! 1240: {
! 1241: GEN *gptr[2]; gptr[0]=&y; gptr[1]=&qn;
! 1242: if(DEBUGMEM>1) err(warnmem,"ellsigma");
! 1243: gerepilemany(av1,gptr,2);
! 1244: }
! 1245: }
! 1246: while (gexpo(qn) > - bit_accuracy(prec) - 5 - toadd);
! 1247:
! 1248: if (flag)
! 1249: {
! 1250: p1=glog(y,prec);
! 1251: tetpil=avma;
! 1252: return gerepile(av,tetpil,gadd(y1,p1));
! 1253: }
! 1254: else
! 1255: {
! 1256: p1=gexp(y1,prec);
! 1257: tetpil=avma;
! 1258: return gerepile(av,tetpil,gmul(p1,y));
! 1259: }
! 1260: }
! 1261:
! 1262: GEN
! 1263: ellsigma(GEN om, GEN z, long flag, long prec)
! 1264: {
! 1265: if (flag>=2) return ellsigmaprod(om,z,flag&1,prec);
! 1266: else return ellsigmasum(om,z,flag,prec);
! 1267: }
! 1268:
! 1269: GEN
! 1270: pointell(GEN e, GEN z, long prec)
! 1271: {
! 1272: long av=avma,tetpil;
! 1273: GEN y,yp,v,p1;
! 1274:
! 1275: checkbell(e);
! 1276: p1=weipellnumall((GEN)e[16],(GEN)e[15],z,1,prec);
! 1277: if (lg(p1)==2) { avma=av; v=cgetg(2,t_VEC); v[1]=zero; return v; }
! 1278: y = gsub((GEN)p1[1], gdivgs((GEN)e[6],12));
! 1279: yp = gsub((GEN)p1[2], gmul2n(ellLHS0(e,y),-1));
! 1280: tetpil=avma; v=cgetg(3,t_VEC); v[1]=lcopy(y); v[2]=lcopy(yp);
! 1281: return gerepile(av,tetpil,v);
! 1282: }
! 1283:
! 1284: GEN
! 1285: weipell(GEN e, long prec)
! 1286: {
! 1287: long av1,tetpil,precres,i,k,l;
! 1288: GEN res,p1,s,t;
! 1289:
! 1290: checkell(e); precres = 2*prec+2;
! 1291: res=cgetg(precres,t_SER);
! 1292: res[1] = evalsigne(1) | evalvalp(-2) | evalvarn(0);
! 1293: if (!prec) { setsigne(res,0); return res; }
! 1294: for (i=3; i<precres; i+=2) res[i]=zero;
! 1295: switch(prec)
! 1296: {
! 1297: default: res[8]=ldivgs((GEN)e[11],6048);
! 1298: case 3: res[6]=ldivgs((GEN)e[10],240);
! 1299: case 2: res[4]=zero;
! 1300: case 1: res[2]=un;
! 1301: case 0: break;
! 1302: }
! 1303: for (k=4; k<prec; k++)
! 1304: {
! 1305: av1 = avma;
! 1306: s = k&1? gzero: gsqr((GEN)res[k+2]);
! 1307: t = gzero;
! 1308: for (l=2; l+l<k; l++)
! 1309: t = gadd(t, gmul((GEN)res[(l+1)<<1],(GEN)res[(k-l+1)<<1]));
! 1310: p1=gmulsg(3,gadd(s,gmul2n(t,1)));
! 1311: tetpil=avma;
! 1312: p1=gdivgs(p1,(k-3)*(2*k+1));
! 1313: res[(k+1)<<1] = lpile(av1,tetpil,p1);
! 1314: }
! 1315: return res;
! 1316: }
! 1317:
! 1318: GEN
! 1319: ellwp0(GEN om, GEN z, long flag, long prec, long PREC)
! 1320: {
! 1321: GEN v,om1,om2;
! 1322: long av = avma;
! 1323:
! 1324: if (z==NULL) return weipell(om,PREC);
! 1325: if (typ(z)==t_POL)
! 1326: {
! 1327: if (lgef(z) != 4 || !gcmp0((GEN)z[2]) || !gcmp1((GEN)z[3]))
! 1328: err(talker,"expecting a simple variable in ellwp");
! 1329: v = weipell(om,PREC); setvarn(v, varn(z));
! 1330: return v;
! 1331: }
! 1332: if (!get_periods(om, &om1, &om2)) err(typeer,"ellwp");
! 1333: switch(flag)
! 1334: {
! 1335: case 0: v=weipellnumall(om1,om2,z,0,prec);
! 1336: if (typ(v)==t_VEC && lg(v)==2) { avma=av; v=gpuigs(z,-2); }
! 1337: return v;
! 1338: case 1: v=weipellnumall(om1,om2,z,1,prec);
! 1339: if (typ(v)==t_VEC && lg(v)==2)
! 1340: {
! 1341: GEN p1 = gmul2n(gpuigs(z,3),1);
! 1342: long tetpil=avma;
! 1343: v=cgetg(3,t_VEC);
! 1344: v[1]=lpuigs(z,-2);
! 1345: v[2]=lneg(p1); return gerepile(av,tetpil,v);
! 1346: }
! 1347: return v;
! 1348: case 2: return pointell(om,z,prec);
! 1349: default: err(flagerr,"ellwp"); return NULL;
! 1350: }
! 1351: }
! 1352:
! 1353: /* compute a_2 using Jacobi sum */
! 1354: static GEN
! 1355: _a_2(GEN e)
! 1356: {
! 1357: long av = avma;
! 1358: GEN unmodp = gmodulss(1,8);
! 1359: ulong e6 = itos((GEN)gmul(unmodp,(GEN)e[6])[2]);
! 1360: ulong e8 = itos((GEN)gmul(unmodp,(GEN)e[8])[2]);
! 1361: ulong e72= itos((GEN)gmul(unmodp,gmul2n((GEN)e[7],1))[2]);
! 1362: long s = kross(e8, 2) + kross(e8 + e72 + e6 + 4, 2);
! 1363: avma = av; return stoi(-s);
! 1364: }
! 1365:
! 1366: /* a_p using Jacobi sums */
! 1367: static GEN
! 1368: apell2_intern(GEN e, ulong p)
! 1369: {
! 1370: if (p == 2) return _a_2(e);
! 1371: else
! 1372: {
! 1373: long av=avma,i;
! 1374: GEN unmodp = gmodulss(1,p);
! 1375: ulong e6 = itos((GEN)gmul(unmodp,(GEN)e[6])[2]);
! 1376: ulong e8 = itos((GEN)gmul(unmodp,(GEN)e[8])[2]);
! 1377: ulong e72= itos((GEN)gmul(unmodp,(GEN)e[7])[2]) << 1;
! 1378: long s = kross(e8, p);
! 1379:
! 1380: if (p < 757)
! 1381: for (i=1; i<p; i++)
! 1382: s += kross(e8 + i*(e72 + i*(e6 + (i<<2))), p);
! 1383: else
! 1384: for (i=1; i<p; i++)
! 1385: s += kross(e8 + mulssmod(i, e72 + mulssmod(i, e6 + (i<<2), p), p), p);
! 1386: avma=av; return stoi(-s);
! 1387: }
! 1388: }
! 1389:
! 1390: GEN
! 1391: apell2(GEN e, GEN pp)
! 1392: {
! 1393: checkell(e); if (typ(pp)!=t_INT) err(elliper1);
! 1394: if (expi(pp) > 29)
! 1395: err(talker,"prime too large in jacobi apell2, use apell instead");
! 1396:
! 1397: return apell2_intern(e, (ulong)pp[2]);
! 1398: }
! 1399:
! 1400: GEN ellap0(GEN e, GEN p, long flag)
! 1401: {
! 1402: return flag? apell2(e,p): apell(e,p);
! 1403: }
! 1404:
! 1405: /* invert all elements of x mod p using Montgomery's trick */
! 1406: GEN
! 1407: multi_invmod(GEN x, GEN p)
! 1408: {
! 1409: long i, lx = lg(x);
! 1410: GEN u,y = cgetg(lx, t_VEC);
! 1411:
! 1412: y[1] = x[1];
! 1413: for (i=2; i<lx; i++)
! 1414: y[i] = lresii(mulii((GEN)y[i-1], (GEN)x[i]), p);
! 1415:
! 1416: u = mpinvmod((GEN)y[--i], p);
! 1417: for ( ; i > 1; i--)
! 1418: {
! 1419: y[i] = lresii(mulii(u, (GEN)y[i-1]), p);
! 1420: u = resii(mulii(u, (GEN)x[i]), p); /* u = 1 / (x[1] ... x[i-1]) */
! 1421: }
! 1422: y[1] = (long)u; return y;
! 1423: }
! 1424:
! 1425: static GEN
! 1426: addsell(GEN e, GEN z1, GEN z2, GEN p)
! 1427: {
! 1428: GEN p1,p2,x,x1,x2,y,y1,y2;
! 1429: long av = avma;
! 1430:
! 1431: if (!z1) return z2;
! 1432: if (!z2) return z1;
! 1433:
! 1434: x1 = (GEN)z1[1]; y1 = (GEN)z1[2];
! 1435: x2 = (GEN)z2[1]; y2 = (GEN)z2[2];
! 1436: p2 = subii(x2, x1);
! 1437: if (p2 == gzero)
! 1438: {
! 1439: if (!signe(y1) || !egalii(y1,y2)) return NULL;
! 1440: p2 = shifti(y1,1);
! 1441: p1 = addii(e, mulii(x1,mulsi(3,x1)));
! 1442: p1 = resii(p1, p);
! 1443: }
! 1444: else p1 = subii(y2,y1);
! 1445: p1 = mulii(p1, mpinvmod(p2, p));
! 1446: p1 = resii(p1, p);
! 1447: x = subii(sqri(p1), addii(x1,x2)); x = modii(x,p);
! 1448: y = negi(addii(y1, mulii(p1,subii(x,x1))));
! 1449: avma = av; p1 = cgetg(3,t_VEC);
! 1450: p1[1] = licopy(x);
! 1451: p1[2] = lmodii(y, p); return p1;
! 1452: }
! 1453:
! 1454: /* z1 <-- z1 + z2 */
! 1455: static void
! 1456: addsell_part2(GEN e, GEN z1, GEN z2, GEN p, GEN p2inv)
! 1457: {
! 1458: GEN p1,x,x1,x2,y,y1,y2;
! 1459:
! 1460: x1 = (GEN)z1[1]; y1 = (GEN)z1[2];
! 1461: x2 = (GEN)z2[1]; y2 = (GEN)z2[2];
! 1462: if (x1 == x2)
! 1463: {
! 1464: p1 = addii(e, mulii(x1,mulsi(3,x1)));
! 1465: p1 = resii(p1, p);
! 1466: }
! 1467: else p1 = subii(y2,y1);
! 1468:
! 1469: p1 = mulii(p1, p2inv);
! 1470: p1 = resii(p1, p);
! 1471: x = subii(sqri(p1), addii(x1,x2)); x = modii(x,p);
! 1472: y = negi(addii(y1, mulii(p1,subii(x,x1)))); y = modii(y,p);
! 1473: affii(x, x1);
! 1474: affii(y, y1);
! 1475: }
! 1476:
! 1477: static GEN
! 1478: powsell(GEN e, GEN z, GEN n, GEN p)
! 1479: {
! 1480: GEN y;
! 1481: long s=signe(n),i,j;
! 1482: ulong m;
! 1483:
! 1484: if (!s || !z) return NULL;
! 1485: if (s < 0)
! 1486: {
! 1487: n = negi(n); y = cgetg(3,t_VEC);
! 1488: y[2] = lnegi((GEN)z[2]);
! 1489: y[1] = z[1]; z = y;
! 1490: }
! 1491: if (is_pm1(n)) return z;
! 1492:
! 1493: y = NULL;
! 1494: for (i=lgefint(n)-1; i>2; i--)
! 1495: for (m=n[i],j=0; j<BITS_IN_LONG; j++,m>>=1)
! 1496: {
! 1497: if (m&1) y = addsell(e,y,z,p);
! 1498: z = addsell(e,z,z,p);
! 1499: }
! 1500: for (m=n[2]; m>1; m>>=1)
! 1501: {
! 1502: if (m&1) y = addsell(e,y,z,p);
! 1503: z = addsell(e,z,z,p);
! 1504: }
! 1505: return addsell(e,y,z,p);
! 1506: }
! 1507:
! 1508: /* make sure *x has lgefint >= k */
! 1509: static void
! 1510: _fix(GEN x, long k)
! 1511: {
! 1512: GEN y = (GEN)*x;
! 1513: if (lgefint(y) < k) { GEN p1 = cgeti(k); affii(y,p1); *x = (long)p1; }
! 1514: }
! 1515:
! 1516: /* low word of integer x */
! 1517: #define _low(x) ((x)[lgefint(x)-1])
! 1518:
! 1519: /* compute a_p using Shanks/Mestre + Montgomery's trick. Assume p > 20, say */
! 1520: GEN
! 1521: apell1(GEN e, GEN p)
! 1522: {
! 1523: long *tx, *ty, *ti, av = avma, av2,pfinal,i,j,j2,s,flc,flcc,x,nb;
! 1524: GEN p1,p2,p3,h,mfh,f,fh,fg,pordmin,u,v,p1p,p2p,acon,bcon,c4,c6,cp4,pts;
! 1525:
! 1526: if (DEBUGLEVEL) timer2();
! 1527: p1 = gmodulsg(1,p);
! 1528: c4 = gdivgs(gmul(p1,(GEN)e[10]), -48);
! 1529: c6 = gdivgs(gmul(p1,(GEN)e[11]), -864);
! 1530: pordmin = gceil(gmul2n(gsqrt(p,DEFAULTPREC),2));
! 1531: p1p = addsi(1,p); p2p = shifti(p1p,1);
! 1532: x=0; flcc=0; flc = kronecker((GEN)c6[2],p);
! 1533: u=c6; acon=gzero; bcon=gun; h=p1p;
! 1534: for(;;)
! 1535: {
! 1536: while (flc==flcc || !flc)
! 1537: {
! 1538: x++;
! 1539: u = gadd(c6, gmulsg(x, gaddgs(c4,x*x)));
! 1540: flc = kronecker((GEN)u[2],p);
! 1541: }
! 1542: flcc = flc;
! 1543: f = cgetg(3,t_VEC);
! 1544: f[1] = (long)lift_intern(gmulsg(x,u));
! 1545: f[2] = (long)lift_intern(gsqr(u));
! 1546: cp4 = lift_intern(gmul(c4, (GEN)f[2]));
! 1547: fh = powsell(cp4,f,h,p);
! 1548: s = itos(gceil(gsqrt(gdiv(pordmin,bcon),DEFAULTPREC))) >> 1;
! 1549: nb = min(128, s >> 1);
! 1550: if (bcon == gun)
! 1551: { /* first time: initialize */
! 1552: tx = newbloc(s+1); *tx = evaltyp(t_VECSMALL) | evallg(s+1);
! 1553: ty = newbloc(s+1);
! 1554: ti = newbloc(s+1);
! 1555: }
! 1556: else f = powsell(cp4,f,bcon,p);
! 1557: if (!fh) goto FOUND;
! 1558:
! 1559: p1 = gcopy(fh);
! 1560: pts = new_chunk(nb+1);
! 1561: j = lgefint(p);
! 1562: for (i=1; i<=nb; i++)
! 1563: { /* baby steps */
! 1564: pts[i] = (long)p1;
! 1565: _fix(p1+1, j); tx[i] = _low((GEN)p1[1]);
! 1566: _fix(p1+2, j); ty[i] = _low((GEN)p1[2]);
! 1567: p1 = addsell(cp4,p1,f,p); /* f^h * F^nb */
! 1568: if (!p1) { h = addii(h, mulsi(i,bcon)); goto FOUND; }
! 1569: }
! 1570: mfh = dummycopy(fh);
! 1571: mfh[2] = lnegi((GEN)mfh[2]);
! 1572: fg = addsell(cp4,p1,mfh,p); /* F^nb */
! 1573: if (!fg) { h = addii(h, mulsi(nb,bcon)); goto FOUND; }
! 1574: u = cgetg(nb+1, t_VEC);
! 1575: av2 = avma; /* more baby steps, nb points at a time */
! 1576: while (i <= s)
! 1577: {
! 1578: long maxj;
! 1579: for (j=1; j<=nb; j++)
! 1580: {
! 1581: p1 = (GEN)pts[j];
! 1582: u[j] = lsubii((GEN)fg[1], (GEN)p1[1]);
! 1583: if (u[j] == zero)
! 1584: {
! 1585: if (!signe(p1[2]) || !egalii((GEN)p1[2],(GEN)fg[2]))
! 1586: { h = addii(h, mulsi(i+j-1,bcon)); goto FOUND; }
! 1587: /* doubling never occurs */
! 1588: err(bugparier, "apell1: doubling?");
! 1589: }
! 1590: }
! 1591: v = multi_invmod(u, p);
! 1592: maxj = (i-1 + nb <= s)? nb: s % nb;
! 1593: for (j=1; j<=maxj; j++,i++)
! 1594: {
! 1595: p1 = (GEN)pts[j];
! 1596: addsell_part2(cp4,p1,fg,p, (GEN)v[j]);
! 1597: tx[i] = _low((GEN)p1[1]);
! 1598: ty[i] = _low((GEN)p1[2]);
! 1599: }
! 1600: avma = av2;
! 1601: }
! 1602: p1 = addsell(cp4,(GEN)pts[j-1],mfh,p); /* = f^(s-1) */
! 1603: if (DEBUGLEVEL) msgtimer("[apell1] baby steps, s = %ld",s);
! 1604:
! 1605: /* giant steps: fg = f^s */
! 1606: fg = addsell(cp4,p1,f,p);
! 1607: if (!fg) { h = addii(h, mulsi(s,bcon)); goto FOUND; }
! 1608: pfinal = _low(p); av2 = avma;
! 1609:
! 1610: p1 = gen_sort(tx, cmp_IND | cmp_C, NULL);
! 1611: for (i=1; i<=s; i++) ti[i] = tx[p1[i]];
! 1612: for (i=1; i<=s; i++) { tx[i] = ti[i]; ti[i] = ty[p1[i]]; }
! 1613: for (i=1; i<=s; i++) { ty[i] = ti[i]; ti[i] = p1[i]; }
! 1614: if (DEBUGLEVEL) msgtimer("[apell1] sorting");
! 1615: avma = av2;
! 1616:
! 1617: gaffect(fg, (GEN)pts[1]);
! 1618: for (j=2; j<=nb; j++) /* pts = first nb multiples of fg */
! 1619: gaffect(addsell(cp4,(GEN)pts[j-1],fg,p), (GEN)pts[j]);
! 1620: /* replace fg by fg^nb since we do nb points at a time */
! 1621: avma = av2;
! 1622: fg = gcopy((GEN)pts[nb]);
! 1623: av2 = avma;
! 1624:
! 1625: for (i=1,j=1; ; i++)
! 1626: {
! 1627: GEN ftest = (GEN)pts[j];
! 1628: ulong m, l = 1, r = s+1;
! 1629: long k, k2;
! 1630:
! 1631: avma = av2;
! 1632: k = _low((GEN)ftest[1]);
! 1633: while (l<r)
! 1634: {
! 1635: m = (l+r) >> 1;
! 1636: if (tx[m] < k) l = m+1; else r = m;
! 1637: }
! 1638: if (r <= s && tx[r] == k)
! 1639: {
! 1640: while (tx[r] == k && r) r--;
! 1641: k2 = _low((GEN)ftest[2]);
! 1642: for (r++; tx[r] == k && r <= s; r++)
! 1643: if (ty[r] == k2 || ty[r] == pfinal - k2)
! 1644: { /* [h+j2] f == ± ftest (= [i.s] f)? */
! 1645: if (DEBUGLEVEL) msgtimer("[apell1] giant steps, i = %ld",i);
! 1646: j2 = ti[r] - 1;
! 1647: p1 = addsell(cp4, powsell(cp4,f,stoi(j2),p),fh,p);
! 1648: if (egalii((GEN)p1[1], (GEN)ftest[1]))
! 1649: {
! 1650: h = addii(h, mulsi(j2,bcon));
! 1651: if (egalii((GEN)p1[2], (GEN)ftest[2])) i = -i;
! 1652: h = addii(h, mulsi(s, mulsi(i, bcon)));
! 1653: goto FOUND;
! 1654: }
! 1655: }
! 1656: }
! 1657: if (++j > nb)
! 1658: { /* compute next nb points */
! 1659: long save;
! 1660: for (j=1; j<=nb; j++)
! 1661: {
! 1662: p1 = (GEN)pts[j];
! 1663: u[j] = lsubii((GEN)fg[1], (GEN)p1[1]);
! 1664: if (u[j] == zero) /* occurs once: i = j = nb, p1 == fg */
! 1665: {
! 1666: u[j] = lshifti((GEN)p1[2],1);
! 1667: save = fg[1]; fg[1] = p1[1];
! 1668: }
! 1669: }
! 1670: v = multi_invmod(u, p);
! 1671: for (j=1; j<=nb; j++)
! 1672: addsell_part2(cp4, (GEN)pts[j],fg,p, (GEN)v[j]);
! 1673: if (i == nb) { fg[1] = save; }
! 1674: j = 1;
! 1675: }
! 1676: }
! 1677:
! 1678: FOUND: /* success, found a point of exponent h */
! 1679: p2 = decomp(h); p1=(GEN)p2[1]; p2=(GEN)p2[2];
! 1680: for (i=1; i<lg(p1); i++)
! 1681: for (j=itos((GEN)p2[i]); j; j--)
! 1682: {
! 1683: p3 = divii(h,(GEN)p1[i]);
! 1684: if (powsell(cp4,f,p3,p)) break;
! 1685: h = p3;
! 1686: }
! 1687: /* now h is the exact order */
! 1688: if (bcon == gun) bcon = h;
! 1689: else
! 1690: {
! 1691: p1 = chinois(gmodulcp(acon,bcon), gmodulsg(0,h));
! 1692: acon = (GEN)p1[2];
! 1693: bcon = (GEN)p1[1];
! 1694: }
! 1695:
! 1696: i = (cmpii(bcon, pordmin) < 0);
! 1697: if (i) acon = centermod(subii(p2p,acon), bcon);
! 1698: p1 = ground(gdiv(gsub(p1p,acon),bcon));
! 1699: h = addii(acon, mulii(p1,bcon));
! 1700: if (!i) break;
! 1701: }
! 1702: gunclone(tx);
! 1703: gunclone(ty);
! 1704: gunclone(ti);
! 1705: p1 = (flc==1)? subii(p1p,h): subii(h,p1p);
! 1706: return gerepileupto(av,p1);
! 1707: }
! 1708:
! 1709: typedef struct
! 1710: {
! 1711: int isnull;
! 1712: long x,y;
! 1713: } sellpt;
! 1714:
! 1715: /* set p1 <-- p1 + p2, safe with p1 = p2 */
! 1716: static void
! 1717: addsell1(long e, long p, sellpt *p1, sellpt *p2)
! 1718: {
! 1719: long num, den, lambda;
! 1720:
! 1721: if (p1->isnull) { *p1 = *p2; return; }
! 1722: if (p2->isnull) return;
! 1723: if (p1->x == p2->x)
! 1724: {
! 1725: if (! p1->y || p1->y != p2->y) { p1->isnull = 1; return; }
! 1726: num = addssmod(e, mulssmod(3, mulssmod(p1->x, p1->x, p), p), p);
! 1727: den = addssmod(p1->y, p1->y, p);
! 1728: }
! 1729: else
! 1730: {
! 1731: num = subssmod(p1->y, p2->y, p);
! 1732: den = subssmod(p1->x, p2->x, p);
! 1733: }
! 1734: lambda = divssmod(num, den, p);
! 1735: num = subssmod(mulssmod(lambda, lambda, p), addssmod(p1->x, p2->x, p), p);
! 1736: p1->y = subssmod(mulssmod(lambda, subssmod(p2->x, num, p), p), p2->y, p);
! 1737: p1->x = num; /* necessary in case p1 = p2: we need p2->x above */
! 1738: }
! 1739:
! 1740: static void
! 1741: powssell1(long e, long p, long n, sellpt *p1, sellpt *p2)
! 1742: {
! 1743: sellpt p3 = *p1;
! 1744:
! 1745: if (n < 0) { n = -n; if (p3.y) p3.y = p - p3.y; }
! 1746: p2->isnull = 1;
! 1747: for(;;)
! 1748: {
! 1749: if (n&1) addsell1(e, p, p2, &p3);
! 1750: n>>=1; if (!n) return;
! 1751: addsell1(e, p, &p3, &p3);
! 1752: }
! 1753: }
! 1754:
! 1755: typedef struct
! 1756: {
! 1757: long x,y,i;
! 1758: } multiple;
! 1759:
! 1760: static int
! 1761: compare_multiples(multiple *a, multiple *b)
! 1762: {
! 1763: return a->x - b->x;
! 1764: }
! 1765:
! 1766: /* assume e has good reduction at p. Should use Montgomery. */
! 1767: static GEN
! 1768: apell0(GEN e, long p)
! 1769: {
! 1770: GEN p1,p2;
! 1771: sellpt f,fh,fg,ftest,f2;
! 1772: long pordmin,u,p1p,p2p,acon,bcon,c4,c6,cp4;
! 1773: long av,i,j,s,flc,flcc,x,q,h,p3,l,r,m;
! 1774: multiple *table;
! 1775:
! 1776: if (p < 99) return apell2_intern(e,(ulong)p);
! 1777:
! 1778: av = avma; p1 = gmodulss(1,p);
! 1779: c4 = itos((GEN)gdivgs(gmul(p1,(GEN)e[10]), -48)[2]);
! 1780: c6 = itos((GEN)gdivgs(gmul(p1,(GEN)e[11]), -864)[2]);
! 1781: pordmin = (long)(1 + 4*sqrt((float)p));
! 1782: p1p = p+1; p2p = p1p << 1;
! 1783: x=0; flcc=0; flc = kross(c6, p);
! 1784: u=c6; acon=0; bcon=1; h=p1p;
! 1785: for(;;)
! 1786: {
! 1787: while (flc==flcc || !flc)
! 1788: {
! 1789: x++;
! 1790: u = addssmod(c6, mulssmod(x, c4+mulssmod(x,x,p), p), p);
! 1791: flc = kross(u,p);
! 1792: }
! 1793: flcc = flc;
! 1794: f.isnull = 0;
! 1795: f.x = mulssmod(x, u, p);
! 1796: f.y = mulssmod(u, u, p);
! 1797: cp4 = mulssmod(c4, f.y, p);
! 1798: powssell1(cp4, p, h, &f, &fh);
! 1799: s = (long) (sqrt(((float)pordmin)/bcon) / 2);
! 1800: if (!s) s=1;
! 1801: if (bcon==1)
! 1802: {
! 1803: table = (multiple *) gpmalloc((s+1)*sizeof(multiple));
! 1804: f2 = f;
! 1805: }
! 1806: else powssell1(cp4, p, bcon, &f, &f2);
! 1807: for (i=0; i < s; i++)
! 1808: {
! 1809: if (fh.isnull) { h += bcon*i; goto FOUND; }
! 1810: table[i].x = fh.x;
! 1811: table[i].y = fh.y;
! 1812: table[i].i = i;
! 1813: addsell1(cp4, p, &fh, &f2);
! 1814: }
! 1815: qsort(table,s,sizeof(multiple),(QSCOMP)compare_multiples);
! 1816: powssell1(cp4, p, s, &f2, &fg); ftest = fg;
! 1817: for (i=1; ; i++)
! 1818: {
! 1819: if (ftest.isnull) err(bugparier,"apell (f^(i*s) = 1)");
! 1820: l=0; r=s;
! 1821: while (l<r)
! 1822: {
! 1823: m = (l+r) >> 1;
! 1824: if (table[m].x < ftest.x) l=m+1; else r=m;
! 1825: }
! 1826: if (r < s && table[r].x == ftest.x) break;
! 1827: addsell1(cp4, p, &ftest, &fg);
! 1828: }
! 1829: h += table[r].i * bcon;
! 1830: if (table[r].y == ftest.y) i = -i;
! 1831: h += s * i * bcon;
! 1832:
! 1833: FOUND:
! 1834: p2=decomp(stoi(h)); p1=(GEN)p2[1]; p2=(GEN)p2[2];
! 1835: for (i=1; i < lg(p1); i++)
! 1836: for (j = mael(p2,i,2); j; j--)
! 1837: {
! 1838: p3 = h / mael(p1,i,2);
! 1839: powssell1(cp4, p, p3, &f, &fh);
! 1840: if (!fh.isnull) break;
! 1841: h = p3;
! 1842: }
! 1843: if (bcon == 1) bcon = h;
! 1844: else
! 1845: {
! 1846: p1 = chinois(gmodulss(acon,bcon), gmodulss(0,h));
! 1847: acon = itos((GEN)p1[2]);
! 1848: if (is_bigint(p1[1])) { h = acon; break; }
! 1849: bcon = itos((GEN)p1[1]);
! 1850: }
! 1851:
! 1852: i = (bcon < pordmin);
! 1853: if (i)
! 1854: {
! 1855: acon = (p2p - acon) % bcon;
! 1856: if ((acon << 1) > bcon) acon -= bcon;
! 1857: }
! 1858: q = ((ulong)(p2p + bcon - (acon << 1))) / (bcon << 1);
! 1859: h = acon + q*bcon;
! 1860: avma = av; if (!i) break;
! 1861: }
! 1862: free(table); return stoi((flc==1)? p1p-h: h-p1p);
! 1863: }
! 1864:
! 1865: GEN
! 1866: apell(GEN e, GEN p)
! 1867: {
! 1868: checkell(e);
! 1869: if (typ(p)!=t_INT || signe(p)<0) err(talker,"not a prime in apell");
! 1870: if (gdivise((GEN)e[12],p)) /* e[12] may be an intmod */
! 1871: {
! 1872: long av = avma,s;
! 1873: GEN c6 = gmul((GEN)e[11],gmodulsg(1,p));
! 1874: s = kronecker((GEN)c6[2],p); avma=av;
! 1875: switch(mod4(p))
! 1876: {
! 1877: case 0:
! 1878: case 3: s = -s;
! 1879: }
! 1880: return stoi(s);
! 1881: }
! 1882: if (cmpis(p, 0x3fffffff) > 0) return apell1(e, p);
! 1883: return apell0(e, itos(p));
! 1884: }
! 1885:
! 1886: /* TEMPC is the largest prime whose square is less than HIGHBIT */
! 1887: #ifndef LONG_IS_64BIT
! 1888: # define TEMPC 46337
! 1889: # define TEMPMAX 16777215UL
! 1890: #else
! 1891: # define TEMPC 3037000493
! 1892: # define TEMPMAX 4294967295UL
! 1893: #endif
! 1894:
! 1895: GEN
! 1896: anell(GEN e, long n)
! 1897: {
! 1898: long tab[4]={0,1,1,-1}; /* p prime; (-1/p) = tab[p&3]. tab[0] is not used */
! 1899: long p, i, m, av, tetpil;
! 1900: GEN p1,p2,an;
! 1901:
! 1902: checkell(e);
! 1903: if (n <= 0) return cgetg(1,t_VEC);
! 1904: if (n>TEMPMAX) err(impl,"anell for n>=2^24 (or 2^32 for 64 bit machines)");
! 1905: an = cgetg(n+1,t_VEC); an[1] = un;
! 1906: for (i=2; i <= n; i++) an[i] = 0;
! 1907: for (p=2; p<=n; p++)
! 1908: if (!an[p])
! 1909: {
! 1910: if (!smodis((GEN)e[12],p)) /* mauvaise reduction, p | e[12] */
! 1911: switch (tab[p&3] * krogs((GEN)e[11],p)) /* renvoie (-c6/p) */
! 1912: {
! 1913: case -1: /* non deployee */
! 1914: for (m=p; m<=n; m+=p)
! 1915: if (an[m/p]) an[m]=lneg((GEN)an[m/p]);
! 1916: continue;
! 1917: case 0: /* additive */
! 1918: for (m=p; m<=n; m+=p) an[m]=zero;
! 1919: continue;
! 1920: case 1: /* deployee */
! 1921: for (m=p; m<=n; m+=p)
! 1922: if (an[m/p]) an[m]=lcopy((GEN)an[m/p]);
! 1923: }
! 1924: else /* bonne reduction */
! 1925: {
! 1926: GEN ap = apell0(e,p);
! 1927:
! 1928: if (p < TEMPC)
! 1929: {
! 1930: ulong pk, oldpk = 1;
! 1931: for (pk=p; pk <= n; oldpk=pk, pk *= p)
! 1932: {
! 1933: if (pk == p) an[pk] = (long) ap;
! 1934: else
! 1935: {
! 1936: av = avma;
! 1937: p1 = mulii(ap, (GEN)an[oldpk]);
! 1938: p2 = mulsi(p, (GEN)an[oldpk/p]);
! 1939: tetpil = avma;
! 1940: an[pk] = lpile(av,tetpil,subii(p1,p2));
! 1941: }
! 1942: for (m = n/pk; m > 1; m--)
! 1943: if (an[m] && m%p) an[m*pk] = lmulii((GEN)an[m], (GEN)an[pk]);
! 1944: }
! 1945: }
! 1946: else
! 1947: {
! 1948: an[p] = (long) ap;
! 1949: for (m = n/p; m > 1; m--)
! 1950: if (an[m] && m%p) an[m*p] = lmulii((GEN)an[m], (GEN)an[p]);
! 1951: }
! 1952: }
! 1953: }
! 1954: return an;
! 1955: }
! 1956:
! 1957: GEN
! 1958: akell(GEN e, GEN n)
! 1959: {
! 1960: long i,j,ex,av=avma;
! 1961: GEN p1,p2,ap,u,v,w,y,pl;
! 1962:
! 1963: checkell(e);
! 1964: if (typ(n)!=t_INT) err(talker,"not an integer type in akell");
! 1965: if (signe(n)<= 0) return gzero;
! 1966: y=gun; if (gcmp1(n)) return y;
! 1967: p2=auxdecomp(n,1); p1=(GEN)p2[1]; p2=(GEN)p2[2];
! 1968: for (i=1; i<lg(p1); i++)
! 1969: {
! 1970: pl=(GEN)p1[i];
! 1971: if (divise((GEN)e[12], pl)) /* mauvaise reduction */
! 1972: {
! 1973: j = (((mod4(pl)+1)&2)-1)*kronecker((GEN)e[11],pl);
! 1974: if (j<0 && mpodd((GEN)p2[i])) y = negi(y);
! 1975: if (!j) { avma=av; return gzero; }
! 1976: }
! 1977: else /* bonne reduction */
! 1978: {
! 1979: ap=apell(e,pl); ex=itos((GEN)p2[i]);
! 1980: u=ap; v=gun;
! 1981: for (j=2; j<=ex; j++)
! 1982: {
! 1983: w = subii(mulii(ap,u), mulii(pl,v));
! 1984: v=u; u=w;
! 1985: }
! 1986: y = mulii(u,y);
! 1987: }
! 1988: }
! 1989: return gerepileupto(av,y);
! 1990: }
! 1991:
! 1992: GEN
! 1993: hell(GEN e, GEN a, long prec)
! 1994: {
! 1995: long av=avma,tetpil,n;
! 1996: GEN p1,p2,y,z,q,pi2surw,pi2isurw,qn,ps;
! 1997:
! 1998: checkbell(e);
! 1999: pi2surw=gdiv(gmul2n(mppi(prec),1),(GEN)e[15]);
! 2000: pi2isurw=cgetg(3,t_COMPLEX); pi2isurw[1]=zero; pi2isurw[2]=(long)pi2surw;
! 2001: z=gmul(greal(zell(e,a,prec)),pi2surw);
! 2002: q=greal(gexp(gmul((GEN)e[16],pi2isurw),prec));
! 2003: y=gsin(z,prec); n=0; qn=gun; ps=gneg_i(q);
! 2004: do
! 2005: {
! 2006: n++; p1=gsin(gmulsg(2*n+1,z),prec); qn=gmul(qn,ps);
! 2007: ps=gmul(ps,q); p1=gmul(p1,qn); y=gadd(y,p1);
! 2008: }
! 2009: while (gexpo(qn) >= - bit_accuracy(prec));
! 2010: p1=gmul(gsqr(gdiv(gmul2n(y,1), d_ellLHS(e,a))),pi2surw);
! 2011: p2=gsqr(gsqr(gdiv(p1,gsqr(gsqr(denom((GEN)a[1]))))));
! 2012: p1=gdiv(gmul(p2,q),(GEN)e[12]);
! 2013: p1=gmul2n(glog(gabs(p1,prec),prec),-5);
! 2014: tetpil=avma; return gerepile(av,tetpil,gneg(p1));
! 2015: }
! 2016:
! 2017: static GEN
! 2018: hells(GEN e, GEN x, long prec)
! 2019: {
! 2020: GEN w,z,t,mu,e72,e82;
! 2021: long n,lim;
! 2022:
! 2023: t = gdiv(realun(prec),(GEN)x[1]);
! 2024: mu = gmul2n(glog(numer((GEN)x[1]),prec),-1);
! 2025: e72 = gmul2n((GEN)e[7],1);
! 2026: e82 = gmul2n((GEN)e[8],1);
! 2027: lim = 6 + (bit_accuracy(prec) >> 1);
! 2028: for (n=0; n<lim; n++)
! 2029: {
! 2030: w = gmul(t,gaddsg(4,gmul(t,gadd((GEN)e[6],gmul(t,gadd(e72,gmul(t,(GEN)e[8])))))));
! 2031: z = gsub(gun,gmul(gsqr(t),gadd((GEN)e[7],gmul(t,gadd(e82,gmul(t,(GEN)e[9]))))));
! 2032: mu = gadd(mu,gmul2n(glog(z,prec), -((n<<1)+3)));
! 2033: t = gdiv(w,z);
! 2034: }
! 2035: return mu;
! 2036: }
! 2037:
! 2038: GEN
! 2039: hell2(GEN e, GEN x, long prec)
! 2040: {
! 2041: GEN ep,e3,ro,p1,p2,mu,d,xp;
! 2042: long av=avma,tetpil,lx,lc,i,j,tx;
! 2043:
! 2044: if (!oncurve(e,x)) err(heller1);
! 2045: d=(GEN)e[12]; ro=(GEN)e[14]; e3=(gsigne(d) < 0)?(GEN)ro[1]:(GEN)ro[3];
! 2046: p1=cgetg(5,t_VEC); p1[1]=un; p1[2]=laddgs(gfloor(e3),-1);
! 2047: p1[3]=p1[4]=zero; ep=coordch(e,p1); xp=pointch(x,p1);
! 2048: tx=typ(x[1]); lx=lg(x);
! 2049: if (!is_matvec_t(tx))
! 2050: {
! 2051: if (lx<3) { avma=av; return gzero; }
! 2052: tetpil=avma; return gerepile(av,tetpil,hells(ep,xp,prec));
! 2053: }
! 2054: tx=typ(x);
! 2055: tetpil=avma; mu=cgetg(lx,tx);
! 2056: if (tx != t_MAT)
! 2057: for (i=1; i<lx; i++) mu[i]=(long)hells(ep,(GEN)xp[i],prec);
! 2058: else
! 2059: {
! 2060: lc=lg(x[1]);
! 2061: for (i=1; i<lx; i++)
! 2062: {
! 2063: p1=cgetg(lc,t_COL); mu[i]=(long)p1; p2=(GEN)xp[i];
! 2064: for (j=1; j<lc; j++) p1[j]=(long)hells(ep,(GEN)p2[j],prec);
! 2065: }
! 2066: }
! 2067: return gerepile(av,tetpil,mu);
! 2068: }
! 2069:
! 2070: GEN
! 2071: hell0(GEN e, GEN z, long prec)
! 2072: {
! 2073: GEN a,b,s,x,u,v,u1,p1,p2;
! 2074: long n,i, ex = 5-bit_accuracy(prec);
! 2075:
! 2076: /* cf. zell mais ne marche pas. Comment corriger? K.B. */
! 2077: x = new_coords(e,(GEN)z[1],&a,&b,prec);
! 2078:
! 2079: u = gmul2n(gadd(a,b), -1);
! 2080: v = gsqrt(gmul(a,b), prec); s = gun;
! 2081: for(n=0; ; n++)
! 2082: {
! 2083: p1 = gmul2n(gsub(x, gsqr(v)), -1);
! 2084: p2 = gsqr(u);
! 2085: x = gadd(p1, gsqrt(gadd(gsqr(p1), gmul(x, p2)), prec));
! 2086: p2 = gadd(x, p2);
! 2087: for (i=1; i<=n; i++) p2 = gsqr(p2);
! 2088: s = gmul(s, p2);
! 2089: u1 = gmul2n(gadd(u,v), -1);
! 2090: if (gexpo(gsub(u,u1)) < ex) break;
! 2091:
! 2092: v = gsqrt(gmul(u,v), prec);
! 2093: u = u1;
! 2094: }
! 2095: return gmul2n(glog(gdiv(gsqr(p2), s), prec) ,-1);
! 2096: }
! 2097:
! 2098: /* On suppose que `e' est a coeffs entiers donnee par un modele minimal */
! 2099: static GEN
! 2100: ghell0(GEN e, GEN a, long flag, long prec)
! 2101: {
! 2102: long av=avma,lx,i,n,n2,grandn,tx=typ(a);
! 2103: GEN p,p1,p2,x,y,z,phi2,psi2,psi3,logdep;
! 2104:
! 2105: checkbell(e); if (!is_matvec_t(tx)) err(elliper1);
! 2106: lx = lg(a); if (lx==1) return cgetg(1,tx);
! 2107: tx=typ(a[1]);
! 2108: if (is_matvec_t(tx))
! 2109: {
! 2110: z=cgetg(lx,tx);
! 2111: for (i=1; i<lx; i++) z[i]=(long)ghell0(e,(GEN)a[i],flag,prec);
! 2112: return z;
! 2113: }
! 2114: if (lg(a)<3) return gzero;
! 2115: if (!oncurve(e,a)) err(heller1);
! 2116:
! 2117: psi2=numer(d_ellLHS(e,a));
! 2118: if (!signe(psi2)) { avma=av; return gzero; }
! 2119:
! 2120: x=(GEN)a[1]; y=(GEN)a[2];
! 2121: p2=gadd(gmulsg(3,(GEN)e[7]),gmul(x,gadd((GEN)e[6],gmulsg(3,x))));
! 2122: psi3=numer(gadd((GEN)e[9],gmul(x,gadd(gmulsg(3,(GEN)e[8]),gmul(x,p2)))));
! 2123: if (!signe(psi3)) { avma=av; return gzero; }
! 2124:
! 2125: p1 = gmul(x,gadd(shifti((GEN)e[2],1),gmulsg(3,x)));
! 2126: phi2=numer(gsub(gadd((GEN)e[4],p1), gmul((GEN)e[1],y)));
! 2127: p1=(GEN)factor(mppgcd(psi2,phi2))[1]; lx=lg(p1);
! 2128: switch(flag)
! 2129: {
! 2130: case 0: z = hell2(e,a,prec); break; /* Tate 4^n */
! 2131: case 1: z = hell(e,a,prec); break; /* Silverman's trick */
! 2132: case 2: z = hell0(e,a,prec); break; /* Mestre's trick */
! 2133:
! 2134: }
! 2135: for (i=1; i<lx; i++)
! 2136: {
! 2137: p=(GEN)p1[i];
! 2138: if (signe(resii((GEN)e[10],p)))
! 2139: {
! 2140: grandn=ggval((GEN)e[12],p);
! 2141: if (grandn)
! 2142: {
! 2143: n2=ggval(psi2,p); n=n2<<1;
! 2144: logdep=gneg_i(glog(p,prec));
! 2145: if (n>grandn) n=grandn;
! 2146: p2=divrs(mulsr(n*(grandn+grandn-n),logdep),grandn<<3);
! 2147: z=gadd(z,p2);
! 2148: }
! 2149: }
! 2150: else
! 2151: {
! 2152: n2=ggval(psi2,p);
! 2153: logdep=gneg_i(glog(p,prec));
! 2154: n=ggval(psi3,p);
! 2155: if (n>=3*n2) p2=gdivgs(mulsr(n2,logdep),3);
! 2156: else p2=gmul2n(mulsr(n,logdep),-3);
! 2157: z=gadd(z,p2);
! 2158: }
! 2159: }
! 2160: return gerepileupto(av,z);
! 2161: }
! 2162:
! 2163: GEN
! 2164: ellheight0(GEN e, GEN a, long flag, long prec)
! 2165: {
! 2166: switch(flag)
! 2167: {
! 2168: case 0: return ghell(e,a,prec);
! 2169: case 1: return ghell2(e,a,prec);
! 2170: case 2: return ghell0(e,a,2,prec);
! 2171: }
! 2172: err(flagerr,"ellheight");
! 2173: return NULL; /* not reached */
! 2174: }
! 2175:
! 2176: GEN
! 2177: ghell2(GEN e, GEN a, long prec)
! 2178: {
! 2179: return ghell0(e,a,0,prec);
! 2180: }
! 2181:
! 2182: GEN
! 2183: ghell(GEN e, GEN a, long prec)
! 2184: {
! 2185: return ghell0(e,a,1,prec);
! 2186: }
! 2187:
! 2188: static long ellrootno_all(GEN e, GEN p, GEN* ptcond);
! 2189:
! 2190: GEN
! 2191: lseriesell(GEN e, GEN s, GEN A, long prec)
! 2192: {
! 2193: long av=avma,av1,tetpil,lim,l,n,eps,flun;
! 2194: GEN z,p1,p2,cg,cg1,v,cga,cgb,s2,ns,gs,N;
! 2195:
! 2196: if (!A) A = gun;
! 2197: else
! 2198: {
! 2199: if (gsigne(A)<=0)
! 2200: err(talker,"cut-off point must be positive in lseriesell");
! 2201: if (gcmpgs(A,1) < 0) A = ginv(A);
! 2202: }
! 2203: flun = gcmp1(A) && gcmp1(s);
! 2204: eps = ellrootno_all(e,gun,&N);
! 2205: if (flun && eps<0) { z=cgetr(prec); affsr(0,z); return z; }
! 2206: cg1=mppi(prec); setexpo(cg1,2); cg=divrr(cg1,gsqrt(N,prec));
! 2207: cga=gmul(cg,A); cgb=gdiv(cg,A);
! 2208: l=(long)((pariC2*(prec-2) + fabs(gtodouble(s)-1.)*log(rtodbl(cga)))
! 2209: / rtodbl(cgb)+1);
! 2210: v = anell(e, min(l,TEMPMAX));
! 2211: if (!flun) { s2=gsubsg(2,s); ns=gpui(cg,gsubgs(gmul2n(s,1),2),prec); }
! 2212: z=gzero;
! 2213: if (typ(s)==t_INT)
! 2214: {
! 2215: if (signe(s)<=0) { avma=av; return gzero; }
! 2216: gs=mpfactr(itos(s)-1,prec);
! 2217: }
! 2218: else gs=ggamma(s,prec);
! 2219: av1=avma; lim=stack_lim(av1,1);
! 2220: for (n=1; n<=l; n++)
! 2221: {
! 2222: p1=gdiv(incgam4(s,gmulsg(n,cga),gs,prec),gpui(stoi(n),s,prec));
! 2223: p2=flun? p1: gdiv(gmul(ns,incgam(s2,gmulsg(n,cgb),prec)),
! 2224: gpui(stoi(n),s2,prec));
! 2225: if (eps<0) p2=gneg_i(p2);
! 2226: z = gadd(z,gmul(gadd(p1,p2),(n<=TEMPMAX)? (GEN)v[n]: akell(e,stoi(n))));
! 2227: if (low_stack(lim, stack_lim(av1,1)))
! 2228: {
! 2229: if(DEBUGMEM>1) err(warnmem,"lseriesell");
! 2230: tetpil=avma; z=gerepile(av1,tetpil,gcopy(z));
! 2231: }
! 2232: }
! 2233: tetpil=avma; return gerepile(av,tetpil,gdiv(z,gs));
! 2234: }
! 2235:
! 2236: /********************************************************************/
! 2237: /** **/
! 2238: /** Tate's algorithm e (cf Anvers IV) **/
! 2239: /** Kodaira types, global minimal model **/
! 2240: /** **/
! 2241: /********************************************************************/
! 2242:
! 2243: /* Given an integral elliptic curve in ellinit form, and a prime p, returns the
! 2244: type of the fiber at p of the Neron model, as well as the change of variables
! 2245: in the form [f, kod, v, c].
! 2246:
! 2247: * The integer f is the conductor's exponent.
! 2248:
! 2249: * The integer kod is the Kodaira type using the following notation:
! 2250: II , III , IV --> 2, 3, 4
! 2251: I0 --> 1
! 2252: Inu --> 4+nu for nu > 0
! 2253: A '*' negates the code (e.g I* --> -2)
! 2254:
! 2255: * v is a quadruple [u, r, s, t] yielding a minimal model
! 2256:
! 2257: * c is the Tamagawa number.
! 2258:
! 2259: Uses Tate's algorithm (Anvers IV). Given the remarks at the bottom of
! 2260: page 46, the "long" algorithm is used for p < 4 only. */
! 2261: static void cumule(GEN *vtotal, GEN *e, GEN u, GEN r, GEN s, GEN t);
! 2262: static void cumule1(GEN *vtotal, GEN *e, GEN v2);
! 2263:
! 2264: static GEN
! 2265: localreduction_result(long av, long f, long kod, long c, GEN v)
! 2266: {
! 2267: long tetpil = avma;
! 2268: GEN result = cgetg(5, t_VEC);
! 2269: result[1] = lstoi(f); result[2] = lstoi(kod);
! 2270: result[3] = lcopy(v); result[4] = lstoi(c);
! 2271: return gerepile(av,tetpil, result);
! 2272: }
! 2273:
! 2274: /* ici, p1 != 2 et p1 != 3 */
! 2275: static GEN
! 2276: localreduction_carac_not23(GEN e, GEN p1)
! 2277: {
! 2278: long av = avma, k, f, kod, c, nuj, nudelta;
! 2279: GEN pk, p2k, a2prime, a3prime;
! 2280: GEN p2, r = gzero, s = gzero, t = gzero, v;
! 2281: GEN c4, c6, delta, unmodp, xun, tri, var, p4k, p6k;
! 2282:
! 2283: nudelta = ggval((GEN)e[12], p1);
! 2284: v = cgetg(5,t_VEC); v[1] = un; v[2] = v[3] = v[4] = zero;
! 2285: nuj = gcmp0((GEN)e[13]) ? 0 : - ggval((GEN)e[13], p1);
! 2286: k = (nuj > 0 ? nudelta - nuj : nudelta) / 12;
! 2287: c4 = (GEN)e[10]; c6 = (GEN)e[11]; delta = (GEN)e[12];
! 2288: if (k > 0) /* modele non minimal */
! 2289: {
! 2290: pk = gpuigs(p1, k);
! 2291: if (mpodd((GEN)e[1]))
! 2292: s = shifti(subii(pk, (GEN)e[1]), -1);
! 2293: else
! 2294: s = negi(shifti((GEN)e[1], -1));
! 2295: p2k = sqri(pk);
! 2296: p4k = sqri(p2k);
! 2297: p6k = mulii(p4k, p2k);
! 2298:
! 2299: a2prime = subii((GEN)e[2], mulii(s, addii((GEN)e[1], s)));
! 2300: switch(smodis(a2prime, 3))
! 2301: {
! 2302: case 0: r = negi(divis(a2prime, 3)); break;
! 2303: case 1: r = divis(subii(p2k, a2prime), 3); break;
! 2304: case 2: r = negi(divis(addii(a2prime, p2k), 3)); break;
! 2305: }
! 2306: a3prime = ellLHS0_i(e,r);
! 2307: if (mpodd(a3prime))
! 2308: t = shifti(subii(mulii(pk, p2k), a3prime), -1);
! 2309: else
! 2310: t = negi(shifti(a3prime, -1));
! 2311: v[1] = (long)pk; v[2] = (long)r; v[3] = (long)s; v[4] = (long)t;
! 2312: nudelta -= 12 * k;
! 2313: c4 = divii(c4, p4k); c6 = divii(c6, p6k);
! 2314: delta = divii(delta, sqri(p6k));
! 2315: }
! 2316: if (nuj > 0) switch(nudelta - nuj)
! 2317: {
! 2318: case 0: f = 1; kod = 4+nuj; /* Inu */
! 2319: switch(kronecker(negi(c6),p1))
! 2320: {
! 2321: case 1: c = nudelta; break;
! 2322: case -1: c = 2 - (nudelta % 2); break;
! 2323: default: err(tater1);
! 2324: }
! 2325: break;
! 2326: case 6: f = 2; kod = -4-nuj; /* Inu* */
! 2327: if (nuj & 1)
! 2328: c = 3 + kronecker(divii(mulii(c6, delta),gpuigs(p1, 9+nuj)), p1);
! 2329: else
! 2330: c = 3 + kronecker(divii(delta, gpuigs(p1, 6+nuj)), p1);
! 2331: break;
! 2332: default: err(tater1);
! 2333: }
! 2334: else switch(nudelta)
! 2335: {
! 2336: case 0: f = 0; kod = 1; c = 1; break; /* I0, regulier */
! 2337: case 2: f = 2; kod = 2; c = 1; break; /* II */
! 2338: case 3: f = 2; kod = 3; c = 2; break; /* III */
! 2339: case 4: f = 2; kod = 4; /* IV */
! 2340: c = 2 + kronecker(gdiv(mulis(c6, -6), sqri(p1)), p1);
! 2341: break;
! 2342: case 6: f = 2; kod = -1; /* I0* */
! 2343: p2 = sqri(p1);
! 2344: unmodp = gmodulsg(1,p1);
! 2345: var = gmul(unmodp,polx[0]);
! 2346: tri = gsub(gsqr(var),gmul(divii(gmulsg(3, c4), p2),unmodp));
! 2347: tri = gsub(gmul(tri, var),
! 2348: gmul(divii(gmul2n(c6,1), mulii(p2,p1)),unmodp));
! 2349: xun = gmodulcp(var,tri);
! 2350: c = lgef(ggcd((GEN)(gsub(gpui(xun,p1,0),xun))[2], tri)) - 2;
! 2351: break;
! 2352: case 8: f = 2; kod = -4; /* IV* */
! 2353: c = 2 + kronecker(gdiv(mulis(c6,-6), gpuigs(p1,4)), p1);
! 2354: break;
! 2355: case 9: f = 2; kod = -3; c = 2; break; /* III* */
! 2356: case 10: f = 2; kod = -2; c = 1; break; /* II* */
! 2357: default: err(tater1);
! 2358: }
! 2359: return localreduction_result(av,f,kod,c,v);
! 2360: }
! 2361:
! 2362: /* renvoie a_{ k,l } avec les notations de Tate */
! 2363: static int
! 2364: aux(GEN ak, int p, int l)
! 2365: {
! 2366: long av = avma, pl = p, res;
! 2367: while (--l) pl *= p;
! 2368: res = smodis(divis(ak, pl), p);
! 2369: avma = av; return res;
! 2370: }
! 2371:
! 2372: static int
! 2373: aux2(GEN ak, int p, GEN pl)
! 2374: {
! 2375: long av = avma, res;
! 2376: res = smodis(divii(ak, pl), p);
! 2377: avma = av;
! 2378: return res;
! 2379: }
! 2380:
! 2381: /* renvoie le nombre de racines distinctes du polynome XXX + aXX + bX + c
! 2382: * modulo p s'il y a une racine multiple, elle est renvoyee dans *mult
! 2383: */
! 2384: static int
! 2385: numroots3(int a, int b, int c, int p, int *mult)
! 2386: {
! 2387: if (p == 2)
! 2388: {
! 2389: if ((c + a * b) & 1) return 3;
! 2390: else { *mult = b; return (a + b) & 1 ? 2 : 1; }
! 2391: }
! 2392: else
! 2393: {
! 2394: if (a % 3) { *mult = a * b; return (a * b * (1 - b) + c) % 3 ? 3 : 2; }
! 2395: else { *mult = -c; return b % 3 ? 3 : 1; }
! 2396: }
! 2397: }
! 2398:
! 2399: /* idem pour aXX +bX + c */
! 2400: static int
! 2401: numroots2(int a, int b, int c, int p, int *mult)
! 2402: {
! 2403: if (p == 2) { *mult = c; return b & 1 ? 2 : 1; }
! 2404: else { *mult = a * b; return (b * b - a * c) % 3 ? 2 : 1; }
! 2405: }
! 2406:
! 2407: /* ici, p1 = 2 ou p1 = 3 */
! 2408: static GEN
! 2409: localreduction_carac_23(GEN e, GEN p1)
! 2410: {
! 2411: long av = avma, p, c, nu, nudelta;
! 2412: int a21, a42, a63, a32, a64, theroot, al, be, ga;
! 2413: GEN pk, p2k, pk1, p4, p6;
! 2414: GEN p2, p3, r = gzero, s = gzero, t = gzero, v;
! 2415:
! 2416: nudelta = ggval((GEN)e[12], p1);
! 2417: v = cgetg(5,t_VEC); v[1] = un; v[2] = v[3] = v[4] = zero;
! 2418:
! 2419: for(;;)
! 2420: {
! 2421: if (!nudelta)
! 2422: return localreduction_result(av, 0, 1, 1, v);
! 2423: /* I0 */
! 2424: p = itos(p1);
! 2425: if (!divise((GEN)e[6], p1))
! 2426: {
! 2427: if (smodis(negi((GEN)e[11]), p == 2 ? 8 : 3) == 1)
! 2428: c = nudelta;
! 2429: else
! 2430: c = 2 - (nudelta & 1);
! 2431: return localreduction_result(av, 1, 4 + nudelta, c, v);
! 2432: }
! 2433: /* Inu */
! 2434: if (p == 2)
! 2435: {
! 2436: r = modis((GEN)e[4], 2);
! 2437: s = modis(addii(r, (GEN)e[2]), 2);
! 2438: if (signe(r)) t = modis(addii(addii((GEN)e[4], (GEN)e[5]), s), 2);
! 2439: else t = modis((GEN)e[5], 2);
! 2440: }
! 2441: else /* p == 3 */
! 2442: {
! 2443: r = negi(modis((GEN)e[8], 3));
! 2444: s = modis((GEN)e[1], 3);
! 2445: t = modis(ellLHS0_i(e,r), 3);
! 2446: }
! 2447: cumule(&v, &e, gun, r, s, t); /* p | a1, a2, a3, a4 et a6 */
! 2448: p2 = stoi(p*p);
! 2449: if (!divise((GEN)e[5], p2))
! 2450: return localreduction_result(av, nudelta, 2, 1, v);
! 2451: /* II */
! 2452: p3 = stoi(p*p*p);
! 2453: if (!divise((GEN)e[9], p3))
! 2454: return localreduction_result(av, nudelta - 1, 3, 2, v);
! 2455: /* III */
! 2456: if (!divise((GEN)e[8], p3))
! 2457: {
! 2458: if (smodis((GEN)e[8], (p==2)? 32: 27) == p*p)
! 2459: c = 3;
! 2460: else
! 2461: c = 1;
! 2462: return localreduction_result(av, nudelta - 2, 4, c, v);
! 2463: }
! 2464: /* IV */
! 2465:
! 2466: /* now for the last five cases... */
! 2467:
! 2468: if (!divise((GEN)e[5], p3))
! 2469: cumule(&v, &e, gun, gzero, gzero, p == 2? gdeux: modis((GEN)e[3], 9));
! 2470: /* p | a1, a2; p^2 | a3, a4; p^3 | a6 */
! 2471: a21 = aux((GEN)e[2], p, 1); a42 = aux((GEN)e[4], p, 2);
! 2472: a63 = aux((GEN)e[5], p, 3);
! 2473: switch (numroots3(a21, a42, a63, p, &theroot))
! 2474: {
! 2475: case 3:
! 2476: if (p == 2)
! 2477: c = 1 + (a63 == 0) + ((a21 + a42 + a63) & 1);
! 2478: else
! 2479: c = 1 + (a63 == 0) + (((1 + a21 + a42 + a63) % 3) == 0)
! 2480: + (((1 - a21 + a42 - a63) % 3) == 0);
! 2481: return localreduction_result(av, nudelta - 4, -1, c, v);
! 2482: /* I0* */
! 2483: case 2: /* calcul de nu */
! 2484: if (theroot) cumule(&v, &e, gun, stoi(theroot * p), gzero, gzero);
! 2485: /* p | a1; p^2 | a2, a3; p^3 | a4; p^4 | a6 */
! 2486: nu = 1;
! 2487: pk = p2;
! 2488: p2k = stoi(p * p * p * p);
! 2489: for(;;)
! 2490: {
! 2491: if (numroots2(al = 1, be = aux2((GEN)e[3], p, pk),
! 2492: ga = -aux2((GEN)e[5], p, p2k), p, &theroot) == 2)
! 2493: break;
! 2494: if (theroot) cumule(&v, &e, gun, gzero, gzero, mulsi(theroot,pk));
! 2495: pk1 = pk; pk = mulsi(p, pk); p2k = mulsi(p, p2k);
! 2496: nu++;
! 2497: if (numroots2(al = a21, be = aux2((GEN)e[4], p, pk),
! 2498: ga = aux2((GEN)e[5], p, p2k), p, &theroot) == 2)
! 2499: break;
! 2500: if (theroot) cumule(&v, &e, gun, mulsi(theroot, pk1), gzero, gzero);
! 2501: p2k = mulsi(p, p2k);
! 2502: nu++;
! 2503: }
! 2504: if (p == 2)
! 2505: c = 4 - 2 * (ga & 1);
! 2506: else
! 2507: c = 3 + kross(be * be - al * ga, 3);
! 2508: return localreduction_result(av, nudelta - 4 - nu, -4 - nu, c, v);
! 2509: /* Inu* */
! 2510: case 1:
! 2511: if (theroot) cumule(&v, &e, gun, stoi(theroot * p), gzero, gzero);
! 2512: /* p | a1; p^2 | a2, a3; p^3 | a4; p^4 | a6 */
! 2513: a32 = aux((GEN)e[3], p, 2); a64 = aux((GEN)e[5], p, 4);
! 2514: if (numroots2(1, a32, -a64, p, &theroot) == 2)
! 2515: {
! 2516: if (p == 2)
! 2517: c = 3 - 2 * a64;
! 2518: else
! 2519: c = 2 + kross(a32 * a32 + a64, 3);
! 2520: return localreduction_result(av, nudelta - 6, -4, c, v);
! 2521: }
! 2522: /* IV* */
! 2523: if (theroot) cumule(&v, &e, gun, gzero, gzero, stoi(theroot*p*p));
! 2524: /* p | a1; p^2 | a2; p^3 | a3, a4; p^5 | a6 */
! 2525: p4 = sqri(p2);
! 2526: if (!divise((GEN)e[4], p4))
! 2527: return localreduction_result(av, nudelta - 7, -3, 2, v);
! 2528: /* III* */
! 2529: p6 = mulii(p4, p2);
! 2530: if (!divise((GEN)e[5], p6))
! 2531: return localreduction_result(av, nudelta - 8, -2, 1, v);
! 2532: /* II* */
! 2533: cumule(&v, &e, p1, gzero, gzero, gzero); /* non minimal, on repart
! 2534: pour un tour */
! 2535: nudelta -= 12;
! 2536: }
! 2537: }
! 2538: /* Not reached */
! 2539: }
! 2540:
! 2541: GEN
! 2542: localreduction(GEN e, GEN p1)
! 2543: {
! 2544: checkell(e);
! 2545: if (typ(e[12]) != t_INT)
! 2546: err(talker,"not an integral curve in localreduction");
! 2547: if (gcmpgs(p1, 3) > 0) /* p different de 2 ou 3 */
! 2548: return localreduction_carac_not23(e,p1);
! 2549: else
! 2550: return localreduction_carac_23(e,p1);
! 2551: }
! 2552:
! 2553: #if 0
! 2554: /* Calcul de toutes les fibres non elliptiques d'une courbe sur Z.
! 2555: * Etant donne une courbe elliptique sous forme longue e, dont les coefficients
! 2556: * sont entiers, renvoie une matrice dont les lignes sont de la forme
! 2557: * [p, fp, kodp, cp]. Il y a une ligne par diviseur premier du discriminant.
! 2558: */
! 2559: GEN
! 2560: globaltatealgo(GEN e)
! 2561: {
! 2562: long k, l,av;
! 2563: GEN p1, p2, p3, p4, prims, result;
! 2564:
! 2565: checkell(e);
! 2566: prims = decomp((GEN)e[12]);
! 2567: l = lg(p1 = (GEN)prims[1]);
! 2568: p2 = (GEN)prims[2];
! 2569: if ((long)prims == avma) cgiv(prims);
! 2570: result = cgetg(5, t_MAT);
! 2571: result[1] = (long)p1;
! 2572: result[2] = (long)p2;
! 2573: result[3] = (long)(p3 = cgetg(l, t_COL));
! 2574: for (k = 1; k < l; k++) p3[k] = lgeti(3);
! 2575: result[4] = (long)(p4 = cgetg(l, t_COL));
! 2576: for (k = 1; k < l; k++) p4[k] = lgeti(3);
! 2577: av = avma;
! 2578: for (k = 1; k < l; k++)
! 2579: {
! 2580: GEN q = localreduction(e, (GEN)p1[k]);
! 2581: affii((GEN)q[1],(GEN)p2[k]);
! 2582: affii((GEN)q[2],(GEN)p3[k]);
! 2583: affii((GEN)q[4],(GEN)p4[k]);
! 2584: avma = av;
! 2585: }
! 2586: return result;
! 2587: }
! 2588: #endif
! 2589:
! 2590: /* Algorithme de reduction d'une courbe sur Q a sa forme standard. Etant
! 2591: * donne une courbe elliptique sous forme longue e, dont les coefficients
! 2592: * sont rationnels, renvoie son [N, [u, r, s, t], c], ou N est le conducteur
! 2593: * arithmetique de e, [u, r, s, t] est le changement de variables qui reduit
! 2594: * e a sa forme minimale globale dans laquelle a1 et a3 valent 0 ou 1, et a2
! 2595: * vaut -1, 0 ou 1 et tel que u est un rationnel positif. Enfin c est le
! 2596: * produit des nombres de Tamagawa locaux cp.
! 2597: */
! 2598: GEN
! 2599: globalreduction(GEN e1)
! 2600: {
! 2601: long i, k, l, m, tetpil, av = avma;
! 2602: GEN p1, c = gun, prims, result, N = gun, u = gun, r, s, t;
! 2603: GEN v = cgetg(5, t_VEC), a = cgetg(7, t_VEC), e = cgetg(20, t_VEC);
! 2604:
! 2605: checkell(e1);
! 2606: for (i = 1; i < 5; i++) a[i] = e1[i]; a[5] = zero; a[6] = e1[5];
! 2607: prims = decomp(denom(a));
! 2608: p1 = (GEN)prims[1]; l = lg(p1);
! 2609: for (k = 1; k < l; k++)
! 2610: {
! 2611: int n = 0;
! 2612: for (i = 1; i < 7; i++)
! 2613: if (!gcmp0((GEN)a[i]))
! 2614: {
! 2615: m = i * n + ggval((GEN)a[i], (GEN)p1[k]);
! 2616: while (m < 0) { n++; m += i; }
! 2617: }
! 2618: u = gmul(u, gpuigs((GEN)p1[k], n));
! 2619: }
! 2620: v[1] = linv(u); v[2] = v[3] = v[4] = zero;
! 2621: for (i = 1; i < 14; i++) e[i] = e1[i];
! 2622: for (; i < 20; i++) e[i] = zero;
! 2623: if (!gcmp1(u)) e = coordch(e, v);
! 2624: prims = decomp((GEN)e[12]);
! 2625: l = lg(p1 = (GEN)prims[1]);
! 2626: for (k = (signe(e[12]) < 0) + 1; k < l; k++)
! 2627: {
! 2628: GEN q = localreduction(e, (GEN)p1[k]);
! 2629: GEN v1 = (GEN)q[3];
! 2630: N = mulii(N, gpui((GEN)p1[k],(GEN)q[1],0));
! 2631: c = mulii(c, (GEN)q[4]);
! 2632: if (!gcmp1((GEN)v1[1])) cumule1(&v, &e, v1);
! 2633: }
! 2634: s = gdiventgs((GEN)e[1], -2);
! 2635: r = gdiventgs(gaddgs(gsub(gsub((GEN)e[2], gmul(s,(GEN)e[1])), gsqr(s)), 1), -3);
! 2636: t = gdiventgs(ellLHS0(e,r), -2);
! 2637: cumule(&v, &e, gun, r, s, t);
! 2638: tetpil = avma;
! 2639: result = cgetg(4, t_VEC); result[1] = lcopy(N); result[2] = lcopy(v);
! 2640: result[3] = lcopy(c);
! 2641: return gerepile(av, tetpil, result);
! 2642: }
! 2643:
! 2644: /* cumule les effets de plusieurs chgts de variable. On traite a part les cas
! 2645: * particuliers frequents, tels que soit u = 1, soit r' = s' = t' = 0
! 2646: */
! 2647: static void
! 2648: cumulev(GEN *vtotal, GEN u, GEN r, GEN s, GEN t)
! 2649: {
! 2650: long av = avma, tetpil;
! 2651: GEN temp, v = *vtotal, v3 = cgetg(5, t_VEC);
! 2652: if (gcmp1((GEN)v[1]))
! 2653: {
! 2654: v3[1] = lcopy(u);
! 2655: v3[2] = ladd((GEN)v[2], r);
! 2656: v3[3] = ladd((GEN)v[3], s);
! 2657: av = avma;
! 2658: temp = gadd((GEN)v[4], gmul((GEN)v[3], r));
! 2659: tetpil = avma;
! 2660: v3[4] = lpile(av, tetpil, gadd(temp, t));
! 2661: }
! 2662: else if (gcmp0(r) && gcmp0(s) && gcmp0(t))
! 2663: {
! 2664: v3[1] = lmul((GEN)v[1], u);
! 2665: v3[2] = lcopy((GEN)v[2]);
! 2666: v3[3] = lcopy((GEN)v[3]);
! 2667: v3[4] = lcopy((GEN)v[4]);
! 2668: }
! 2669: else /* cas general */
! 2670: {
! 2671: v3[1] = lmul((GEN)v[1], u);
! 2672: temp = gsqr((GEN)v[1]);
! 2673: v3[2] = ladd(gmul(temp, r), (GEN)v[2]);
! 2674: v3[3] = ladd(gmul((GEN)v[1], s), (GEN)v[3]);
! 2675: v3[4] = ladd((GEN)v[4], gmul(temp, gadd(gmul((GEN)v[1], t), gmul((GEN)v[3], r))));
! 2676:
! 2677: tetpil = avma;
! 2678: v3 = gerepile(av, tetpil, gcopy(v3));
! 2679: }
! 2680: *vtotal = v3;
! 2681: }
! 2682:
! 2683: static void
! 2684: cumule(GEN *vtotal, GEN *e, GEN u, GEN r, GEN s, GEN t)
! 2685: {
! 2686: long av = avma, tetpil;
! 2687: GEN v2 = cgetg(5, t_VEC);
! 2688: v2[1] = (long)u; v2[2] = (long)r; v2[3] = (long)s; v2[4] = (long)t;
! 2689: tetpil = avma;
! 2690: *e = gerepile(av, tetpil, coordch(*e, v2));
! 2691: cumulev(vtotal, u, r, s, t);
! 2692: }
! 2693:
! 2694: static void
! 2695: cumule1(GEN *vtotal, GEN *e, GEN v2)
! 2696: {
! 2697: *e = coordch(*e, v2);
! 2698: cumulev(vtotal, (GEN)v2[1], (GEN)v2[2], (GEN)v2[3], (GEN)v2[4]);
! 2699: }
! 2700:
! 2701: /********************************************************************/
! 2702: /** **/
! 2703: /** Parametrisation modulaire **/
! 2704: /** **/
! 2705: /********************************************************************/
! 2706:
! 2707: GEN
! 2708: taniyama(GEN e)
! 2709: {
! 2710: GEN v,w,c,d,s1,s2,s3;
! 2711: long n,m,av=avma,tetpil;
! 2712:
! 2713: checkell(e); v = cgetg(precdl+3,t_SER);
! 2714: v[1] = evalsigne(1) | evalvalp(-2) | evalvarn(0);
! 2715: v[2] = un;
! 2716: c=gtoser(anell(e,precdl+1),0); setvalp(c,1);
! 2717: d=ginv(c); c=gsqr(d);
! 2718: for (n=-3; n<=precdl-4; n++)
! 2719: {
! 2720: if (n!=2)
! 2721: {
! 2722: s3=n?gzero:(GEN)e[7];
! 2723: if (n>-3) s3=gadd(s3,gmul((GEN)e[6],(GEN)v[n+4]));
! 2724: s2=gzero;
! 2725: for (m=-2; m<=n+1; m++)
! 2726: s2 = gadd(s2,gmulsg(m*(n+m),gmul((GEN)v[m+4],(GEN)c[n-m+4])));
! 2727: s2=gmul2n(s2,-1);
! 2728: s1=gzero;
! 2729: for (m=-1; m+m<=n; m++)
! 2730: {
! 2731: if (m+m==n)
! 2732: s1=gadd(s1,gsqr((GEN)v[m+4]));
! 2733: else
! 2734: s1=gadd(s1,gmul2n(gmul((GEN)v[m+4],(GEN)v[n-m+4]),1));
! 2735: }
! 2736: v[n+6]=ldivgs(gsub(gadd(gmulsg(6,s1),s3),s2),(n+2)*(n+1)-12);
! 2737: }
! 2738: else
! 2739: {
! 2740: setlg(v,9); v[8]=(long)polx[MAXVARN];
! 2741: w=deriv(v,0); setvalp(w,-2);
! 2742: s1=gadd((GEN)e[8],gmul(v,gadd(gmul2n((GEN)e[7],1),gmul(v,gadd((GEN)e[6],gmul2n(v,2))))));
! 2743: setlg(v,precdl+3);
! 2744: s2=gsub(s1,gmul(c,gsqr(w)));
! 2745: s2=gsubst((GEN)s2[2],MAXVARN,polx[0]);
! 2746: v[n+6]=lneg(gdiv((GEN)s2[2],(GEN)s2[3]));
! 2747: }
! 2748: }
! 2749: w=gsub(gmul(polx[0],gmul(d,deriv(v,0))), ellLHS0(e,v));
! 2750: tetpil=avma; s1=cgetg(3,t_VEC); s1[1]=lcopy(v); s1[2]=lmul2n(w,-1);
! 2751: return gerepile(av,tetpil,s1);
! 2752: }
! 2753:
! 2754: /********************************************************************/
! 2755: /** **/
! 2756: /** TORSION POINTS (over Q) **/
! 2757: /** **/
! 2758: /********************************************************************/
! 2759: /* assume e is defined over Q (use Mazur's theorem) */
! 2760: GEN
! 2761: orderell(GEN e, GEN p)
! 2762: {
! 2763: GEN p1;
! 2764: long av=avma,k;
! 2765:
! 2766: checkell(e); checkpt(p);
! 2767: k=typ(e[13]);
! 2768: if (k!=t_INT && !is_frac_t(k))
! 2769: err(impl,"orderell for nonrational elliptic curves");
! 2770: p1=p; k=1;
! 2771: for (k=1; k<16; k++)
! 2772: {
! 2773: if (lg(p1)<3) { avma=av; return stoi(k); }
! 2774: p1 = addell(e,p1,p);
! 2775: }
! 2776: avma=av; return gzero;
! 2777: }
! 2778:
! 2779: /* one can do much better by factoring denom(D) (see ellglobalred) */
! 2780: static GEN
! 2781: ellintegralmodel(GEN e)
! 2782: {
! 2783: GEN a = cgetg(6,t_VEC), v;
! 2784: long i;
! 2785:
! 2786: for (i=1; i<6; i++) a[i]=e[i];
! 2787: a = denom(a); if (gcmp1(a)) return NULL;
! 2788: v = cgetg(5,t_VEC);
! 2789: v[1]=linv(a); v[2]=v[3]=v[4]=zero; return v;
! 2790: }
! 2791:
! 2792: /* Using Lutz-Nagell */
! 2793:
! 2794: /* p is a polynomial of degree exactly 3 with integral coefficients
! 2795: * and leading term 4. Outputs the vector of rational roots of p
! 2796: */
! 2797: static GEN
! 2798: ratroot(GEN p)
! 2799: {
! 2800: GEN v,a,ld;
! 2801: long i,t;
! 2802:
! 2803: i=2; while (!signe(p[i])) i++;
! 2804: if (i==5)
! 2805: { v=cgetg(2,t_VEC); v[1]=zero; return v; }
! 2806: if (i==4)
! 2807: { v=cgetg(3,t_VEC); v[1]=zero; v[2]=ldivgs((GEN)p[4],-4); return v; }
! 2808:
! 2809: v=cgetg(4,t_VEC); t=1;
! 2810: if (i==3) v[t++]=zero;
! 2811: ld=divisors(gmul2n((GEN)p[i],2));
! 2812: for (i=1; i<lg(ld); i++)
! 2813: {
! 2814: a = gmul2n((GEN)ld[i],-2);
! 2815: if (!gsigne(poleval(p,a))) v[t++]=(long)a;
! 2816: a = gneg_i(a);
! 2817: if (!gsigne(poleval(p,a))) v[t++]=(long)a;
! 2818: }
! 2819: setlg(v,t); return v;
! 2820: }
! 2821:
! 2822: static int
! 2823: is_new_torsion(GEN e, GEN v, GEN p, long t2) {
! 2824: GEN pk = p, pkprec = NULL;
! 2825: long k,l;
! 2826:
! 2827: for (k=2; k<=6; k++)
! 2828: {
! 2829: pk=addell(e,pk,p);
! 2830: if (lg(pk)==2) return 1;
! 2831:
! 2832: for (l=2; l<=t2; l++)
! 2833: if (gegal((GEN)pk[1],gmael(v,l,1))) return 1;
! 2834:
! 2835: if (pkprec && k<=5)
! 2836: if (gegal((GEN)pk[1],(GEN)pkprec[1])) return 1;
! 2837: pkprec=pk;
! 2838: }
! 2839: return 0;
! 2840: }
! 2841:
! 2842: GEN
! 2843: torsellnagelllutz(GEN e)
! 2844: {
! 2845: GEN d,ld,pol,p1,lr,r,v,w,w2,w3;
! 2846: long i,j,nlr,t,t2,k,k2,av=avma;
! 2847:
! 2848: checkell(e);
! 2849: v = ellintegralmodel(e);
! 2850: if (v) e = coordch(e,v);
! 2851: pol = RHSpol(e);
! 2852: lr=ratroot(pol); nlr=lg(lr)-1;
! 2853: r=cgetg(17,t_VEC); p1=cgetg(2,t_VEC); p1[1]=zero; r[1]=(long)p1;
! 2854: for (t=1,i=1; i<=nlr; i++)
! 2855: {
! 2856: p1=cgetg(3,t_VEC);
! 2857: p1[1] = lr[i];
! 2858: p1[2] = lmul2n(gneg(ellLHS0(e,(GEN)lr[i])), -1);
! 2859: r[++t]=(long)p1;
! 2860: }
! 2861: ld = factor(gmul2n(absi((GEN)e[12]), 4));
! 2862: p1 = (GEN)ld[2]; k = lg(p1);
! 2863: for (i=1; i<k; i++) p1[i] = lshifti((GEN)p1[i], -1);
! 2864: ld = divisors(ld);
! 2865: for (t2=t,j=1; j<lg(ld); j++)
! 2866: {
! 2867: d=(GEN)ld[j]; lr=ratroot(gsub(pol,gsqr(d)));
! 2868: for (i=1; i<lg(lr); i++)
! 2869: {
! 2870: p1 = cgetg(3,t_VEC);
! 2871: p1[1] = lr[i];
! 2872: p1[2] = lmul2n(gsub(d,ellLHS0(e,(GEN)lr[i])), -1);
! 2873:
! 2874: if (is_new_torsion(e,r,p1,t2))
! 2875: {
! 2876: GEN p2 = cgetg(3,t_VEC);
! 2877: p2[1] = p1[1];
! 2878: p2[2] = lsub((GEN)p1[2],d);
! 2879: r[++t]=(long)p1;
! 2880: r[++t]=(long)p2;
! 2881: }
! 2882: }
! 2883: }
! 2884: if (t==1)
! 2885: {
! 2886: avma=av; w=cgetg(4,t_VEC);
! 2887: w[1] = un;
! 2888: w[2] = lgetg(1,t_VEC);
! 2889: w[3] = lgetg(1,t_VEC);
! 2890: return w;
! 2891: }
! 2892:
! 2893: if (nlr<3)
! 2894: {
! 2895: w2=cgetg(2,t_VEC); w2[1]=lstoi(t);
! 2896: for (k=2; k<=t; k++)
! 2897: if (itos(orderell(e,(GEN)r[k])) == t) break;
! 2898: if (k>t) err(bugparier,"torsell (bug1)");
! 2899:
! 2900: w3=cgetg(2,t_VEC); w3[1]=r[k];
! 2901: }
! 2902: else
! 2903: {
! 2904: if (t&3) err(bugparier,"torsell (bug2)");
! 2905: t2 = t>>1;
! 2906: w2=cgetg(3,t_VEC); w2[1]=lstoi(t2); w2[2]=(long)gdeux;
! 2907: for (k=2; k<=t; k++)
! 2908: if (itos(orderell(e,(GEN)r[k])) == t2) break;
! 2909: if (k>t) err(bugparier,"torsell (bug3)");
! 2910:
! 2911: p1 = powell(e,(GEN)r[k],stoi(t>>2));
! 2912: k2 = (lg(p1)==3 && gegal((GEN)r[2],p1))? 3: 2;
! 2913: w3=cgetg(3,t_VEC); w3[1]=r[k]; w3[2]=r[k2];
! 2914: }
! 2915: if (v)
! 2916: {
! 2917: v[1] = linv((GEN)v[1]);
! 2918: w3 = pointch(w3,v);
! 2919: }
! 2920: w=cgetg(4,t_VEC);
! 2921: w[1] = lstoi(t);
! 2922: w[2] = (long)w2;
! 2923: w[3] = (long)w3;
! 2924: return gerepileupto(av, gcopy(w));
! 2925: }
! 2926:
! 2927: /* Using Doud's algorithm */
! 2928:
! 2929: /* Input e and n, finds a bound for #Tor */
! 2930: static long
! 2931: torsbound(GEN e, long n)
! 2932: {
! 2933: long av = avma, m, b, c, d, prime = 2;
! 2934: byteptr p = diffptr;
! 2935: GEN D = (GEN)e[12];
! 2936:
! 2937: b = c = m = 0; p++;
! 2938: while (m<n)
! 2939: {
! 2940: d = *p++; if (!d) err(primer1);
! 2941: prime += d;
! 2942: if (ggval(D,stoi(prime)) == 0)
! 2943: {
! 2944: b = cgcd(b, prime+1 - itos(apell0(e,prime)));
! 2945: if (b==c) m++; else {c = b; m = 0;}
! 2946: avma = av;
! 2947: }
! 2948: }
! 2949: return b;
! 2950: }
! 2951:
! 2952: static GEN
! 2953: _round(GEN x, long *e)
! 2954: {
! 2955: GEN y = grndtoi(x,e);
! 2956: if (*e > -5 && bit_accuracy(gprecision(x)) < gexpo(y) - 10)
! 2957: err(talker, "ellinit data not accurate enough. Increase precision");
! 2958: return y;
! 2959: }
! 2960:
! 2961: /* Input the curve, a point, and an integer n, returns a point of order n
! 2962: on the curve, or NULL if q is not rational. */
! 2963: static GEN
! 2964: torspnt(GEN E, GEN q, long n)
! 2965: {
! 2966: GEN p = cgetg(3,t_VEC);
! 2967: long e;
! 2968: p[1] = lmul2n(_round(gmul2n((GEN)q[1],2), &e),-2);
! 2969: if (e > -5) return NULL;
! 2970: p[2] = lmul2n(_round(gmul2n((GEN)q[2],3), &e),-3);
! 2971: if (e > -5) return NULL;
! 2972: return (gcmp0(gimag(p)) && oncurve(E,p)
! 2973: && lg(powell(E,p,stoi(n))) == 2
! 2974: && itos(orderell(E,p)) == n)? greal(p): NULL;
! 2975: }
! 2976:
! 2977: static int
! 2978: smaller_x(GEN p, GEN q)
! 2979: {
! 2980: int s = absi_cmp(denom(p), denom(q));
! 2981: return (s<0 || (s==0 && absi_cmp(numer(p),numer(q)) < 0));
! 2982: }
! 2983:
! 2984: /* best generator in cycle of length k */
! 2985: static GEN
! 2986: best_in_cycle(GEN e, GEN p, long k)
! 2987: {
! 2988: GEN p0 = p,q = p;
! 2989: long i;
! 2990:
! 2991: for (i=2; i+i<k; i++)
! 2992: {
! 2993: q = addell(e,q,p0);
! 2994: if (cgcd(i,k)==1 && smaller_x((GEN)q[1], (GEN)p[1])) p = q;
! 2995: }
! 2996: return (gsigne(d_ellLHS(e,p)) < 0)? invell(e,p): p;
! 2997: }
! 2998:
! 2999: static GEN
! 3000: tors(GEN e, long k, GEN p, GEN q, GEN v)
! 3001: {
! 3002: GEN p1,r;
! 3003: if (q)
! 3004: {
! 3005: long n = k>>1;
! 3006: GEN p1, best = q, np = powell(e,p,stoi(n));
! 3007: if (n % 2 && smaller_x((GEN)np[1], (GEN)best[1])) best = np;
! 3008: p1 = addell(e,q,np);
! 3009: if (smaller_x((GEN)p1[1], (GEN)best[1])) q = p1;
! 3010: else if (best == np) { p = addell(e,p,q); q = np; }
! 3011: p = best_in_cycle(e,p,k);
! 3012: if (v)
! 3013: {
! 3014: v[1] = linv((GEN)v[1]);
! 3015: p = pointch(p,v);
! 3016: q = pointch(q,v);
! 3017: }
! 3018: r = cgetg(4,t_VEC);
! 3019: r[1] = lstoi(2*k); p1 = cgetg(3,t_VEC); p1[1] = lstoi(k); p1[2] = deux;
! 3020: r[2] = (long)p1; p1 = cgetg(3,t_VEC); p1[1] = lcopy(p); p1[2] = lcopy(q);
! 3021: r[3] = (long)p1;
! 3022: }
! 3023: else
! 3024: {
! 3025: if (p)
! 3026: {
! 3027: p = best_in_cycle(e,p,k);
! 3028: if (v)
! 3029: {
! 3030: v[1] = linv((GEN)v[1]);
! 3031: p = pointch(p,v);
! 3032: }
! 3033: r = cgetg(4,t_VEC);
! 3034: r[1] = lstoi(k); p1 = cgetg(2,t_VEC); p1[1] = r[1];
! 3035: r[2] = (long)p1; p1 = cgetg(2,t_VEC); p1[1] = lcopy(p);
! 3036: r[3] = (long)p1;
! 3037: }
! 3038: else
! 3039: {
! 3040: r = cgetg(4,t_VEC);
! 3041: r[1] = un;
! 3042: r[2] = lgetg(1,t_VEC);
! 3043: r[3] = lgetg(1,t_VEC);
! 3044: }
! 3045: }
! 3046: return r;
! 3047: }
! 3048:
! 3049: GEN
! 3050: torselldoud(GEN e)
! 3051: {
! 3052: long b,i,ord,av=avma,prec, k = 1;
! 3053: GEN v,w1,w22,w1j,w12,p,tor1,tor2;
! 3054:
! 3055: checkbell(e);
! 3056: v = ellintegralmodel(e);
! 3057: if (v) e = coordch(e,v);
! 3058:
! 3059: prec=precision((GEN)e[15]);
! 3060: prec=max(prec,MEDDEFAULTPREC);
! 3061: b = torsbound(e,3);
! 3062: if (b==1) { avma=av; return tors(e,1,NULL,NULL, v); }
! 3063: w22 = gmul2n((GEN)e[16],-1);
! 3064: w1 = (GEN)e[15];
! 3065: if (b % 4)
! 3066: {
! 3067: for (i=10; i>1; i--)
! 3068: {
! 3069: if (b%i==0)
! 3070: {
! 3071: w1j = gdivgs(w1,i);
! 3072: p = torspnt(e,pointell(e,w1j,prec),i);
! 3073: if (i%2==0 && p==NULL)
! 3074: {
! 3075: p = torspnt(e,pointell(e,gadd(w22,w1j),prec),i);
! 3076: if (p==NULL)
! 3077: p = torspnt(e,pointell(e,gadd(w22,gmul2n(w1j,1)),prec),i);
! 3078: }
! 3079: }
! 3080: else p = NULL;
! 3081: if (p) {k = i; break; }
! 3082: }
! 3083: return gerepileupto(av, tors(e,k,p,NULL, v));
! 3084: }
! 3085:
! 3086: ord = 0; tor2 = NULL;
! 3087: w12 = gmul2n((GEN)e[15],-1);
! 3088: if ((p = torspnt(e,pointell(e,w12,prec),2)))
! 3089: {
! 3090: tor1 = p; ord++;
! 3091: }
! 3092: if ((p = torspnt(e,pointell(e,w22,prec),2))
! 3093: || (!ord && (p = torspnt(e,pointell(e,gadd(w12,w22),prec),2))))
! 3094: {
! 3095: tor2 = p; ord += 2;
! 3096: }
! 3097:
! 3098: switch(ord)
! 3099: {
! 3100: case 0:
! 3101: for (i=9; i>1; i-=2)
! 3102: {
! 3103: w1j=gdivgs((GEN)e[15],i);
! 3104: p = (b%i==0)? torspnt(e,pointell(e,w1j,prec),i): NULL;
! 3105: if (p) { k = i; break; }
! 3106: }
! 3107: break;
! 3108:
! 3109: case 1:
! 3110: for (i=12; i>2; i-=2)
! 3111: {
! 3112: w1j=gdivgs((GEN)e[15],i);
! 3113: if (b%i==0)
! 3114: {
! 3115: p = torspnt(e,pointell(e,w1j,prec),i);
! 3116: if (i%4==0 && p==NULL)
! 3117: p = torspnt(e,pointell(e,gadd(w22,w1j),prec),i);
! 3118: }
! 3119: else p = NULL;
! 3120: if (p) { k = i; break; }
! 3121: }
! 3122: if (!p) { p = tor1; k = 2; }
! 3123: break;
! 3124:
! 3125: case 2:
! 3126: for (i=5; i>1; i-=2)
! 3127: {
! 3128: w1j = gdivgs((GEN)e[15],i);
! 3129: p = (b%i==0)? torspnt(e,pointell(e,gadd(w22,w1j),prec),i+i): NULL;
! 3130: if (p) { k = i+i; break; }
! 3131: }
! 3132: if (!p) { p = tor2; k = 2; }
! 3133: tor2 = NULL; break;
! 3134:
! 3135: case 3:
! 3136: for (i=8; i>2; i-=2)
! 3137: {
! 3138: w1j=gdivgs((GEN)e[15],i);
! 3139: p = (b%(2*i)==0)? torspnt(e,pointell(e,w1j,prec),i): NULL;
! 3140: if (p) { k = i; break; }
! 3141: }
! 3142: if (!p) { p = tor1; k = 2; }
! 3143: break;
! 3144: }
! 3145: return gerepileupto(av, tors(e,k,p,tor2, v));
! 3146: }
! 3147:
! 3148: GEN
! 3149: elltors0(GEN e, long flag)
! 3150: {
! 3151: switch(flag)
! 3152: {
! 3153: case 0: return torselldoud(e);
! 3154: case 1: return torsellnagelllutz(e);
! 3155: default: err(flagerr,"torsell");
! 3156: }
! 3157: return NULL; /* not reached */
! 3158: }
! 3159:
! 3160: /* par compatibilite */
! 3161: GEN torsell(GEN e) {return torselldoud(e);}
! 3162:
! 3163: /* LOCAL ROOT NUMBERS, D'APRES HALBERSTADT halberst@math.jussieu.fr */
! 3164:
! 3165: /* ici p=2 ou 3 */
! 3166: static long
! 3167: neron(GEN e, GEN p, long* ptkod)
! 3168: {
! 3169: long av=avma,kod,v4,v6,vd;
! 3170: GEN c4, c6, d, nv;
! 3171:
! 3172: nv=localreduction(e,p);
! 3173: kod=itos((GEN)nv[2]); *ptkod=kod;
! 3174: c4=(GEN)e[10]; c6=(GEN)e[11]; d=(GEN)e[12];
! 3175: v4=gcmp0(c4) ? 12 : ggval(c4,p);
! 3176: v6=gcmp0(c6) ? 12 : ggval(c6,p);
! 3177: vd=ggval(d,p);
! 3178: avma=av;
! 3179: switch(itos(p))
! 3180: {
! 3181: case 3:
! 3182: if (labs(kod)>4) return 1;
! 3183: else
! 3184: {
! 3185: switch(kod)
! 3186: {
! 3187: case -1: case 1: return v4&1 ? 2 : 1;
! 3188: case -3: case 3: return (2*v6>vd+3) ? 2 : 1;
! 3189: case -4: case 2:
! 3190: switch (vd%6)
! 3191: {
! 3192: case 4: return 3;
! 3193: case 5: return 4;
! 3194: default: return v6%3==1 ? 2 : 1;
! 3195: }
! 3196: default: /* kod = -2 et 4 */
! 3197: switch (vd%6)
! 3198: {
! 3199: case 0: return 2;
! 3200: case 1: return 3;
! 3201: default: return 1;
! 3202: }
! 3203: }
! 3204: }
! 3205: case 2:
! 3206: if (kod>4) return 1;
! 3207: else
! 3208: {
! 3209: switch(kod)
! 3210: {
! 3211: case 1: return (v6>0) ? 2 : 1;
! 3212: case 2:
! 3213: if (vd==4) return 1;
! 3214: else
! 3215: {
! 3216: if (vd==7) return 3;
! 3217: else return v4==4 ? 2 : 4;
! 3218: }
! 3219: case 3:
! 3220: switch(vd)
! 3221: {
! 3222: case 6: return 3;
! 3223: case 8: return 4;
! 3224: case 9: return 5;
! 3225: default: return v4==5 ? 2 : 1;
! 3226: }
! 3227: case 4: return v4>4 ? 2 : 1;
! 3228: case -1:
! 3229: switch(vd)
! 3230: {
! 3231: case 9: return 2;
! 3232: case 10: return 4;
! 3233: default: return v4>4 ? 3 : 1;
! 3234: }
! 3235: case -2:
! 3236: switch(vd)
! 3237: {
! 3238: case 12: return 2;
! 3239: case 14: return 3;
! 3240: default: return 1;
! 3241: }
! 3242: case -3:
! 3243: switch(vd)
! 3244: {
! 3245: case 12: return 2;
! 3246: case 14: return 3;
! 3247: case 15: return 4;
! 3248: default: return 1;
! 3249: }
! 3250: case -4: return v6==7 ? 2 : 1;
! 3251: case -5: return (v6==7 || v4==6) ? 2 : 1;
! 3252: case -6:
! 3253: switch(vd)
! 3254: {
! 3255: case 12: return 2;
! 3256: case 13: return 3;
! 3257: default: return v4==6 ? 2 : 1;
! 3258: }
! 3259: case -7: return (vd==12 || v4==6) ? 2 : 1;
! 3260: default: return v4==6 ? 2 : 1;
! 3261: }
! 3262: }
! 3263: default: return 0; /* should not occur */
! 3264: }
! 3265: }
! 3266:
! 3267: static long
! 3268: ellrootno_2(GEN e)
! 3269: {
! 3270: long n2,kod,u,v,x1,y1,d1,av=avma,v4,v6,w2;
! 3271: GEN p=gdeux,c4,c6,tmp,p6;
! 3272:
! 3273: n2=neron(e,p,&kod); c4=(GEN)e[10]; c6=(GEN)e[11]; p6=stoi(64);
! 3274: if (gcmp0(c4)) {v4=12; u=0;}
! 3275: else {v4=pvaluation(c4,p,&tmp); u=itos(modii(tmp,p6));}
! 3276: if (gcmp0(c6)) {v6=12; v=0;}
! 3277: else {v6=pvaluation(c6,p,&tmp); v=itos(modii(tmp,p6));}
! 3278: (void)pvaluation((GEN)e[12],p,&tmp); d1=itos(modii(tmp,p6));
! 3279: avma=av; x1=u+v+v;
! 3280: if (kod>=5)
! 3281: {w2=mpodd(addii((GEN)e[2],(GEN)e[3])) ? 1 : -1; avma=av; return w2;}
! 3282: if (kod<-9) return (n2==2) ? -kross(-1,v) : -1;
! 3283: switch(kod)
! 3284: {
! 3285: case 1: return 1;
! 3286: case 2:
! 3287: switch(n2)
! 3288: {
! 3289: case 1:
! 3290: switch(v4)
! 3291: {
! 3292: case 4: return kross(-1,u);
! 3293: case 5: return 1;
! 3294: default: return -1;
! 3295: }
! 3296: case 2: return (v6==7) ? 1 : -1;
! 3297: case 3: return (v%8==5 || (u*v)%8==5) ? 1 : -1;
! 3298: case 4: if (v4>5) return kross(-1,v);
! 3299: return (v4==5) ? -kross(-1,u) : -1;
! 3300: }
! 3301: case 3:
! 3302: switch(n2)
! 3303: {
! 3304: case 1: return -kross(2,u*v);
! 3305: case 2: return -kross(2,v);
! 3306: case 3: y1=itos(modis(gsubsg(u,gmul2n(c6,-5)),16)); avma=av;
! 3307: return (y1==7 || y1==11) ? 1 : -1;
! 3308: case 4: return (v%8==3 || (2*u+v)%8==7) ? 1 : -1;
! 3309: case 5: return v6==8 ? kross(2,x1) : kross(-2,u);
! 3310: }
! 3311: case -1:
! 3312: switch(n2)
! 3313: {
! 3314: case 1: return -kross(2,x1);
! 3315: case 2: return (v%8==7) || (x1%32==11) ? 1 : -1;
! 3316: case 3: return v4==6 ? 1 : -1;
! 3317: case 4: if (v4>6) return kross(-1,v);
! 3318: return v4==6 ? -kross(-1,u*v) : -1;
! 3319: }
! 3320: case -2: return n2==1 ? kross(-2,v) : kross(-1,v);
! 3321: case -3:
! 3322: switch(n2)
! 3323: {
! 3324: case 1: y1=(u-2*v)%64; if (y1<0) y1+=64;
! 3325: return (y1==3) || (y1==19) ? 1 : -1;
! 3326: case 2: return kross(2*kross(-1,u),v);
! 3327: case 3: return -kross(-1,u)*kross(-2*kross(-1,u),u*v);
! 3328: case 4: return v6==11 ? kross(-2,x1) : -kross(-2,u);
! 3329: }
! 3330: case -5:
! 3331: if (n2==1) return x1%32==23 ? 1 : -1;
! 3332: else return -kross(2,2*u+v);
! 3333: case -6:
! 3334: switch(n2)
! 3335: {
! 3336: case 1: return 1;
! 3337: case 2: return v6==10 ? 1 : -1;
! 3338: case 3: return (u%16==11) || ((u+4*v)%16==3) ? 1 : -1;
! 3339: }
! 3340: case -7:
! 3341: if (n2==1) return 1;
! 3342: else
! 3343: {
! 3344: y1=itos(modis(gaddsg(u,gmul2n(c6,-8)),16)); avma=av;
! 3345: if (v6==10) return (y1==9) || (y1==13) ? 1 : -1;
! 3346: else return (y1==9) || (y1==5) ? 1 : -1;
! 3347: }
! 3348: case -8: return n2==2 ? kross(-1,v*d1) : -1;
! 3349: case -9: return n2==2 ? -kross(-1,d1) : -1;
! 3350: default: return -1;
! 3351: }
! 3352: }
! 3353:
! 3354: static long
! 3355: ellrootno_3(GEN e)
! 3356: {
! 3357: long n2,kod,u,v,d1,av=avma,r6,k4,k6,v4;
! 3358: GEN p=stoi(3),c4,c6,tmp,p4;
! 3359:
! 3360: n2=neron(e,p,&kod); c4=(GEN)e[10]; c6=(GEN)e[11]; p4=stoi(81);
! 3361: if (gcmp0(c4)) { v4=12; u=0; }
! 3362: else { v4=pvaluation(c4,p,&tmp); u=itos(modii(tmp,p4)); }
! 3363: if (gcmp0(c6)) v=0;
! 3364: else {(void)pvaluation(c6,p,&tmp); v=itos(modii(tmp,p4));}
! 3365: (void)pvaluation((GEN)e[12],p,&tmp); d1=itos(modii(tmp,p4));
! 3366: avma=av;
! 3367: r6=v%9; k4=kross(u,3); k6=kross(v,3);
! 3368: if (kod>4) return k6;
! 3369: switch(kod)
! 3370: {
! 3371: case 1: case 3: case -3: return 1;
! 3372: case 2:
! 3373: switch(n2)
! 3374: {
! 3375: case 1: return (r6==4 || r6>6) ? 1 : -1;
! 3376: case 2: return -k4*k6;
! 3377: case 3: return 1;
! 3378: case 4: return -k6;
! 3379: }
! 3380: case 4:
! 3381: switch(n2)
! 3382: {
! 3383: case 1: return k6*kross(d1,3);
! 3384: case 2: return -k4;
! 3385: case 3: return -k6;
! 3386: }
! 3387: case -2: return n2==2 ? 1 : k6;
! 3388: case -4:
! 3389: switch(n2)
! 3390: {
! 3391: case 1:
! 3392: if (v4==4) return (r6==4 || r6==8) ? 1 : -1;
! 3393: else return (r6==1 || r6==2) ? 1 : -1;
! 3394: case 2: return -k6;
! 3395: case 3: return (r6==2 || r6==7) ? 1 : -1;
! 3396: case 4: return k6;
! 3397: }
! 3398: default: return -1;
! 3399: }
! 3400: }
! 3401:
! 3402: static long
! 3403: ellrootno_not23(GEN e, GEN p, GEN ex)
! 3404: {
! 3405: GEN j;
! 3406: long ep,z;
! 3407:
! 3408: if (gcmp1(ex)) return -kronecker(negi((GEN)e[11]),p);
! 3409: j=(GEN)e[13];
! 3410: if (!gcmp0(j) && ggval(j,p) < 0) return kronecker(negi(gun),p);
! 3411: ep=12/cgcd(12,ggval((GEN)e[12],p));
! 3412: if (ep==4) z=2;
! 3413: else z=(ep%2==0) ? 1 : 3;
! 3414: return kronecker(stoi(-z),p);
! 3415: }
! 3416:
! 3417: static long
! 3418: ellrootno_intern(GEN e, GEN p, GEN ex)
! 3419: {
! 3420: if (cmpis(p,3) > 0) return ellrootno_not23(e,p,ex);
! 3421: switch(itos(p))
! 3422: {
! 3423: case 3: return ellrootno_3(e);
! 3424: case 2: return ellrootno_2(e);
! 3425: default: err(talker,"incorrect prime in ellrootno_intern");
! 3426: }
! 3427: return 0; /* not reached */
! 3428: }
! 3429:
! 3430: /* local epsilon factor at p, including p=0 for the infinite place. Global
! 3431: if p==1. The equation can be non minimal, but must be over Q. Internal,
! 3432: no garbage collection. */
! 3433: static long
! 3434: ellrootno_all(GEN e, GEN p, GEN* ptcond)
! 3435: {
! 3436: long s,exs,i;
! 3437: GEN fa,gr,cond,pr,ex;
! 3438:
! 3439: gr=globalreduction(e);
! 3440: e=coordch(e,(GEN)gr[2]);
! 3441: cond=(GEN)gr[1]; if(ptcond) *ptcond=cond;
! 3442: if (typ(e[12]) != t_INT)
! 3443: err(talker,"not an integral curve in ellrootno");
! 3444: if (typ(p) != t_INT || signe(p)<0)
! 3445: err(talker,"not a nonnegative integer second arg in ellrootno");
! 3446: if (cmpis(p,2)>=0)
! 3447: {
! 3448: exs=ggval(cond,p);
! 3449: if (!exs) return 1;
! 3450: }
! 3451: if (cmpis(p,3)>0) return ellrootno_not23(e,p,stoi(exs));
! 3452: switch(itos(p))
! 3453: {
! 3454: case 3: return ellrootno_3(e);
! 3455: case 2: return ellrootno_2(e);
! 3456: case 1: s=-1; fa=factor(cond); pr=(GEN)fa[1]; ex=(GEN)fa[2];
! 3457: for (i=1; i<lg(pr); i++) s*=ellrootno_intern(e,(GEN)pr[i],(GEN)ex[i]);
! 3458: return s;
! 3459: case 0: return -1; /* local factor at infinity = -1 */
! 3460: default: return 0; /* never reached */
! 3461: }
! 3462: }
! 3463:
! 3464: long
! 3465: ellrootno(GEN e, GEN p)
! 3466: {
! 3467: long av=avma,s;
! 3468: if (!p) p = gun;
! 3469: s=ellrootno_all(e, p, NULL);
! 3470: avma=av; return s;
! 3471: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>