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