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