Line data Source code
1 : /* Copyright (C) 2005 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 : /** INTERFACE TO JOHN CREMONA ELLIPTIC CURVES DATABASE **/
18 : /** **/
19 : /********************************************************************/
20 : #include "pari.h"
21 : #include "paripriv.h"
22 :
23 : static long
24 126 : strtoclass(const char *s)
25 : {
26 126 : long c=0;
27 378 : while (*s && *s<='9') s++;
28 126 : if (!*s) return -1;
29 252 : while ('a'<=*s && *s<='z') c = 26*c + *(s++)-'a';
30 126 : return c;
31 : }
32 :
33 : /*Take a curve name like "100a2" and set
34 : * f to the conductor, (100)
35 : * c to the isogeny class (in base 26), ("a" or 0)
36 : * i to the curve index (2).
37 : * return 0 if parse error. */
38 : static int
39 529732 : ellparsename(const char *s, long *f, long *c, long *i)
40 : {
41 : long j;
42 529732 : *f=-1; *c=-1; *i=-1;
43 529732 : if (*s<'0' || *s>'9') return 0;
44 529725 : *f=0;
45 2526041 : for (j=0;j<10 && '0'<=*s && *s<='9';j++)
46 1996316 : *f=10**f+*(s++)-'0';
47 529725 : if (j==10) {*f=-1; return 0;}
48 529725 : if (*s<'a' || *s>'z') return !*s;
49 529718 : *c=0;
50 1086393 : for (j=0; j<7 && 'a'<=*s && *s<='z';j++)
51 556675 : *c=26**c+*(s++)-'a';
52 529718 : if (j==7) {*c=-1; return 0;}
53 529718 : if (*s<'0' || *s>'9') return !*s;
54 529704 : *i=0;
55 1059408 : for (j=0; j<10 && '0'<=*s && *s<='9';j++)
56 529704 : *i=10**i+*(s++)-'0';
57 529704 : if (j==10) {*i=-1; return 0;}
58 529704 : return !*s;
59 : }
60 :
61 : /* Take an integer and convert it to base 26 */
62 : static GEN
63 14 : ellrecode(long x)
64 : {
65 : GEN str;
66 : char *s;
67 14 : long d = 0, n = x;
68 14 : do { d++; n /= 26; } while (n);
69 14 : str = cgetg(nchar2nlong(d+1)+1, t_STR);
70 14 : s = GSTR(str); s[d] = 0;
71 14 : n = x;
72 14 : do { s[--d] = n%26 + 'a'; n /= 26; } while (n);
73 14 : return str;
74 : }
75 :
76 : GEN
77 524405 : ellconvertname(GEN n)
78 : {
79 524405 : switch(typ(n))
80 : {
81 524391 : case t_STR:
82 : {
83 : long f,i,c;
84 524391 : if (!ellparsename(GSTR(n),&f,&c,&i)) pari_err_TYPE("ellconvertname", n);
85 524391 : if (f<0 || c<0 || i<0)
86 0 : pari_err_TYPE("ellconvertname [incomplete name]", n);
87 524391 : return mkvec3s(f,c,i);
88 : }
89 14 : case t_VEC:
90 14 : if (lg(n)==4)
91 : {
92 14 : pari_sp av = avma;
93 14 : GEN f=gel(n,1), c=gel(n,2), s=gel(n,3);
94 14 : if (typ(f)!=t_INT || typ(c)!=t_INT || typ(s)!=t_INT)
95 0 : pari_err_TYPE("ellconvertname",n);
96 14 : return gc_GEN(av, shallowconcat1(mkvec3(f, ellrecode(itos(c)), s)));
97 : }
98 : /*fall through*/
99 : }
100 0 : pari_err_TYPE("ellconvertname",n);
101 : return NULL; /*LCOV_EXCL_LINE*/
102 : }
103 :
104 : THREAD GEN ellcondfile_cache;
105 : THREAD long ellcondfile_cache_cond;
106 :
107 : void
108 378340 : pari_init_ellcondfile(void)
109 : {
110 378340 : ellcondfile_cache = NULL;
111 378340 : ellcondfile_cache_cond = -1;
112 378340 : }
113 :
114 : static GEN
115 1295 : ellcondfile(long n)
116 : {
117 1295 : if (ellcondfile_cache_cond >= 0 && n == ellcondfile_cache_cond)
118 728 : return gcopy(ellcondfile_cache);
119 : else
120 : {
121 567 : pari_sp av = avma;
122 : pariFILE *F;
123 : GEN V;
124 567 : char *s = stack_sprintf("%s/elldata/ell%ld", pari_datadir, n);
125 567 : F = pari_fopengz(s);
126 567 : if (!F) pari_err_FILE("elldata file",s);
127 567 : set_avma(av);
128 567 : V = gp_read_stream(F->file);
129 567 : if (!V || typ(V)!=t_VEC ) pari_err_FILE("elldata file [read]",s);
130 567 : ellcondfile_cache_cond = -1; /* disable cache until update */
131 567 : if (ellcondfile_cache) gunclone(ellcondfile_cache);
132 567 : ellcondfile_cache = gclone(V);
133 567 : ellcondfile_cache_cond = n; /* re-enable cache */
134 567 : pari_fclose(F); return V;
135 : }
136 : }
137 :
138 : /* return the vector of all curves of conductor f */
139 : static int
140 9457 : cmpi1(GEN x, GEN v) { return cmpii(x, gel(v,1)); }
141 : static GEN
142 1092 : ellcondlist(long f)
143 : {
144 1092 : pari_sp av = avma;
145 1092 : GEN V = ellcondfile(f/1000);
146 1092 : long i = tablesearch(V, utoipos(f), &cmpi1);
147 1092 : if (i)
148 : {
149 1092 : GEN v = gel(V,i);
150 1092 : return vecslice(v,2, lg(v)-1);
151 : }
152 0 : retgc_const(av, cgetg(1, t_VEC));
153 : }
154 :
155 : static GEN
156 1036 : ellsearchbyname(GEN V, char *name)
157 : {
158 : GEN x;
159 : long j;
160 5068 : for (j=1; j<lg(V); j++)
161 : {
162 5068 : GEN v = gel(V,j);
163 5068 : if (!strcmp(GSTR(gel(v,1)), name)) return v;
164 : }
165 0 : x = strtoGENstr(name);
166 0 : pari_err_DOMAIN("ellsearchbyname", "name", "=", x,x);
167 : return NULL;/*LCOV_EXCL_LINE*/
168 : }
169 :
170 : static GEN
171 21 : ellsearchbyclass(GEN V, long c)
172 : {
173 : long i,j,n;
174 : GEN res;
175 84 : for (n=0,j=1; j<lg(V); j++)
176 63 : if (strtoclass(GSTR(gmael(V,j,1)))==c) n++;
177 21 : res = cgetg(n+1,t_VEC);
178 84 : for (i=1,j=1; j<lg(V); j++)
179 63 : if (strtoclass(GSTR(gmael(V,j,1)))==c) res[i++] = V[j];
180 21 : return res;
181 : }
182 :
183 : GEN
184 84 : ellsearch(GEN A)
185 : {
186 84 : pari_sp av = avma;
187 : long f, c, i;
188 : GEN V;
189 84 : if (typ(A)==t_INT) { f = itos(A); c = i = -1; }
190 77 : else if (typ(A)==t_VEC)
191 : {
192 35 : long l = lg(A)-1;
193 35 : if (l<1 || l>3)
194 7 : pari_err_TYPE("ellsearch",A);
195 28 : f = gtos(gel(A,1));
196 28 : c = l>=2 ? gtos(gel(A,2)): -1;
197 28 : i = l>=3 ? gtos(gel(A,3)): -1;
198 28 : if (l>=3) A = ellconvertname(A);
199 : }
200 42 : else if (typ(A)==t_STR) {
201 35 : if (!ellparsename(GSTR(A),&f,&c,&i))
202 7 : pari_err_TYPE("ellsearch",A);
203 : } else {
204 7 : pari_err_TYPE("ellsearch",A);
205 : return NULL;/*LCOV_EXCL_LINE*/
206 : }
207 63 : if (f <= 0) pari_err_DOMAIN("ellsearch", "conductor", "<=", gen_0,stoi(f));
208 56 : V = ellcondlist(f);
209 56 : if (c >= 0)
210 35 : V = (i < 0)? ellsearchbyclass(V,c): ellsearchbyname(V, GSTR(A));
211 56 : return gc_GEN(av, V);
212 : }
213 :
214 : GEN
215 1022 : ellsearchcurve(GEN name)
216 : {
217 1022 : pari_sp ltop=avma;
218 : long f, c, i;
219 1022 : if (!ellparsename(GSTR(name),&f,&c,&i)) pari_err_TYPE("ellsearch",name);
220 1022 : if (f<0 || c<0 || i<0) pari_err_TYPE("ellsearch [incomplete name]", name);
221 1022 : return gc_GEN(ltop, ellsearchbyname(ellcondlist(f), GSTR(name)));
222 : }
223 :
224 : GEN
225 21 : ellidentify(GEN E)
226 : {
227 21 : pari_sp ltop=avma;
228 : long j;
229 : GEN V, M, G, N;
230 21 : checkell_Q(E);
231 14 : G = ellglobalred(E); N = gel(G,1);
232 14 : V = ellcondlist(itos(N));
233 14 : M = ellchangecurve(vecslice(E,1,5),gel(G,2));
234 14 : for (j=1; j<lg(V); j++)
235 14 : if (ZV_equal(gmael(V,j,2), M))
236 14 : return gc_GEN(ltop, mkvec2(gel(V,j),gel(G,2)));
237 0 : pari_err_BUG("ellidentify [missing curve]");
238 : return NULL;/*LCOV_EXCL_LINE*/
239 : }
240 :
241 : GEN
242 7 : elldatagenerators(GEN E)
243 : {
244 7 : pari_sp ltop=avma;
245 7 : GEN V=ellidentify(E);
246 7 : GEN gens=gmael(V,1,3);
247 7 : GEN W=ellchangepointinv(gens,gel(V,2));
248 7 : return gc_upto(ltop,W);
249 : }
250 :
251 : void
252 56 : forell(void *E, long call(void*, GEN), long a, long b, long flag)
253 : {
254 56 : long ca=a/1000, cb=b/1000;
255 : long i, j, k;
256 :
257 56 : if (ca < 0) ca = 0;
258 259 : for(i=ca; i<=cb; i++)
259 : {
260 203 : pari_sp ltop=avma;
261 203 : GEN V = ellcondfile(i);
262 106099 : for (j=1; j<lg(V); j++)
263 : {
264 105945 : GEN ells = gel(V,j);
265 105945 : long cond= itos(gel(ells,1));
266 :
267 105945 : if (i==ca && cond<a) continue;
268 105945 : if (i==cb && cond>b) break;
269 1091664 : for(k=2; k<lg(ells); k++)
270 : {
271 985768 : GEN e = gel(ells,k);
272 985768 : if (flag) {
273 4284 : GEN n = gel(e,1); /* Cremona label */
274 : long f, c, x;
275 4284 : if (!ellparsename(GSTR(n),&f,&c,&x))
276 0 : pari_err_TYPE("ellconvertname", n);
277 4284 : if (x != 1) continue;
278 : }
279 982786 : if (call(E, e)) return;
280 : }
281 : }
282 203 : set_avma(ltop);
283 : }
284 : }
285 :
286 : void
287 56 : forell0(long a, long b, GEN code, long flag)
288 56 : { EXPRVOID_WRAP(code, forell(EXPR_ARGVOID, a, b, flag)) }
|