/************************************************************/ /* Author : Gonzalo Tornaria * Date : December 2003 * * * Explicit routines to compute the central value of the L-series of * quadratic twists using the data in and . * NOT practical to compute lots of twists of the same elliptic curve: * all the coefficients of each theta series can and should be computed * at the same time, in a optimized routine. * In pari, qfrep, but only available from version 2.2.7 * (anyway, this is LOTS faster than using elllseries on the twist!!) * * Take this as an example of how to use the data, as well as the precise * formulas to compute the central value of the twisted L-series. * I've checked this at least for all the available data, and for all * twists by discriminants less than 1000. * * Imaginary case based on Gross, 1987 (Heights and the Special Values of L-series) * Real case based on joint work with Ariel Pacetti, in preparation. * */ /************************************************************/ /* function to compute the coefficient of a theta series; * qfminim is not flexible enough to do it all at once, * and qfrep is not available until 2.2.7 (alpha) */ q3_coeff(q,i)= { local(A); A=[2*q[1],q[6],q[5];q[6],2*q[2],q[4];q[5],q[4],2*q[3]]; qfminim(A,2*i,0)[1]-qfminim(A,2*i-1,0)[1]; } /* wrappers on the elliptic curve data */ tw_ell(tw,D=1)=ellinit(ellquadtwist(tw[1][4],D)); tw_deg(tw)=tw[1][3]; tw_level(tw)=tw[1][2]; tw_name(tw)=tw[1][1]; /* compute a coefficient of the given linear combination of theta series */ tw_coeff(tw,n) = sum(i=1,length(tw[2]),tw[2][i]*q3_coeff(tw[3][i],n)); /* The height of the linear combination, for the formula */ tw_height(tw) = sum(i=1,length(tw[2]),tw[4][i]*tw[2][i]^2); /************************************************************/ /* Central value of the L-series of the twist -- using theta series */ ctwist(tw,D,epsilon=1E-20)= { local(loc,L,coeff); loc = ctwist_local(tw,D); L = ctwist_global(tw,D); coeff = tw_coeff(tw,abs(D)); if(abs(L)2) && (D%Nf[i,1]==0), 0, 1) ) / 2; } /* */ ctwist_isodd(tw, D) = { sign(D)*kronecker(D,tw_level(tw))==-ellrootno(tw_ell(tw)) } /* The global constant (D is only used for the sign) */ ctwist_global(tw,sgn) = { local(N,e,L); N=tw_level(tw); e=tw_ell(tw, if(sgn>0,-N,1)); L=elllseries(e,1); L / e.area * tw_height(tw) / tw_deg(tw) / if(sgn>0, sqrt(N)*(1+N),1); /* factor for the sqrt and the degree */ } /************************************************************/ /* equation of the quadratic twist of an elliptic curve */ ellquadtwist(E,D)= {if(D%4!=0&&D%4!=1,error("not a discriminant")); [E[1]*D,D*(E[2]-E[1]^2/4*(D-1)),E[3]*D^2,D^2*(E[4]-E[1]*E[3]/2*(D-1)), D^3*(E[5]-E[3]^2/4*(D-1))]} /* Central value of the L-series of the twist -- using elllseries */ etwist(tw,D)=elllseries(tw_ell(tw,D),1); /************************************************************/ /* TESTING (see and */ TAB = " "; CRTAB = " "; CRTABTAB = " "; CRTABTABTAB = " "; /* This verifies that ctwist == etwist * (for fundamental discriminants of given sign up to bound) */ verify_twist(tw,sgn,bound=100,epsilon=1E-20,debug=0,first=0) = { local(L,e,eok,loc,coeff, count_odd,count_NA,count_zero, lhs,diff,bug,count,maxdiff); L = ctwist_global(tw, sgn); for(i=1,bound+1,D=sgn*i; print1(CRTABTABTAB, "(odd=", count_odd, ", N/A=", count_NA); if(abs(L)>epsilon, if(count_zero, print1(", zero=",count_zero)); print1(", good=",count-bug-count_zero,"/",count-count_zero); , print1(", ZERO=",count-bug,"/",count); ); if(bug,print1(", BUG=",bug)); print1(")"); if(first && count>bug+count_zero, break); if(i<=bound && isfundamental(D), print1(CRTAB,D," "); loc=ctwist_local(tw,D); lhs=L*loc*sqrt(abs(D)); coeff=tw_coeff(tw,abs(D)); eok=0; /* This deals with the rest of cases for which the formula does * not give us interesting information about L(D) */ /* This handles the cases where the local term is 0 */ if(loc==0, if(first, next); if(ctwist_isodd(tw,D), /* some of this corresponds to the twist having odd rank */ count_odd++; /* we check that L(D) = 0, just in case */ if(!eok, e=etwist(tw,D);eok=1); if(e!=0, print(CRTAB,[D,e,lhs*e,coeff]," L(D) should be zero")); , /* otherwise, the formula does not give information */ count_NA++; ); /* In any case, this alone verifies the formula */ if(coeff!=0, if(!eok, e=etwist(tw,D);eok=1); print(CRTAB,[D,e,lhs*e,coeff]," coeff should be zero") ); next; ); /* Now we are dealing with a nontrivial case of the formula !! */ count++; if(coeff==0, count_zero++); if(abs(lhs)>epsilon, if(!eok, e=etwist(tw,D);eok=1)); diff=abs(lhs*e-coeff^2); if(diff>epsilon,bug++); if(diff>epsilon||debug, if(!eok,e=etwist(tw,D);eok=1); print(CRTAB,[D,e,lhs*e,coeff]) ); maxdiff=max(maxdiff,diff); )); print(CRTABTAB,if(bug,"bug","ok")); } verify_twist_first(tw,sgn,bound=1000,epsilon=1E-20,debug=0) = { local(L,i,D,coeff,e,lhsdiff); L=ctwist_global(tw, sgn); if(abs(L)epsilon, break) )); if(abs(e)>epsilon, coeff=tw_coeff(tw,abs(D)); if(coeff||debug, print1(CRTABTABTAB,[D,e,0,coeff])); print(CRTAB,D,TAB,if(coeff,"BUG","ZERO")); , print(CRTABTAB,"N/A"); ); , /* do the NONZERO case */ for(i=1,bound,D=sgn*i;if(isfundamental(D) && ctwist_local(tw,D), coeff=tw_coeff(tw,abs(D)); if(coeff, break) )); if(coeff, e=etwist(tw,D); lhs=L*ctwist_local(tw,D)*sqrt(abs(D)); diff=abs(lhs*e-coeff^2); if(diff>epsilon||debug, print1(CRTABTABTAB,[D,e,lhs*e,coeff])); print(CRTAB,D,TAB,if(diff>epsilon,"BUG","ok")); , print(CRTABTAB,"N/A"); ); ); } /* This verifies that ctwist == etwist * (for imaginary fundamental discriminants up to bound) */ verify_twist_i(tw,bound=100,epsilon=1E-20,debug=0) = { verify_twist(tw,-1,bound,epsilon,debug); } verify_twist_first_i(tw,bound=1000,epsilon=1E-20,debug=0) = { verify_twist_first(tw,-1,bound,epsilon,debug); } /* This verifies that ctwist == etwist * (for real fundamental discriminants up to bound) */ verify_twist_r(tw,bound=100,epsilon=1E-20,debug=0) = { verify_twist(tw,+1,bound,epsilon,debug); } verify_twist_first_r(tw,bound=1000,epsilon=1E-20,debug=0) = { verify_twist_first(tw,+1,bound,epsilon,debug); } /************************************************************/