/* Some functions for working with models of elliptic curves in GP
Author: John Cremona (john.cremona@nottingham.ac.uk)
Last edited: 2007-02-21
*/
\\ For curves defined over Q these can test integrality locally or
\\ globally, and transform to an integral model by scaling (as in the
\\ static function ellintegralmodel() in elliptic.c); and test
\\ minimality locally or globally; transforming to a minimal model is
\\ already provided in minimalmodel().
\\ In all the followign functions it is assumed that the elliptic
\\ curve e has rational coefficients (not necessarily integral) but we
\\ do not check this!
\\ In the functions which return a new model we would also like to
\\ return the transformation [u,0,0,0] used, as in the built-in function
\\ ellminimalmodel; but user-defined functions cannot have reference
\\ parameters :( -- but for the future, we do compute the factor u such
\\ that output = ellchangecurve(e,[u,0,0,0])
\\
\\ INTEGRALITY FUNCTIONS
\\
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\ Checking integrality: cheats by using type-checking
\\ e is an ellinit structure of any length (5,13 or 19)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{
ellisintegral(e)=
prod(j=1,5,(type(e[j])=="t_INT"));
}
/* Examples:
ellisintegral([0,0,1,-7,6])
ellisintegral(ellchangecurve(ellinit([0,0,1,-7,6]),[2,0,0,0]))
ellisintegral(ellchangecurve(ellinit([0,0,1,-7,6]),[1/2,0,0,0]))
returns 1 (true), 0 (false), 1 (true)
*/
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\ Checking local integrality at a prime:
\\ e is an ellinit structure of any length (5,13 or 19),
\\ p should be a prime
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{
ellislocallyintegral(e,p)=
prod(j=1,5,(valuation(e[j],p)>=0));
}
/* Example:
e = ellchangecurve(ellinit([0,0,1,-7,6]),[2,0,0,0]);
ellislocallyintegral(e,2)
ellislocallyintegral(e,3)
returns 0 (false), 1 (true); e.ai is [0, 0, 1/8, -7/16, 3/32] here.
*/
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\ Making locally integral at a prime:
\\ e is an ellinit structure of any length (5,13 or 19),
\\ returns same length structure;
\\ p should be a prime
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{
elllocalintegralmodel(e,p)=
local(ai,u);
u=p^vecmax(vector(5,k,-valuation(e[k],p)/if(k==5,6,k)));
ai=vector(5,k,e[k]*u^(if(k==5,6,k)));
if(#e==5,ai,ellinit(ai,#e==13));
}
/* Example:
e = ellchangecurve(ellinit([0,0,1,-7,6]),[6,0,0,0]).ai
elllocalintegralmodel(e,2)
elllocalintegralmodel(e,3)
elllocalintegralmodel(elllocalintegralmodel(e,2),3)
returns
[0, 0, 1/216, -7/1296, 1/7776]
[0, 0, 1/27, -7/81, 2/243]
[0, 0, 1/8, -7/16, 3/32]
[0, 0, 1, -7, 6]
*/
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\ Making globally integral:
\\ e is an ellinit structure of any length (5,13 or 19)
\\ returns same length structure
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\ Method: for each ai in turn and each p dividing denom(ai) we call
\\ the local version to scale up the short ai vector
\\
\\ To get the global u take the product of the local ones.
{
ellintegralmodel(e)=
local(ai,plist);
ai=vecextract(e,[1,2,3,4,5]);
for(i=1,5,plist=factor(denominator(ai[i]))[,1]~;
for(j=1,#plist,ai=elllocalintegralmodel(ai,plist[j])));
if(#e==5,ai,ellinit(ai,#e==13));
}
/* Example:
e = ellchangecurve(ellinit([0,0,1,-7,6]),[6,0,0,0]).ai
ellintegralmodel(e)
returns
[0, 0, 1/216, -7/1296, 1/7776]
[0, 0, 1, -7, 6]
*/
\\
\\ MINIMALITY FUNCTIONS
\\
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\ test whether (integer) c4,c6 is a valid pair of invariants
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{
ellvalidc4c6(c4,c6)=local(d=c4^3-c6^2);
if(d==0,return(0));
if(d%1728!=0,return(0));
if(valuation(c4,3)==2,return(0));
if(c6%4==3, return(1));
if(c4%16!=0, return(0));
d=c6%32;
(d==0)||(d==8)
}
/* Examples:
ellvalidc4c6(336,-5400)
returns 1
ellvalidc4c6(random(),random())
probably returns 0
*/
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\ test local minimality at 2
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{
ellislocallyminimalat2(e)=
ellislocallyintegral(e,2) &&
(valuation(e.c4,2)<4) || (valuation(e.c6,2)<6) ||
!ellvalidc4c6(e.c4>>4,e.c6>>6)
}
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\ test local minimality at 3
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{
ellislocallyminimalat3(e)=
ellislocallyintegral(e,3) &&
(valuation(e.c4,3)<4) || (valuation(e.c6,3)<6) ||
!ellvalidc4c6(e.c4/3^4,e.c6/3^6)
}
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\ test local minimality at arbitrary p
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{
ellislocallyminimal(e,p)=
ellislocallyintegral(e,p) &&
if(p==2,ellislocallyminimalat2(e),
if(p==3,ellislocallyminimalat3(e),
(valuation(e.c4,p)<4)||(valuation(e.c6,p)<6)))
}
/* Examples:
e=ellinit([0,0,1,-7,6]);
e1=ellchangecurve(e,[1/120,0,0,0]);
ellisintegral(e1)
ellislocallyminimal(e1,2)
ellislocallyminimal(e1,3)
ellislocallyminimal(e1,5)
ellislocallyminimal(e1,7)
returns
1 0 0 0 1
*/
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\ test global minimality
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{
ellisminimal(e)=
local(badp);
if(!ellisintegral(e),return(0));
badp=factor(abs(e.disc))[,1]~;
for(i=1,#badp,if(!ellislocallyminimal(e,badp[i]),return(0)));
1
}
/* Examples:
e=ellinit([0,0,1,-7,6]);
e1=ellchangecurve(e,[1/120,0,0,0]);
ellisintegral(e1)
ellisminimal(e)
ellisminimal(e1)
returns 1 1 0
*/
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\ Construct e from c4, c6
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{
ellinitfromc4c6(c4,c6)=
local(a1,a2,a3,a4,a6,b2,b4,b6);
if(!ellvalidc4c6(c4,c6),
print("Error in ellinitfromc4c6(): ",c4,",",c6," are not valid!");
return(0),
b2 = centerlift(Mod(-c6,12));
b4 = (b2^2-c4)/24;
b6 = (-b2^3+36*b2*b4-c6)/216;
a1 = b2%2;
a3 = b6%2;
a2 = (b2-a1)/4;
a4 = (b4-a1*a3)/2;
a6 = (b6-a3)/4;
ellinit([a1,a2,a3,a4,a6]));
}
/* Examples:
e=ellinitfromc4c6(336, -5400);
e.ai
returns
[0, 0, 1, -7, 6]
*/
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\ Given valid integral c4, c6 return those of a minimal model
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{
ellminimisec4c6(c4,c6)=
local(u,d,g,plist,p,a,b);
u=1;
d = (c4^3-c6^2)/1728;
g=gcd(c4,c6); if(g==1,return([c4,c6]));
g=gcd(c6^2,d); if(g==1,return([c4,c6]));
plist = factor(g)[,1]~;
for(i=1,#plist,
p = plist[i];
d = floor(valuation(g,p)/12);
if(p==2,
a = (c4 >> (4*d)) % 16;
b = (c6 >> (6*d)) % 32;
if ((( (b%4)!=3) && !( (a==0) && (( b==0) || (b==8) ))),d-=1));
if(p==3, if (valuation(c6,3)==(6*d + 2), d-=1));
if(d>0, u *= p^d));
[c4/u^4,c6/u^6];
}
/* Examples:
e=ellinit([0,0,1,-7,6]);
e1=ellchangecurve(e,[1/120,0,0,0]);
ellminimisec4c6(e1.c4,e1.c6)
returns
[336, -5400]
*/
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\ Minimal model without Tate's algorithm:
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{
ellminimalmodel2(e)=
local(c4c6);
e=ellintegralmodel(e);
c4c6=ellminimisec4c6(e.c4,e.c6);
ellinitfromc4c6(c4c6[1],c4c6[2]);
}
/* Example:
e0=ellinit([6,-3,9,-16,-14]);
ellminimalmodel2(e0).ai==ellminimalmodel(e0).ai
returns
1
*/