Bill Allombert on Fri, 03 Jun 2005 14:51:28 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Re: Proposed elldata database at the PARI workshop |
On Fri, Jun 03, 2005 at 09:50:03AM +0200, Jeroen Demeyer wrote: > Bug: when using a changed curve equation, ellgens() doens't transform > the generators: > > gp> E=ellinit([0,50,0,609,0]); > gp> ellidentify(E) > %16 = [["9744C2", [0, -1, 0, -224, -816], [[-11, 14], [-10, 18]]], [1, > -17, 0, 0]] /* <--- Note the coordinate change */ > gp> ellgens(E) > %17 = [[-11, 14], [-10, 18]] > > But this should be [[-28, 14], [-27, 18]]. Good catch... here a new patch that fix that together with an egregious typo. Apparently, there is no functions to reverse elliptic curves coordinate change, so I had to write a pointchinv() function. Cheers, Bill.
Index: pari/src/functions/elliptic_curves/ellgens =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ pari/src/functions/elliptic_curves/ellgens 2005-06-03 14:34:13.000000000 +0200 @@ -0,0 +1,8 @@ +Function: ellgens +Section: elliptic_curves +C-Name: ellgens +Prototype: G +Help: ellgens(E): if E is an elliptic curve as output by ellinit(), + return the generators of the Mordell-Weil group associated to the curve. + This function depends on the curve being referenced in the elldata database. + Index: pari/src/functions/elliptic_curves/ellidentify =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ pari/src/functions/elliptic_curves/ellidentify 2005-06-03 14:34:13.000000000 +0200 @@ -0,0 +1,8 @@ +Function: ellidentify +Section: elliptic_curves +C-Name: ellidentify +Prototype: G +Help: ellidentify(E): if E is an elliptic curve as output by ellinit(), + return [[name, M],C] where name is the name of the curve in J.E.Cremona + database, M the minimal model and C the curve changes (see ellchangecurve). + Index: pari/src/functions/elliptic_curves/ellsearch =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ pari/src/functions/elliptic_curves/ellsearch 2005-06-03 14:34:13.000000000 +0200 @@ -0,0 +1,9 @@ +Function: ellsearch +Section: elliptic_curves +C-Name: ellsearch +Prototype: G +Help: ellsearch(N): if N is an integer, it is taken as a conductor else if N is + a string, it can be a curve name ("11A1"), a isogeny class ("11A") or a + conductor "11". Return all curves in the elldata database that match the + property. + Index: pari/src/headers/paridecl.h =================================================================== --- pari.orig/src/headers/paridecl.h 2005-06-03 14:28:37.000000000 +0200 +++ pari/src/headers/paridecl.h 2005-06-03 14:34:13.000000000 +0200 @@ -867,12 +867,16 @@ GEN ellap0(GEN e, GEN p, long flag); GEN elleisnum(GEN om, long k, long flag, long prec); GEN elleta(GEN om, long prec); +GEN ellgens(GEN E); GEN ellglobalred(GEN e1); GEN ellheight0(GEN e, GEN a, long flag,long prec); +GEN ellidentify(GEN E); GEN ellinit0(GEN x,long flag,long prec); GEN elllocalred(GEN e, GEN p1); GEN ellminimalmodel(GEN E, GEN *ptv); long ellrootno(GEN e, GEN p); +GEN ellsearch(GEN A); +GEN ellsearchcurve(GEN A); GEN ellsigma(GEN om, GEN z, long flag, long prec); GEN elltaniyama(GEN e, long prec); GEN elltors0(GEN e, long flag); @@ -887,6 +891,7 @@ GEN ordell(GEN e, GEN x, long prec); GEN orderell(GEN e, GEN p); GEN pointch(GEN x, GEN ch); +GEN pointchinv(GEN x, GEN ch); GEN pointell(GEN e, GEN z, long prec); GEN powell(GEN e, GEN z, GEN n); GEN smallinitell(GEN x); Index: pari/src/modules/elldata.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ pari/src/modules/elldata.c 2005-06-03 14:34:13.000000000 +0200 @@ -0,0 +1,192 @@ +/* $Id: $ + +Copyright (C) 2005 The PARI group. + +This file is part of the PARI/GP package. + +PARI/GP is free software; you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation. It is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY WHATSOEVER. + +Check the License for details. You should have received a copy of it, along +with the package; see the file 'COPYING'. If not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/********************************************************************/ +/** **/ +/** INTERFACE TO JOHN CREMONA ELLIPTIC CURVES DATABASE **/ +/** **/ +/********************************************************************/ +#include "pari.h" +#include "paripriv.h" + +static long +strtoclass(const char *s) +{ + int c=0; + while (*s && *s<='9') s++; + if (!*s) return -1; + while ('A'<=*s && *s<='Z') + c=26*c+*(s++)-'A'; + return c; +} + +/*Take a curve name like "100A2" and set + * f to the conductor, (100) + * c to the isogeny class (in base 26), ("A" or 1) + * i to the curve index (2). + * return 0 if garbage is found at the end. + */ +static int +ellparsename(const char *s, long *f, long *c, long *i) +{ + *f=-1; *c=-1; *i=-1; + if (*s<'0' || *s>'9') return !*s; + *f=0; + while ('0'<=*s && *s<='9') + *f=10**f+*(s++)-'0'; + if (*s<'A' || *s>'Z') return !*s; + *c=0; + while ('A'<=*s && *s<='Z') + *c=26**c+*(s++)-'A'; + if (*s<'0' || *s>'9') return !*s; + *i=0; + while ('0'<=*s && *s<='9') + *i=10**i+*(s++)-'0'; + return !*s; +} + +GEN +ellcondfile(long f) +{ + long n=f/1000; + char *s = gpmalloc(strlen(pari_datadir) + 13 + 20); + FILE *stream; + GEN V; + sprintf(s, "%s/elldata/ell%ld", pari_datadir, n); + stream = fopen(s,"r"); + if (!stream) + err(talker,"Elliptic curves files not available for conductor %ld\n" + "[missing %s]",f,s); + V = lisGEN(stream); + if (!V || typ(V)!=t_VEC ) + err(talker,"Elliptic files %s not compatible\n",s); + fclose(stream); + free(s); + return V; +} + +GEN +ellcondlist(long f) +{ + pari_sp ltop=avma; + GEN V=ellcondfile(f); + long i; + for (i=1; i<lg(V); i++) + if (cmpis(gmael(V,i,1), f)>=0) + break; + if (i==lg(V) || !equalis(gmael(V,i,1), f)) + { + avma=ltop; + return cgetg(1,t_VEC); + } + return gerepilecopy(ltop, vecslice(gel(V,i),2, lg(gel(V,i))-1)); +} + +static GEN +ellsearchbyname(GEN V, GEN name) +{ + long j; + for (j=1; j<lg(V); j++) + if (gequal(gmael(V,j,1), name)) + return gel(V,j); + err(talker,"No such elliptic curve"); + return NULL; +} + +static GEN +ellsearchbyclass(GEN V, long c) +{ + long i,j,n; + GEN res; + for (n=0,j=1; j<lg(V); j++) + if (strtoclass(GSTR(gmael(V,j,1)))==c) + n++; + res=cgetg(n+1,t_VEC); + for (i=1,j=1; j<lg(V); j++) + if (strtoclass(GSTR(gmael(V,j,1)))==c) + res[i++]=V[j]; + return res; +} + +GEN +ellsearch(GEN A) +{ + pari_sp ltop=avma; + long f, c, i; + GEN V; + if (typ(A)==t_INT) + { + f=itos(A); + c=-1; + i=-1; + } + else if (typ(A)==t_STR) + { + if (!ellparsename(GSTR(A),&f,&c,&i)) + err(talker,"Incorrect curve name in ellsearch"); + } + else + err(typeer,"ellsearch"); + V=ellcondlist(f); + if (c<0) + return V; + if (i<0) + return gerepilecopy(ltop, ellsearchbyclass(V,c)); + return gerepilecopy(ltop, ellsearchbyname(V,A)); +} + +GEN +ellsearchcurve(GEN name) +{ + pari_sp ltop=avma; + long f, c, i; + if (!ellparsename(GSTR(name),&f,&c,&i)) + err(talker,"Incorrect curve name in ellsearch"); + if (f<0 || c<0 || i<0) + err(talker,"Incomplete curve name in ellsearch"); + return gerepilecopy(ltop, ellsearchbyname(ellcondlist(f), name)); +} + +GEN +ellidentify(GEN E) +{ + pari_sp ltop=avma; + GEN G, V, M; + long j; + checkell(E); + G=ellglobalred(E); + V=ellcondlist(itos(gel(G,1))); + M=vecslice(coordch(E,gel(G,2)),1,5); + for (j=1; j<lg(V); j++) + if (gequal(gmael(V,j,2), M)) + return gerepilecopy(ltop, mkvec2(gel(V,j),gel(G,2))); + err(talker,"No such elliptic curve in database"); + return NULL; +} + +GEN +ellgens(GEN E) +{ + pari_sp ltop=avma; + if (typ(E)==t_STR) + return gerepilecopy(ltop, gel(ellsearchcurve(E), 3)); + else + { + GEN V=ellidentify(E); + GEN gens=gmael(V,1,3); + GEN W=pointchinv(gens,gel(V,2)); + return gerepileupto(ltop,W); + } +} Index: pari/src/modules/elliptic.c =================================================================== --- pari.orig/src/modules/elliptic.c 2005-06-03 14:28:37.000000000 +0200 +++ pari/src/modules/elliptic.c 2005-06-03 14:34:13.000000000 +0200 @@ -148,6 +148,8 @@ { pari_sp av = avma; GEN y = cgetg(14,t_VEC); + if (typ(x)==t_STR) + x=gel(ellsearchcurve(x),2); smallinitell0(x,y); return gerepilecopy(av,y); } @@ -408,6 +410,8 @@ initell(GEN x, long prec) { pari_sp av = avma; + if (typ(x)==t_STR) + x=gel(ellsearchcurve(x),2); return gerepilecopy(av, initell0(x,prec)); } @@ -595,6 +599,49 @@ return gerepilecopy(av,y); } +/* x = u^2*X +r + * y = u^3*Y +s*u^2*X+t */ +static GEN +pointchinv0(GEN x, GEN u2, GEN u3, GEN r, GEN s, GEN t) +{ + GEN u2X, z; + GEN X=gel(x,1), Y=gel(x,2); + if (is_inf(x)) return x; + + u2X = gmul(u2,X); + z = cgetg(3, t_VEC); + z[1] = ladd(u2X, r); + z[2] = ladd(gmul(u3, Y), gadd(gmul(s, u2X), t)); + return z; +} + +GEN +pointchinv(GEN x, GEN ch) +{ + GEN y, u, r, s, t, u2, u3; + long tx, i, lx = lg(x); + pari_sp av = avma; + + checkpt(x); checkch(ch); + if (lx < 2) return gcopy(x); + u = (GEN)ch[1]; + r = (GEN)ch[2]; + s = (GEN)ch[3]; + t = (GEN)ch[4]; + tx = typ(x[1]); + u2=gsqr(u); u3=gmul(u,u2); + if (is_matvec_t(tx)) + { + y = cgetg(lx,tx); + for (i=1; i<lx; i++) + y[i] = (long)pointchinv0((GEN)x[i],u2,u3,r,s,t); + } + else + y = pointchinv0(x,u2,u3,r,s,t); + return gerepilecopy(av,y); +} + + static long ellexpo(GEN E) {