Line data Source code
1 : /* Copyright (C) 2000 The PARI group.
2 :
3 : This file is part of the PARI/GP package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 2 of the License, or (at your option) any later
8 : version. It is distributed in the hope that it will be useful, but WITHOUT
9 : ANY WARRANTY WHATSOEVER.
10 :
11 : Check the License for details. You should have received a copy of it, along
12 : with the package; see the file 'COPYING'. If not, write to the Free Software
13 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14 :
15 : /********************************************************************/
16 : /** **/
17 : /** TORSION OF ELLIPTIC CURVES over NUMBER FIELDS **/
18 : /** **/
19 : /********************************************************************/
20 : #include "pari.h"
21 : #include "paripriv.h"
22 : static int
23 560 : smaller_x(GEN p, GEN q)
24 : {
25 560 : int s = abscmpii(denom_i(p), denom_i(q));
26 560 : return (s<0 || (s==0 && abscmpii(numer_i(p),numer_i(q)) < 0));
27 : }
28 :
29 : /* best generator in cycle of length k */
30 : static GEN
31 623 : best_in_cycle(GEN e, GEN p, long k)
32 : {
33 623 : GEN p0 = p,q = p;
34 : long i;
35 :
36 931 : for (i=2; i+i<k; i++)
37 : {
38 308 : q = elladd(e,q,p0);
39 308 : if (ugcd(i,k)==1 && smaller_x(gel(q,1), gel(p,1))) p = q;
40 : }
41 623 : return (gsigne(ec_dmFdy_evalQ(e,p)) < 0)? ellneg(e,p): p;
42 : }
43 :
44 : /* <p,q> = E_tors, possibly NULL (= oo), p,q independent unless NULL
45 : * order p = k, order q = 2 unless NULL */
46 : static GEN
47 2149 : tors(GEN e, long k, GEN p, GEN q, GEN v)
48 : {
49 : GEN r;
50 2149 : if (q)
51 : {
52 259 : long n = k>>1;
53 259 : GEN p1, best = q, np = ellmul(e,p,utoipos(n));
54 259 : if (n % 2 && smaller_x(gel(np,1), gel(best,1))) best = np;
55 259 : p1 = elladd(e,q,np);
56 259 : if (smaller_x(gel(p1,1), gel(best,1))) q = p1;
57 238 : else if (best == np) { p = elladd(e,p,q); q = np; }
58 259 : p = best_in_cycle(e,p,k);
59 259 : if (v)
60 : {
61 0 : p = ellchangepointinv(p,v);
62 0 : q = ellchangepointinv(q,v);
63 : }
64 259 : r = cgetg(4,t_VEC);
65 259 : gel(r,1) = utoipos(2*k);
66 259 : gel(r,2) = mkvec2(utoipos(k), gen_2);
67 259 : gel(r,3) = mkvec2copy(p, q);
68 : }
69 : else
70 : {
71 1890 : if (p)
72 : {
73 364 : p = best_in_cycle(e,p,k);
74 364 : if (v) p = ellchangepointinv(p,v);
75 364 : r = cgetg(4,t_VEC);
76 364 : gel(r,1) = utoipos(k);
77 364 : gel(r,2) = mkvec( gel(r,1) );
78 364 : gel(r,3) = mkvec( gcopy(p) );
79 : }
80 : else
81 : {
82 1526 : r = cgetg(4,t_VEC);
83 1526 : gel(r,1) = gen_1;
84 1526 : gel(r,2) = cgetg(1,t_VEC);
85 1526 : gel(r,3) = cgetg(1,t_VEC);
86 : }
87 : }
88 2149 : return r;
89 : }
90 :
91 : /* Finds a multiplicative upper bound for #E_tor (p-Sylow if p != 0);
92 : * assume integral model */
93 : static long
94 2149 : torsbound(GEN e, ulong p)
95 : {
96 2149 : GEN D = ell_get_disc(e);
97 2149 : pari_sp av = avma, av2;
98 2149 : long m, b, bold, nb, CM = ellQ_get_CM(e);
99 : forprime_t S;
100 2149 : nb = expi(D) >> 3; /* number of primes to try ~ 1 prime every 8 bits in D */
101 2149 : switch (p)
102 : {
103 245 : case 0: b = 5040; break;
104 896 : case 2: b = 16; break;
105 42 : case 3: b = 9; break;
106 84 : case 5: case 7: b = p; break;
107 882 : default: return 1;
108 : }
109 1267 : bold = b;
110 1267 : m = 0;
111 : /* p > 2 has good reduction => E(Q) injects in E(Fp) */
112 1267 : (void)u_forprime_init(&S, 3, ULONG_MAX);
113 1267 : av2 = avma;
114 21371 : while (m < nb || (b > 12 && b != 16))
115 : {
116 20678 : ulong p = u_forprime_next(&S);
117 20678 : if (!p) pari_err_BUG("torsbound [ran out of primes]");
118 20678 : if (!umodiu(D, p)) continue;
119 :
120 16485 : b = ugcd(b, p+1 - ellap_CM_fast(e,p,CM));
121 16485 : set_avma(av2);
122 16485 : if (b == 1) break;
123 15911 : if (b == bold) m++; else { bold = b; m = 0; }
124 : }
125 1267 : return gc_long(av,b);
126 : }
127 :
128 : /* return a rational point of order pk = p^k on E, or NULL if E(Q)[k] = O.
129 : * *fk is either NULL (pk = 4 or prime) or elldivpol(p^(k-1)).
130 : * Set *fk to elldivpol(p^k) */
131 : static GEN
132 595 : tpoint(GEN E, long pk, GEN *fk)
133 : {
134 595 : GEN f = elldivpol(E,pk,0), g = *fk, v;
135 : long i, l;
136 595 : *fk = f;
137 595 : if (g) f = RgX_div(f, g);
138 595 : v = nfrootsQ(f); l = lg(v);
139 910 : for (i = 1; i < l; i++)
140 : {
141 749 : GEN x = gel(v,i);
142 749 : GEN y = ellordinate(E,x,0);
143 749 : if (lg(y) != 1) return mkvec2(x,gel(y,1));
144 : }
145 161 : return NULL;
146 : }
147 : /* return E(Q)[2] */
148 : static GEN
149 588 : t2points(GEN E, GEN *f2)
150 : {
151 : long i, l;
152 : GEN v;
153 588 : *f2 = ec_bmodel(E);
154 588 : v = nfrootsQ(*f2); l = lg(v);
155 1680 : for (i = 1; i < l; i++)
156 : {
157 1092 : GEN x = gel(v,i);
158 1092 : GEN y = ellordinate(E,x,0);
159 1092 : if (lg(y) != 1) gel(v,i) = mkvec2(x,gel(y,1));
160 : }
161 588 : return v;
162 : }
163 :
164 : /* psylow = 0 or prime (return p-Sylow subgroup) */
165 : static GEN
166 2149 : ellQtors(GEN E, long psylow)
167 : {
168 2149 : GEN T2 = NULL, p, P, Q, v;
169 : long v2, r2, B;
170 :
171 2149 : E = ellintegralmodel_i(E, &v);
172 2149 : B = torsbound(E, psylow); /* #E_tor | B */
173 2149 : if (B == 1) return tors(E,1,NULL,NULL, v);
174 693 : v2 = vals(B); /* bound for v_2(point order) */
175 693 : B >>= v2;
176 693 : p = const_vec(9, NULL);
177 693 : r2 = 0;
178 693 : if (v2) {
179 : GEN f;
180 588 : T2 = t2points(E, &f);
181 588 : switch(lg(T2)-1)
182 : {
183 14 : case 0: v2 = 0; break;
184 315 : case 1: r2 = 1; if (v2 == 4) v2 = 3; break;
185 259 : default: r2 = 2; v2--; break; /* 3 */
186 : }
187 588 : if (v2) gel(p,2) = gel(T2,1);
188 : /* f = f2 */
189 588 : if (v2 > 1) { gel(p,4) = tpoint(E,4, &f); if (!gel(p,4)) v2 = 1; }
190 : /* if (v2>1) now f = f4 */
191 588 : if (v2 > 2) { gel(p,8) = tpoint(E,8, &f); if (!gel(p,8)) v2 = 2; }
192 : }
193 693 : B <<= v2;
194 693 : if (B % 3 == 0) {
195 84 : GEN f3 = NULL;
196 84 : gel(p,3) = tpoint(E,3,&f3);
197 84 : if (!gel(p,3)) B /= (B%9)? 3: 9;
198 84 : if (gel(p,3) && B % 9 == 0)
199 : {
200 7 : gel(p,9) = tpoint(E,9,&f3);
201 7 : if (!gel(p,9)) B /= 3;
202 : }
203 : }
204 693 : if (B % 5 == 0) {
205 42 : GEN junk = NULL;
206 42 : gel(p,5) = tpoint(E,5,&junk);
207 42 : if (!gel(p,5)) B /= 5;
208 : }
209 693 : if (B % 7 == 0) {
210 35 : GEN junk = NULL;
211 35 : gel(p,7) = tpoint(E,7,&junk);
212 35 : if (!gel(p,7)) B /= 7;
213 : }
214 : /* B is the exponent of E_tors(Q), r2 is the rank of its 2-Sylow,
215 : * for i > 1, p[i] is a point of order i if one exists and i is a prime power
216 : * and NULL otherwise */
217 693 : if (r2 == 2) /* 2 cyclic factors */
218 : { /* C2 x C2 */
219 259 : if (B == 2) return tors(E,2, gel(T2,1), gel(T2,2), v);
220 119 : else if (B == 6)
221 : { /* C2 x C6 */
222 14 : P = elladd(E, gel(p,3), gel(T2,1));
223 14 : Q = gel(T2,2);
224 : }
225 : else
226 : { /* C2 x C4 or C2 x C8 */
227 105 : P = gel(p, B);
228 105 : Q = gel(T2,2);
229 105 : if (gequal(Q, ellmul(E, P, utoipos(B>>1)))) Q = gel(T2,1);
230 : }
231 : }
232 : else /* cyclic */
233 : {
234 434 : Q = NULL;
235 434 : if (v2)
236 : {
237 315 : if (B>>v2 == 1)
238 287 : P = gel(p, B);
239 : else
240 28 : P = elladd(E, gel(p, B>>v2), gel(p,1<<v2));
241 : }
242 119 : else P = gel(p, B);
243 : }
244 553 : return tors(E,B, P, Q, v);
245 : }
246 :
247 : /* either return one prime of degree 1 above p or NULL (none or expensive) */
248 : static GEN
249 6405 : primedec_deg1(GEN K, GEN p)
250 : {
251 6405 : GEN r, T, f = nf_get_index(K);
252 6405 : if (dvdii(f,p)) return NULL;
253 6328 : T = nf_get_pol(K);
254 6328 : r = FpX_oneroot(T, p); if (!r) return NULL;
255 1211 : r = deg1pol_shallow(gen_1, Fp_neg(r,p), varn(T));
256 1211 : return idealprimedec_kummer(K, r, 1, p);
257 : }
258 :
259 : /* Bound for the elementary divisors of the torsion group of elliptic curve
260 : * (p-Sylow if psylow = p is not 0)
261 : * Reduce the curve modulo some small good primes */
262 : static GEN
263 427 : nftorsbound(GEN E, ulong psylow)
264 : {
265 : pari_sp av;
266 427 : long k = 0, g;
267 427 : GEN B1 = gen_0, B2 = gen_0, K = ellnf_get_nf(E);
268 427 : GEN D = ell_get_disc(E), ND = idealnorm(K,D);
269 : forprime_t S;
270 427 : if (typ(ND) == t_FRAC) ND = gel(ND,1);
271 427 : ND = mulii(ND, Q_denom(vecslice(E,1,5)));
272 427 : g = maxss(5, expi(ND) >> 3);
273 427 : if (g > 20) g = 20;
274 : /* P | p such that e(P/p) < p-1 => E(K) injects in E(k(P)) [otherwise
275 : * we may lose some p-torsion]*/
276 427 : (void)u_forprime_init(&S, 3, ULONG_MAX);
277 427 : av = avma;
278 9492 : while (k < g) /* k = number of good primes already used */
279 : {
280 9226 : ulong p = u_forprime_next(&S);
281 : GEN P, gp;
282 : long j, l;
283 9226 : if (!umodiu(ND,p)) continue;
284 8358 : gp = utoipos(p);
285 : /* primes of degree 1 are easier and give smaller bounds */
286 8358 : if (typ(D) != t_POLMOD) /* E/Q */
287 : {
288 5796 : P = primedec_deg1(K, gp); /* single P|p has all the information */
289 5796 : if (!P) continue;
290 973 : P = mkvec(P);
291 : }
292 : else
293 2562 : P = idealprimedec_limit_f(K, utoipos(p), 1);
294 3535 : l = lg(P);
295 6146 : for (j = 1; j < l; j++,k++)
296 : {
297 2772 : GEN Q = gel(P,j), EQ, cyc;
298 : long n;
299 2772 : if ((ulong)pr_get_e(Q) >= p-1) continue;
300 2772 : EQ = ellinit(E,zkmodprinit(K,Q),0);
301 2772 : cyc = ellgroup(EQ, NULL);
302 2772 : n = lg(cyc)-1;
303 2772 : if (n == 0) return mkvec2(gen_1,gen_1);
304 2765 : B1 = gcdii(B1,gel(cyc,1));
305 2765 : B2 = (n == 1)? gen_1: gcdii(B2,gel(cyc,2));
306 2765 : obj_free(EQ);
307 : /* division by 2 is cheap when it fails, no need to have a sharp bound */
308 2765 : if (psylow==0 && Z_ispow2(B1)) return mkvec2(B1,B2);
309 : }
310 3374 : if ((g & 15) == 0) gerepileall(av, 2, &B1, &B2);
311 : }
312 266 : if (abscmpiu(B2, 2) > 0)
313 : { /* if E(K) has full n-torsion then K contains the n-th roots of 1 */
314 91 : GEN n = gel(nfrootsof1(K), 1);
315 91 : B2 = gcdii(B2,n);
316 : }
317 266 : if (psylow)
318 : {
319 0 : B1 = powuu(psylow, Z_lval(B1, psylow));
320 0 : B2 = powuu(psylow, Z_lval(B2, psylow));
321 : }
322 266 : return mkvec2(B1,B2);
323 : }
324 :
325 : /* Checks whether the point P is divisible by n in E(K), where xn is
326 : * [phi_n, psi_n^2]
327 : * If true, returns a point Q such that nQ = P or -P. Else, returns NULL */
328 : static GEN
329 189 : ellnfis_divisible_by(GEN E, GEN K, GEN P, GEN xn)
330 : {
331 189 : GEN r, x = gel(P,1);
332 : long i, l;
333 189 : if (ell_is_inf(P)) return P;
334 189 : r = nfroots(K, RgX_sub(RgX_Rg_mul(gel(xn,2), x), gel(xn,1)));
335 189 : l = lg(r);
336 189 : for(i=1; i<l; i++)
337 : {
338 112 : GEN a = gel(r,i), y = ellordinate(E,a,0);
339 112 : if (lg(y) != 1) return mkvec2(a, gel(y,1));
340 : }
341 77 : return NULL;
342 : }
343 :
344 : /* P is not the point at infinity; w a variable number of highest priority */
345 : static long
346 203 : ellisdivisible_divpol_i(GEN E, GEN P, GEN n, long w, GEN *pQ)
347 : {
348 203 : GEN xP, R, K = NULL, N = NULL;
349 : long i, l;
350 203 : switch(ell_get_type(E))
351 : {
352 182 : case t_ELL_Q: break;
353 21 : case t_ELL_NF: K = ellnf_get_nf(E); break;
354 0 : default: pari_err_TYPE("ellisdivisible",E);
355 : }
356 203 : switch(typ(n))
357 : {
358 56 : case t_INT:
359 56 : N = n;
360 56 : if (!isprime(absi_shallow(n)))
361 : {
362 21 : GEN f = absZ_factor(n), LP = gel(f,1), LE = gel(f,2);
363 21 : l = lg(LP);
364 49 : for (i = 1; i < l; i++)
365 : {
366 28 : long j, e = itos(gel(LE,i));
367 28 : GEN xp = ellxn(E,itos(gel(LP,i)), w);
368 70 : for (j = 1; j <= e; j++)
369 42 : if (!ellisdivisible(E, P, xp, &P)) return 0;
370 : }
371 21 : if (pQ) *pQ = signe(n) < 0? ellneg(E, P): P;
372 21 : return 1;
373 : }
374 35 : n = ellxn(E, itou(n), w);
375 35 : break;
376 147 : case t_VEC:
377 147 : if (lg(n) == 3 && typ(gel(n,1)) == t_POL && typ(gel(n,2)) == t_POL) break;
378 : default:
379 0 : pari_err_TYPE("ellisdivisible",n);
380 0 : break;
381 : }
382 182 : if (!N)
383 : {
384 147 : long d, d2 = degpol(gel(n,1));
385 147 : if (d2 < 0)
386 0 : N = gen_0;
387 : else
388 : {
389 147 : if (!uissquareall(d2,(ulong*)&d)) pari_err_TYPE("ellisdivisible",n);
390 147 : N = stoi(d);
391 : }
392 : }
393 182 : if (!signe(N)) return 0;
394 182 : xP = gel(P,1);
395 182 : R = nfroots(K, RgX_sub(RgX_Rg_mul(gel(n,2), xP), gel(n,1)));
396 182 : l = lg(R);
397 182 : for(i = 1; i < l; i++)
398 : {
399 175 : GEN Q,y, x = gel(R,i), a = ellordinate(E,x,0);
400 175 : if (lg(a) == 1) continue;
401 175 : y = gel(a,1);
402 175 : Q = mkvec2(x,y);
403 175 : if (!gequal(P,ellmul(E,Q,N))) Q = ellneg(E,Q); /* nQ = -P */
404 175 : if (pQ) *pQ = Q;
405 175 : return 1;
406 : }
407 7 : return 0;
408 : }
409 : static long
410 203 : ellisdivisible_divpol(GEN E, GEN P, GEN n, GEN *pQ)
411 : {
412 203 : long w = fetch_var_higher(), t = ellisdivisible_divpol_i(E, P, n, w, pQ);
413 203 : delete_var(); return t;
414 : }
415 :
416 : long
417 231 : ellisdivisible(GEN E, GEN P, GEN n, GEN *pQ)
418 : {
419 231 : pari_sp av = avma;
420 231 : checkell(E); checkellpt(P);
421 231 : if (ell_is_inf(P))
422 : {
423 7 : if (pQ) *pQ = ellinf();
424 7 : return 1;
425 : }
426 224 : if (typ(n) == t_INT)
427 : {
428 77 : if (!signe(n)) return 0;
429 70 : if (ell_get_type(E) == t_ELL_Q)
430 : {
431 49 : ulong nn = itou(n), n2 = u_ppo(nn, 210);
432 49 : nn /= n2;
433 49 : if (n2 > 1)
434 : {
435 14 : P = ellQ_isdivisible(E, P, n2);
436 14 : if (!P) return 0;
437 0 : if (signe(n) < 0) P = ellneg(E, P);
438 0 : if (nn == 1)
439 : {
440 0 : if (pQ) *pQ = P;
441 0 : return 1;
442 : }
443 0 : n = utoipos(nn); /* we may have changed n into -n (and P in -P) */
444 : }
445 : }
446 : }
447 203 : if (!ellisdivisible_divpol(E, P, n, pQ)) return gc_long(av, 0);
448 196 : if (!pQ) return gc_long(av, 1);
449 196 : *pQ = gerepilecopy(av, *pQ); return 1;
450 : }
451 :
452 : /* 2-torsion point of abscissa x */
453 : static GEN
454 126 : tor2(GEN E, GEN x) { return mkvec2(x, gmul2n(gneg(ec_h_evalx(E,x)), -1)); }
455 :
456 : static GEN
457 35 : ptor0(void)
458 35 : { return mkvec2(mkvec(gen_1),cgetg(1,t_VEC)); }
459 : static GEN
460 126 : ptor1(long p, long n, GEN P)
461 126 : { return mkvec2(mkvec(powuu(p,n)), mkvec(P)); }
462 : static GEN
463 98 : ptor2(long p, long n1, long n2, GEN P1, GEN P2)
464 98 : { return mkvec2(mkvec2(powuu(p,n1), powuu(p,n2)), mkvec2(P1,P2)); }
465 :
466 : /* Computes the p-primary torsion in E(K). Assume that p is small, should use
467 : * Weil pairing otherwise.
468 : * N1, N2 = upper bounds on the integers n1 >= n2 such that
469 : * E(K)[p^oo] = Z/p^n1 x Z/p^n2
470 : * Returns [cyc,gen], where E(K)[p^oo] = sum Z/cyc[i] gen[i] */
471 : static GEN
472 259 : ellnftorsprimary(GEN E, long p, long N1, long N2, long v)
473 : {
474 259 : GEN X, P1, P2, Q1, Q2, xp, K = ellnf_get_nf(E);
475 : long n1, n2;
476 :
477 : /* compute E[p] = < P1 > or < P1, P2 > */
478 259 : P1 = P2 = ellinf();
479 259 : X = nfroots(K, elldivpol(E,p,v));
480 259 : if(lg(X) == 1) return ptor0();
481 231 : if (p==2)
482 : {
483 77 : P1 = tor2(E, gel(X,1));
484 77 : if (lg(X) > 2) P2 = tor2(E, gel(X,2)); /* E[2] = (Z/2Z)^2 */
485 : }
486 : else
487 : {
488 154 : long j, l = lg(X), nT, a;
489 154 : GEN T = vectrunc_init(l);
490 539 : for(j=1; j < l; j++)
491 : {
492 385 : GEN a = gel(X,j), Y = ellordinate(E,a,0);
493 385 : if (lg(Y) != 1) vectrunc_append(T, mkvec2(a,gel(Y,1)));
494 : }
495 154 : nT = lg(T)-1;
496 154 : if (!nT) return ptor0();
497 147 : P1 = gel(T,1);
498 147 : a = (p-1)/2;
499 147 : if (nT != a)
500 : { /* E[p] = (Z/pZ)^2 */
501 49 : GEN Z = cgetg(a+1,t_VEC), Q1 = P1;
502 : long k;
503 49 : gel(Z,1) = Q1;
504 49 : for (k=2; k <= a; k++) gel(Z,k) = elladd(E,Q1,P1);
505 49 : gen_sort_inplace(Z, (void*)&cmp_universal, &cmp_nodata, NULL);
506 49 : while (tablesearch(Z, gel(T,k), &cmp_universal)) k++;
507 49 : P2 = gel(T,k);
508 : }
509 : }
510 224 : xp = ellxn(E, p, v);
511 :
512 224 : if (ell_is_inf(P2))
513 : { /* E[p^oo] is cyclic, start from P1 and divide by p while possible */
514 140 : for (n1 = 1; n1 < N1; n1++)
515 : {
516 14 : GEN Q = ellnfis_divisible_by(E,K,P1,xp);
517 14 : if (!Q) break;
518 14 : P1 = Q;
519 : }
520 126 : return ptor1(p, n1, P1);
521 : }
522 :
523 : /* E[p] = (Z/pZ)^2, compute n2 and E[p^n2] */
524 98 : Q1 = NULL;
525 119 : for (n2 = 1; n2 < N2; n2++)
526 : {
527 21 : Q1 = ellnfis_divisible_by(E,K,P1,xp);
528 21 : Q2 = ellnfis_divisible_by(E,K,P2,xp);
529 21 : if (!Q1 || !Q2) break;
530 21 : P1 = Q1;
531 21 : P2 = Q2;
532 : }
533 :
534 : /* compute E[p^oo] = < P1, P2 > */
535 98 : n1 = n2;
536 98 : if (n2 == N2)
537 : {
538 98 : if (N1 == N2) return ptor2(p, n2,n2, P1,P2);
539 42 : Q1 = ellnfis_divisible_by(E,K,P1,xp);
540 : }
541 42 : if (Q1) { P1 = Q1; n1++; }
542 : else
543 : {
544 28 : Q2 = ellnfis_divisible_by(E,K,P2,xp);
545 28 : if (Q2) { P2 = P1; P1 = Q2; n1++; }
546 : else
547 : {
548 : long k;
549 35 : for (k = 1; k < p; k++)
550 : {
551 28 : P1 = elladd(E,P1,P2);
552 28 : Q1 = ellnfis_divisible_by(E,K,P1,xp);
553 28 : if (Q1) { P1 = Q1; n1++; break; }
554 : }
555 28 : if (k == p) return ptor2(p, n2,n2, P1,P2);
556 : }
557 : }
558 : /* P1,P2 of order p^n1,p^n2 with n1=n2+1.
559 : * Keep trying to divide P1 + k P2 with 0 <= k < p by p */
560 56 : while (n1 < N1)
561 : {
562 21 : Q1 = ellnfis_divisible_by(E,K,P1,xp);
563 21 : if (Q1) { P1 = Q1; n1++; }
564 : else
565 : {
566 : long k;
567 14 : for (k = 1; k < p; k++)
568 : {
569 14 : P1 = elladd(E,P1,P2);
570 14 : Q1 = ellnfis_divisible_by(E,K,P1,xp);
571 14 : if (Q1) { P1 = Q1; n1++; break; }
572 : }
573 14 : if (k == p) break;
574 : }
575 : }
576 35 : return ptor2(p, n1,n2, P1,P2);
577 : }
578 :
579 : /* P affine point */
580 : static GEN
581 259 : nfpt(GEN e, GEN P)
582 : {
583 259 : GEN T = nf_get_pol(ellnf_get_nf(e));
584 259 : GEN x = gel(P,1), y = gel(P,2);
585 259 : long tx = typ(x), ty = typ(y);
586 259 : if (tx == ty) return P;
587 98 : if (tx != t_POLMOD) x = mkpolmod(x,T); else y = mkpolmod(y,T);
588 98 : return mkvec2(x,y);
589 : }
590 : /* Computes the torsion subgroup of E(K), as [order, cyc, gen] */
591 : static GEN
592 189 : ellnftors(GEN e, ulong psylow)
593 : {
594 189 : GEN B = nftorsbound(e, psylow), B1 = gel(B,1), B2 = gel(B,2), d1,d2, P1,P2;
595 189 : GEN f = Z_factor(B1), P = gel(f,1), E = gel(f,2);
596 189 : long i, l = lg(P), v = fetch_var_higher();
597 :
598 189 : d1 = d2 = gen_1; P1 = P2 = ellinf();
599 448 : for (i=1; i<l; i++)
600 : {
601 259 : long p = itos(gel(P,i)); /* Compute p-primary torsion */
602 259 : long N1 = itos(gel(E,i)); /* >= n1 */
603 259 : long N2 = Z_lval(B2,p); /* >= n2 */
604 259 : GEN T = ellnftorsprimary(e, p, N1, N2, v), cyc = gel(T,1), gen = gel(T,2);
605 259 : if (is_pm1(gel(cyc,1))) continue;
606 : /* update generators P1,P2 and their respective orders d1,d2 */
607 224 : P1 = elladd(e, P1, gel(gen,1)); d1 = mulii(d1, gel(cyc,1));
608 224 : if (lg(cyc) > 2)
609 98 : { P2 = elladd(e, P2, gel(gen,2)); d2 = mulii(d2, gel(cyc,2)); }
610 : }
611 189 : (void)delete_var();
612 189 : if (is_pm1(d1)) return mkvec3(gen_1,cgetg(1,t_VEC),cgetg(1,t_VEC));
613 168 : if (is_pm1(d2)) return mkvec3(d1, mkvec(d1), mkvec(nfpt(e,P1)));
614 91 : return mkvec3(mulii(d1,d2), mkvec2(d1,d2), mkvec2(nfpt(e,P1),nfpt(e,P2)));
615 : }
616 :
617 : GEN
618 434 : elltors(GEN e)
619 : {
620 434 : pari_sp av = avma;
621 434 : GEN t = NULL;
622 434 : checkell(e);
623 434 : switch(ell_get_type(e))
624 : {
625 245 : case t_ELL_Q: t = ellQtors(e, 0); break;
626 189 : case t_ELL_NF: t = ellnftors(e, 0); break;
627 0 : case t_ELL_Fp:
628 0 : case t_ELL_Fq: return ellgroup0(e,NULL,1);
629 0 : default: pari_err_TYPE("elltors",e);
630 : }
631 434 : return gerepilecopy(av, t);
632 : }
633 :
634 : GEN
635 0 : elltors0(GEN e, long flag) { (void)flag; return elltors(e); }
636 :
637 : GEN
638 1904 : elltors_psylow(GEN e, ulong p)
639 : {
640 1904 : pari_sp av = avma;
641 1904 : GEN t = NULL;
642 1904 : checkell(e);
643 1904 : switch(ell_get_type(e))
644 : {
645 1904 : case t_ELL_Q: t = ellQtors(e, p); break;
646 0 : case t_ELL_NF: t = ellnftors(e, p); break;
647 0 : default: pari_err_TYPE("elltors_psylow",e);
648 : }
649 1904 : return gerepilecopy(av, t);
650 : }
651 :
652 : /********************************************************************/
653 : /** **/
654 : /** ORDER OF POINTS over NUMBER FIELDS **/
655 : /** **/
656 : /********************************************************************/
657 : /* E a t_ELL_Q (use Mazur's theorem) */
658 : long
659 23772 : ellorder_Q(GEN E, GEN P)
660 : {
661 23772 : pari_sp av = avma;
662 : GEN dx, dy, d4, d6, D, Pp, Q;
663 : forprime_t S;
664 : ulong a4, p;
665 : long k;
666 23772 : if (ell_is_inf(P)) return 1;
667 23772 : if (gequal(P, ellneg(E,P))) return 2;
668 :
669 23751 : dx = Q_denom(gel(P,1));
670 23751 : dy = Q_denom(gel(P,2));
671 23751 : if (ell_is_integral(E)) /* integral model, try Nagell Lutz */
672 23688 : if (abscmpiu(dx, 4) > 0 || abscmpiu(dy, 8) > 0) return 0;
673 :
674 7105 : d4 = Q_denom(ell_get_c4(E));
675 7105 : d6 = Q_denom(ell_get_c6(E));
676 7105 : D = ell_get_disc (E);
677 : /* choose not too small prime p dividing neither a coefficient of the
678 : short Weierstrass form nor of P and leading to good reduction */
679 7105 : u_forprime_init(&S, 100003, ULONG_MAX);
680 7105 : while ( (p = u_forprime_next(&S)) )
681 7105 : if (umodiu(d4, p) && umodiu(d6, p) && Rg_to_Fl(D, p)
682 7105 : && umodiu(dx, p) && umodiu(dy, p)) break;
683 :
684 : /* transform E into short Weierstrass form Ep modulo p and P to Pp on Ep,
685 : * check whether the order of Pp on Ep is <= 12 */
686 7105 : Pp = point_to_a4a6_Fl(E, P, p, &a4);
687 91917 : for (Q = Fle_dbl(Pp, a4, p), k = 2;
688 169561 : !ell_is_inf(Q) && k <= 12;
689 77707 : Q = Fle_add(Q, Pp, a4, p), k++) /* empty */;
690 :
691 7105 : if (k == 13) k = 0;
692 : else
693 : { /* check whether [k]P = O over Q. Save potentially costly last elladd */
694 : GEN R;
695 63 : Q = ellmul(E, P, utoipos(k>>1));
696 63 : R = odd(k)? elladd(E, P,Q): Q;
697 63 : if (!gequal(Q, ellneg(E,R))) k = 0;
698 : }
699 7105 : return gc_long(av,k);
700 : }
701 : /* E a t_ELL_NF */
702 : static GEN
703 273 : ellorder_nf(GEN E, GEN P)
704 : {
705 273 : GEN K = ellnf_get_nf(E), B;
706 273 : pari_sp av = avma;
707 : GEN dx, dy, d4, d6, D, ND, Ep, Pp, Q, gp, modpr, pr, T, k;
708 : forprime_t S;
709 : ulong a4, p;
710 273 : if (ell_is_inf(P)) return gen_1;
711 273 : if (gequal(P, ellneg(E,P))) return gen_2;
712 :
713 238 : B = gel(nftorsbound(E, 0), 1);
714 238 : dx = Q_denom(gel(P,1));
715 238 : dy = Q_denom(gel(P,2));
716 238 : d4 = Q_denom(ell_get_c4(E));
717 238 : d6 = Q_denom(ell_get_c6(E));
718 238 : D = ell_get_disc(E);
719 238 : ND = idealnorm(K,D);
720 238 : if (typ(ND) == t_FRAC) ND = gel(ND,1);
721 :
722 : /* choose not too small prime p of degree 1 dividing neither a coefficient of
723 : * the short Weierstrass form nor of P and leading to good reduction */
724 238 : u_forprime_init(&S, 100003, ULONG_MAX);
725 609 : while ( (p = u_forprime_next(&S)) )
726 : {
727 609 : if (!umodiu(d4, p) || !umodiu(d6, p) || !umodiu(ND, p)
728 609 : || !umodiu(dx, p) || !umodiu(dy, p)) continue;
729 609 : gp = utoipos(p);
730 609 : pr = primedec_deg1(K, gp);
731 609 : if (pr) break;
732 : }
733 :
734 238 : modpr = nf_to_Fq_init(K, &pr,&T,&gp);
735 238 : Ep = ellinit(E, pr, 0);
736 238 : Pp = nfV_to_FqV(P, K, modpr);
737 :
738 : /* transform E into short Weierstrass form Ep modulo p and P to Pp on Ep,
739 : * check whether the order of Pp on Ep divides B */
740 238 : Pp = point_to_a4a6_Fl(Ep, Pp, p, &a4);
741 238 : if (!ell_is_inf(Fle_mul(Pp, B, a4, p))) { set_avma(av); return gen_0; }
742 147 : k = Fle_order(Pp, B, a4, p);
743 : { /* check whether [k]P = O over K. Save potentially costly last elladd */
744 : GEN R;
745 147 : Q = ellmul(E, P, shifti(k,-1));
746 147 : R = mod2(k)? elladd(E, P,Q): Q;
747 147 : if (!gequal(Q, ellneg(E,R))) k = gen_0;
748 : }
749 147 : return gerepileuptoint(av, k);
750 : }
751 :
752 : GEN
753 2793 : ellorder(GEN E, GEN P, GEN o)
754 : {
755 2793 : pari_sp av = avma;
756 2793 : GEN fg, r, E0 = E;
757 2793 : checkell(E); checkellpt(P);
758 2793 : if (ell_is_inf(P)) return gen_1;
759 2779 : if (ell_get_type(E)==t_ELL_Q)
760 : {
761 1869 : long tx = typ(gel(P,1)), ty = typ(gel(P,2));
762 1869 : GEN p = NULL;
763 1869 : if (is_rational_t(tx) && is_rational_t(ty)) return utoi(ellorder_Q(E, P));
764 1778 : if (tx == t_INTMOD || tx == t_FFELT) p = gel(P,1);
765 1778 : if (!p && (ty == t_INTMOD || ty == t_FFELT)) p = gel(P,2);
766 1778 : if (p)
767 : {
768 1778 : E = ellinit(E,p,0);
769 1778 : if (lg(E)==1) pari_err_IMPL("ellorder for curve with singular reduction");
770 : }
771 : }
772 2681 : if (ell_get_type(E)==t_ELL_NF) return ellorder_nf(E, P);
773 2408 : checkell_Fq(E);
774 2408 : fg = ellff_get_field(E);
775 2408 : if (!o) o = ellff_get_o(E);
776 2408 : if (typ(fg)==t_FFELT)
777 1750 : r = FF_ellorder(E, P, o);
778 : else
779 : {
780 658 : GEN p = fg, e = ellff_get_a4a6(E);
781 658 : GEN Pp = FpE_changepointinv(RgE_to_FpE(P,p), gel(e,3), p);
782 658 : r = FpE_order(Pp, o, gel(e,1), p);
783 : }
784 2408 : if (E != E0) obj_free(E);
785 2408 : return gerepileuptoint(av, r);
786 : }
787 :
788 : GEN
789 0 : orderell(GEN e, GEN z) { return ellorder(e,z,NULL); }
|