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)
 {