| 1 |
""" |
|---|
| 2 |
Elliptic curves over the rational numbers |
|---|
| 3 |
|
|---|
| 4 |
AUTHORS: |
|---|
| 5 |
-- William Stein (2005): first version |
|---|
| 6 |
-- William Stein (2006-02-26): fixed Lseries_extended which didn't work |
|---|
| 7 |
because of changes elsewhere in SAGE. |
|---|
| 8 |
-- David Harvey (2006-09): Added padic_E2, padic_sigma, padic_height, |
|---|
| 9 |
padic_regulator methods. |
|---|
| 10 |
-- David Harvey (2007-02): reworked padic-height related code |
|---|
| 11 |
-- Christian Wuthrich (2007): added padic sha computation |
|---|
| 12 |
-- David Roe (2007-9): moved sha, l-series and p-adic functionality to separate files. |
|---|
| 13 |
-- John Cremona (2008-01) |
|---|
| 14 |
-- Tobias Nagel & Michael Mardaus (2008-07): added integral_points |
|---|
| 15 |
""" |
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 |
|
|---|
| 32 |
import ell_point |
|---|
| 33 |
import formal_group |
|---|
| 34 |
import rational_torsion |
|---|
| 35 |
from ell_generic import EllipticCurve_generic |
|---|
| 36 |
from ell_number_field import EllipticCurve_number_field |
|---|
| 37 |
|
|---|
| 38 |
import sage.groups.all |
|---|
| 39 |
import sage.rings.arith as arith |
|---|
| 40 |
import sage.rings.all as rings |
|---|
| 41 |
import sage.rings.number_field.number_field as number_field |
|---|
| 42 |
import sage.misc.misc as misc |
|---|
| 43 |
from sage.misc.all import verbose |
|---|
| 44 |
import sage.functions.constants as constants |
|---|
| 45 |
import sage.modular.modform.constructor |
|---|
| 46 |
import sage.modular.modform.element |
|---|
| 47 |
from sage.misc.functional import log |
|---|
| 48 |
from sage.rings.padics.factory import Zp, Qp |
|---|
| 49 |
|
|---|
| 50 |
|
|---|
| 51 |
|
|---|
| 52 |
|
|---|
| 53 |
|
|---|
| 54 |
|
|---|
| 55 |
import sage.matrix.all as matrix |
|---|
| 56 |
import sage.databases.cremona |
|---|
| 57 |
from sage.libs.pari.all import pari |
|---|
| 58 |
import sage.functions.transcendental as transcendental |
|---|
| 59 |
import math |
|---|
| 60 |
from sage.calculus.calculus import sqrt, arcsin, floor, ceil |
|---|
| 61 |
import sage.libs.mwrank.all as mwrank |
|---|
| 62 |
import constructor |
|---|
| 63 |
from sage.interfaces.all import gp |
|---|
| 64 |
|
|---|
| 65 |
import ell_modular_symbols |
|---|
| 66 |
import padic_lseries |
|---|
| 67 |
import padics |
|---|
| 68 |
|
|---|
| 69 |
from lseries_ell import Lseries_ell |
|---|
| 70 |
|
|---|
| 71 |
import mod5family |
|---|
| 72 |
|
|---|
| 73 |
from sage.rings.all import ( |
|---|
| 74 |
PowerSeriesRing, LaurentSeriesRing, O, |
|---|
| 75 |
infinity as oo, |
|---|
| 76 |
Integer, |
|---|
| 77 |
Integers, |
|---|
| 78 |
IntegerRing, RealField, |
|---|
| 79 |
ComplexField, RationalField) |
|---|
| 80 |
|
|---|
| 81 |
import gp_cremona |
|---|
| 82 |
import sea |
|---|
| 83 |
|
|---|
| 84 |
from gp_simon import simon_two_descent |
|---|
| 85 |
|
|---|
| 86 |
import ell_tate_curve |
|---|
| 87 |
|
|---|
| 88 |
factor = arith.factor |
|---|
| 89 |
exp = math.exp |
|---|
| 90 |
mul = misc.mul |
|---|
| 91 |
next_prime = arith.next_prime |
|---|
| 92 |
kronecker_symbol = arith.kronecker_symbol |
|---|
| 93 |
|
|---|
| 94 |
Q = RationalField() |
|---|
| 95 |
C = ComplexField() |
|---|
| 96 |
R = RealField() |
|---|
| 97 |
Z = IntegerRing() |
|---|
| 98 |
IR = rings.RealIntervalField(20) |
|---|
| 99 |
|
|---|
| 100 |
_MAX_HEIGHT=21 |
|---|
| 101 |
|
|---|
| 102 |
|
|---|
| 103 |
|
|---|
| 104 |
|
|---|
| 105 |
CMJ={ 0: -3, 54000: -12, -12288000: -27, 1728: -4, 287496: -16, |
|---|
| 106 |
-3375: -7, 16581375: -28, 8000: -8, -32768: -11, -884736: -19, |
|---|
| 107 |
-884736000: -43, -147197952000: -67, -262537412640768000: -163} |
|---|
| 108 |
|
|---|
| 109 |
|
|---|
| 110 |
|
|---|
| 111 |
class EllipticCurve_rational_field(EllipticCurve_number_field): |
|---|
| 112 |
""" |
|---|
| 113 |
Elliptic curve over the Rational Field. |
|---|
| 114 |
""" |
|---|
| 115 |
def __init__(self, ainvs, extra=None): |
|---|
| 116 |
if extra != None: |
|---|
| 117 |
ainvs = extra |
|---|
| 118 |
if isinstance(ainvs, str): |
|---|
| 119 |
label = ainvs |
|---|
| 120 |
X = sage.databases.cremona.CremonaDatabase()[label] |
|---|
| 121 |
EllipticCurve_number_field.__init__(self, Q, X.a_invariants()) |
|---|
| 122 |
for attr in ['rank', 'torsion_order', 'cremona_label', 'conductor', |
|---|
| 123 |
'modular_degree', 'gens', 'regulator']: |
|---|
| 124 |
s = "_EllipticCurve_rational_field__"+attr |
|---|
| 125 |
if hasattr(X,s): |
|---|
| 126 |
setattr(self, s, getattr(X, s)) |
|---|
| 127 |
return |
|---|
| 128 |
EllipticCurve_number_field.__init__(self, Q, ainvs) |
|---|
| 129 |
self.__np = {} |
|---|
| 130 |
self.__gens = {} |
|---|
| 131 |
self.__rank = {} |
|---|
| 132 |
self.__regulator = {} |
|---|
| 133 |
if self.base_ring() != Q: |
|---|
| 134 |
raise TypeError, "Base field (=%s) must be the Rational Field."%self.base_ring() |
|---|
| 135 |
|
|---|
| 136 |
def _set_rank(self, r): |
|---|
| 137 |
""" |
|---|
| 138 |
Internal function to set the cached rank of this elliptic curve to r. |
|---|
| 139 |
|
|---|
| 140 |
WARNING: No checking is done! Not intended for use by users. |
|---|
| 141 |
|
|---|
| 142 |
EXAMPLES: |
|---|
| 143 |
sage: E=EllipticCurve('37a1') |
|---|
| 144 |
sage: E._set_rank(99) # bogus value -- not checked |
|---|
| 145 |
sage: E.rank() # returns bogus cached value |
|---|
| 146 |
99 |
|---|
| 147 |
sage: E.gens() # causes actual rank to be computed |
|---|
| 148 |
[(0 : -1 : 1)] |
|---|
| 149 |
sage: E.rank() # the correct rank |
|---|
| 150 |
1 |
|---|
| 151 |
""" |
|---|
| 152 |
self.__rank = {} |
|---|
| 153 |
self.__rank[True] = Integer(r) |
|---|
| 154 |
|
|---|
| 155 |
def _set_torsion_order(self, t): |
|---|
| 156 |
""" |
|---|
| 157 |
Internal function to set the cached torsion order of this elliptic curve to t. |
|---|
| 158 |
|
|---|
| 159 |
WARNING: No checking is done! Not intended for use by users. |
|---|
| 160 |
|
|---|
| 161 |
EXAMPLES: |
|---|
| 162 |
sage: E=EllipticCurve('37a1') |
|---|
| 163 |
sage: E._set_torsion_order(99) # bogus value -- not checked |
|---|
| 164 |
sage: E.torsion_order() # returns bogus cached value |
|---|
| 165 |
99 |
|---|
| 166 |
sage: T = E.torsion_subgroup() # causes actual torsion to be computed |
|---|
| 167 |
sage: E.torsion_order() # the correct value |
|---|
| 168 |
1 |
|---|
| 169 |
""" |
|---|
| 170 |
self.__torsion_order = Integer(t) |
|---|
| 171 |
|
|---|
| 172 |
def _set_cremona_label(self, L): |
|---|
| 173 |
""" |
|---|
| 174 |
Internal function to set the cached label of this elliptic curve to L. |
|---|
| 175 |
|
|---|
| 176 |
WARNING: No checking is done! Not intended for use by users. |
|---|
| 177 |
|
|---|
| 178 |
EXAMPLES: |
|---|
| 179 |
sage: E=EllipticCurve('37a1') |
|---|
| 180 |
sage: E._set_cremona_label('bogus') |
|---|
| 181 |
sage: E.label() |
|---|
| 182 |
'bogus' |
|---|
| 183 |
sage: E.database_curve().label() |
|---|
| 184 |
'37a1' |
|---|
| 185 |
sage: E.label() # no change |
|---|
| 186 |
'bogus' |
|---|
| 187 |
sage: E._set_cremona_label(E.database_curve().label()) |
|---|
| 188 |
sage: E.label() # now it is correct |
|---|
| 189 |
'37a1' |
|---|
| 190 |
""" |
|---|
| 191 |
self.__cremona_label = L |
|---|
| 192 |
|
|---|
| 193 |
def _set_conductor(self, N): |
|---|
| 194 |
""" |
|---|
| 195 |
Internal function to set the cached conductor of this elliptic curve to N. |
|---|
| 196 |
|
|---|
| 197 |
WARNING: No checking is done! Not intended for use by users. |
|---|
| 198 |
Setting to the wrong value will cause strange problems (see |
|---|
| 199 |
examples). |
|---|
| 200 |
|
|---|
| 201 |
EXAMPLES: |
|---|
| 202 |
sage: E=EllipticCurve('37a1') |
|---|
| 203 |
sage: E._set_conductor(99) # bogus value -- not checked |
|---|
| 204 |
sage: E.conductor() # returns bogus cached value |
|---|
| 205 |
99 |
|---|
| 206 |
|
|---|
| 207 |
This will not work since the conductor is used when searching |
|---|
| 208 |
the database: |
|---|
| 209 |
sage: E._set_conductor(E.database_curve().conductor()) |
|---|
| 210 |
Traceback (most recent call last): |
|---|
| 211 |
... |
|---|
| 212 |
RuntimeError: Elliptic curve ... not in the database. |
|---|
| 213 |
sage: E._set_conductor(EllipticCurve(E.a_invariants()).database_curve().conductor()) |
|---|
| 214 |
sage: E.conductor() # returns correct value |
|---|
| 215 |
37 |
|---|
| 216 |
""" |
|---|
| 217 |
self.__conductor_pari = Integer(N) |
|---|
| 218 |
|
|---|
| 219 |
def _set_modular_degree(self, deg): |
|---|
| 220 |
""" |
|---|
| 221 |
Internal function to set the cached modular degree of this elliptic curve to deg. |
|---|
| 222 |
|
|---|
| 223 |
WARNING: No checking is done! |
|---|
| 224 |
|
|---|
| 225 |
EXAMPLES: |
|---|
| 226 |
sage: E=EllipticCurve('5077a1') |
|---|
| 227 |
sage: E.modular_degree() |
|---|
| 228 |
1984 |
|---|
| 229 |
sage: E._set_modular_degree(123456789) |
|---|
| 230 |
sage: E.modular_degree() |
|---|
| 231 |
123456789 |
|---|
| 232 |
sage: E._set_modular_degree(E.database_curve().modular_degree()) |
|---|
| 233 |
sage: E.modular_degree() |
|---|
| 234 |
1984 |
|---|
| 235 |
""" |
|---|
| 236 |
self.__modular_degree = Integer(deg) |
|---|
| 237 |
|
|---|
| 238 |
def _set_gens(self, gens): |
|---|
| 239 |
""" |
|---|
| 240 |
Internal function to set the cached generators of this elliptic curve to gens. |
|---|
| 241 |
|
|---|
| 242 |
WARNING: No checking is done! |
|---|
| 243 |
|
|---|
| 244 |
EXAMPLES: |
|---|
| 245 |
sage: E=EllipticCurve('5077a1') |
|---|
| 246 |
sage: E.rank() |
|---|
| 247 |
3 |
|---|
| 248 |
sage: E.gens() # random |
|---|
| 249 |
[(-2 : 3 : 1), (-7/4 : 25/8 : 1), (1 : -1 : 1)] |
|---|
| 250 |
sage: E._set_gens([]) # bogus list |
|---|
| 251 |
sage: E.rank() # unchanged |
|---|
| 252 |
3 |
|---|
| 253 |
sage: E._set_gens(E.database_curve().gens()) |
|---|
| 254 |
sage: E.gens() |
|---|
| 255 |
[(-2 : 3 : 1), (-7/4 : 25/8 : 1), (1 : -1 : 1)] |
|---|
| 256 |
""" |
|---|
| 257 |
self.__gens = {} |
|---|
| 258 |
self.__gens[True] = [self.point(x, check=True) for x in gens] |
|---|
| 259 |
self.__gens[True].sort() |
|---|
| 260 |
|
|---|
| 261 |
def is_integral(self): |
|---|
| 262 |
""" |
|---|
| 263 |
Returns True if this elliptic curve has integral coefficients (in Z) |
|---|
| 264 |
|
|---|
| 265 |
EXAMPLES: |
|---|
| 266 |
sage: E=EllipticCurve(QQ,[1,1]); E |
|---|
| 267 |
Elliptic Curve defined by y^2 = x^3 + x +1 over Rational Field |
|---|
| 268 |
sage: E.is_integral() |
|---|
| 269 |
True |
|---|
| 270 |
sage: E2=E.change_weierstrass_model(2,0,0,0); E2 |
|---|
| 271 |
Elliptic Curve defined by y^2 = x^3 + 1/16*x + 1/64 over Rational Field |
|---|
| 272 |
sage: E2.is_integral() |
|---|
| 273 |
False |
|---|
| 274 |
""" |
|---|
| 275 |
try: |
|---|
| 276 |
return self.__is_integral |
|---|
| 277 |
except AttributeError: |
|---|
| 278 |
one = Integer(1) |
|---|
| 279 |
self.__is_integral = bool(misc.mul([x.denominator() == 1 for x in self.ainvs()])) |
|---|
| 280 |
return self.__is_integral |
|---|
| 281 |
|
|---|
| 282 |
|
|---|
| 283 |
def mwrank(self, options=''): |
|---|
| 284 |
""" |
|---|
| 285 |
Run Cremona's mwrank program on this elliptic curve and |
|---|
| 286 |
return the result as a string. |
|---|
| 287 |
|
|---|
| 288 |
INPUT: |
|---|
| 289 |
options -- string; passed when starting mwrank. The format is |
|---|
| 290 |
q p<precision> v<verbosity> b<hlim_q> x<naux> c<hlim_c> l t o s d>] |
|---|
| 291 |
|
|---|
| 292 |
OUTPUT: |
|---|
| 293 |
string -- output of mwrank on this curve |
|---|
| 294 |
|
|---|
| 295 |
NOTE: The output is a raw string and completely illegible |
|---|
| 296 |
using automatic display, so it is recommended to use print |
|---|
| 297 |
for legible outout |
|---|
| 298 |
|
|---|
| 299 |
EXAMPLES: |
|---|
| 300 |
sage: E = EllipticCurve('37a1') |
|---|
| 301 |
sage: E.mwrank() #random |
|---|
| 302 |
... |
|---|
| 303 |
sage: print E.mwrank() |
|---|
| 304 |
Curve [0,0,1,-1,0] : Basic pair: I=48, J=-432 |
|---|
| 305 |
disc=255744 |
|---|
| 306 |
... |
|---|
| 307 |
Generator 1 is [0:-1:1]; height 0.05111... |
|---|
| 308 |
<BLANKLINE> |
|---|
| 309 |
Regulator = 0.05111... |
|---|
| 310 |
<BLANKLINE> |
|---|
| 311 |
The rank and full Mordell-Weil basis have been determined unconditionally. |
|---|
| 312 |
... |
|---|
| 313 |
|
|---|
| 314 |
Options to mwrank can be passed: |
|---|
| 315 |
sage: E = EllipticCurve([0,0,0,877,0]) |
|---|
| 316 |
|
|---|
| 317 |
Run mwrank with 'verbose' flag set to 0 but list generators if found |
|---|
| 318 |
sage: print E.mwrank('-v0 -l') |
|---|
| 319 |
Curve [0,0,0,877,0] : 0 <= rank <= 1 |
|---|
| 320 |
Regulator = 1 |
|---|
| 321 |
|
|---|
| 322 |
Run mwrank again, this time with a higher bound for point |
|---|
| 323 |
searching on homogeneous spaces: |
|---|
| 324 |
|
|---|
| 325 |
sage: print E.mwrank('-v0 -l -b11') |
|---|
| 326 |
Curve [0,0,0,877,0] : Rank = 1 |
|---|
| 327 |
Generator 1 is [29604565304828237474403861024284371796799791624792913256602210:-256256267988926809388776834045513089648669153204356603464786949:490078023219787588959802933995928925096061616470779979261000]; height 95.980371987964 |
|---|
| 328 |
Regulator = 95.980371987964 |
|---|
| 329 |
""" |
|---|
| 330 |
if options == "": |
|---|
| 331 |
from sage.interfaces.all import mwrank |
|---|
| 332 |
else: |
|---|
| 333 |
from sage.interfaces.all import Mwrank |
|---|
| 334 |
mwrank = Mwrank(options=options) |
|---|
| 335 |
return mwrank(self.a_invariants()) |
|---|
| 336 |
|
|---|
| 337 |
def conductor(self, algorithm="pari"): |
|---|
| 338 |
""" |
|---|
| 339 |
Returns the conductor of the elliptic curve. |
|---|
| 340 |
|
|---|
| 341 |
INPUT: |
|---|
| 342 |
algorithm -- str, (default: "pari") |
|---|
| 343 |
"pari" -- use the PARI C-library ellglobalred |
|---|
| 344 |
implementation of Tate's algorithm |
|---|
| 345 |
"mwrank" -- use Cremona's mwrank implementation of |
|---|
| 346 |
Tate's algorithm; can be faster if the |
|---|
| 347 |
curve has integer coefficients (TODO: |
|---|
| 348 |
limited to small conductor until mwrank |
|---|
| 349 |
gets integer factorization) |
|---|
| 350 |
"gp" -- use the GP interpreter. |
|---|
| 351 |
"all" -- use both implementations, verify that the |
|---|
| 352 |
results are the same (or raise an error), |
|---|
| 353 |
and output the common value. |
|---|
| 354 |
|
|---|
| 355 |
EXAMPLE: |
|---|
| 356 |
sage: E = EllipticCurve([1, -1, 1, -29372, -1932937]) |
|---|
| 357 |
sage: E.conductor(algorithm="pari") |
|---|
| 358 |
3006 |
|---|
| 359 |
sage: E.conductor(algorithm="mwrank") |
|---|
| 360 |
3006 |
|---|
| 361 |
sage: E.conductor(algorithm="gp") |
|---|
| 362 |
3006 |
|---|
| 363 |
sage: E.conductor(algorithm="all") |
|---|
| 364 |
3006 |
|---|
| 365 |
|
|---|
| 366 |
NOTE: The conductor computed using each algorithm is cached separately. |
|---|
| 367 |
Thus calling E.conductor("pari"), then E.conductor("mwrank") and |
|---|
| 368 |
getting the same result checks that both systems compute the same answer. |
|---|
| 369 |
""" |
|---|
| 370 |
|
|---|
| 371 |
if algorithm == "pari": |
|---|
| 372 |
try: |
|---|
| 373 |
return self.__conductor_pari |
|---|
| 374 |
except AttributeError: |
|---|
| 375 |
self.__conductor_pari = Integer(self.pari_mincurve().ellglobalred()[0]) |
|---|
| 376 |
return self.__conductor_pari |
|---|
| 377 |
|
|---|
| 378 |
elif algorithm == "gp": |
|---|
| 379 |
try: |
|---|
| 380 |
return self.__conductor_gp |
|---|
| 381 |
except AttributeError: |
|---|
| 382 |
self.__conductor_gp = Integer(gp.eval('ellglobalred(ellinit(%s,0))[1]'%self.a_invariants())) |
|---|
| 383 |
return self.__conductor_gp |
|---|
| 384 |
|
|---|
| 385 |
elif algorithm == "mwrank": |
|---|
| 386 |
try: |
|---|
| 387 |
return self.__conductor_mwrank |
|---|
| 388 |
except AttributeError: |
|---|
| 389 |
if self.is_integral(): |
|---|
| 390 |
self.__conductor_mwrank = Integer(self.mwrank_curve().conductor()) |
|---|
| 391 |
else: |
|---|
| 392 |
self.__conductor_mwrank = Integer(self.minimal_model().mwrank_curve().conductor()) |
|---|
| 393 |
return self.__conductor_mwrank |
|---|
| 394 |
|
|---|
| 395 |
elif algorithm == "all": |
|---|
| 396 |
N1 = self.conductor("pari") |
|---|
| 397 |
N2 = self.conductor("mwrank") |
|---|
| 398 |
N3 = self.conductor("gp") |
|---|
| 399 |
if N1 != N2 or N2 != N3: |
|---|
| 400 |
raise ArithmeticError, "Pari, mwrank and gp compute different conductors (%s,%s,%s) for %s"%( |
|---|
| 401 |
N1, N2, N3, self) |
|---|
| 402 |
return N1 |
|---|
| 403 |
else: |
|---|
| 404 |
raise RuntimeError, "algorithm '%s' is not known."%algorithm |
|---|
| 405 |
|
|---|
| 406 |
|
|---|
| 407 |
|
|---|
| 408 |
|
|---|
| 409 |
|
|---|
| 410 |
def pari_curve(self, prec = None, factor = 1): |
|---|
| 411 |
""" |
|---|
| 412 |
Return the PARI curve corresponding to this elliptic curve. |
|---|
| 413 |
|
|---|
| 414 |
INPUT: |
|---|
| 415 |
prec -- The precision of quantities calculated for the |
|---|
| 416 |
returned curve (in decimal digits). if None, defaults |
|---|
| 417 |
to factor * the precision of the largest cached curve |
|---|
| 418 |
(or 10 if none yet computed) |
|---|
| 419 |
factor -- the factor to increase the precision over the |
|---|
| 420 |
maximum previously computed precision. Only used if |
|---|
| 421 |
prec (which gives an explicit precision) is None. |
|---|
| 422 |
|
|---|
| 423 |
EXAMPLES: |
|---|
| 424 |
sage: E = EllipticCurve([0, 0,1,-1,0]) |
|---|
| 425 |
sage: e = E.pari_curve() |
|---|
| 426 |
sage: type(e) |
|---|
| 427 |
<type 'sage.libs.pari.gen.gen'> |
|---|
| 428 |
sage: e.type() |
|---|
| 429 |
't_VEC' |
|---|
| 430 |
sage: e.ellan(10) |
|---|
| 431 |
[1, -2, -3, 2, -2, 6, -1, 0, 6, 4] |
|---|
| 432 |
|
|---|
| 433 |
sage: E = EllipticCurve(RationalField(), ['1/3', '2/3']) |
|---|
| 434 |
sage: e = E.pari_curve() |
|---|
| 435 |
sage: e.type() |
|---|
| 436 |
't_VEC' |
|---|
| 437 |
sage: e[:5] |
|---|
| 438 |
[0, 0, 0, 1/3, 2/3] |
|---|
| 439 |
""" |
|---|
| 440 |
if prec is None: |
|---|
| 441 |
try: |
|---|
| 442 |
L = self._pari_curve.keys() |
|---|
| 443 |
L.sort() |
|---|
| 444 |
if factor == 1: |
|---|
| 445 |
return self._pari_curve[L[-1]] |
|---|
| 446 |
else: |
|---|
| 447 |
prec = int(factor * L[-1]) |
|---|
| 448 |
self._pari_curve[prec] = pari(self.a_invariants()).ellinit(precision=prec) |
|---|
| 449 |
return self._pari_curve[prec] |
|---|
| 450 |
except AttributeError: |
|---|
| 451 |
pass |
|---|
| 452 |
try: |
|---|
| 453 |
return self._pari_curve[prec] |
|---|
| 454 |
except AttributeError: |
|---|
| 455 |
prec = 10 |
|---|
| 456 |
self._pari_curve = {} |
|---|
| 457 |
except KeyError: |
|---|
| 458 |
pass |
|---|
| 459 |
self._pari_curve[prec] = pari(self.a_invariants()).ellinit(precision=prec) |
|---|
| 460 |
return self._pari_curve[prec] |
|---|
| 461 |
|
|---|
| 462 |
def pari_mincurve(self, prec = None): |
|---|
| 463 |
""" |
|---|
| 464 |
Return the PARI curve corresponding to a minimal model |
|---|
| 465 |
for this elliptic curve. |
|---|
| 466 |
|
|---|
| 467 |
INPUT: |
|---|
| 468 |
prec -- The precision of quantities calculated for the |
|---|
| 469 |
returned curve (in decimal digits). if None, defaults |
|---|
| 470 |
to the precision of the largest cached curve (or 10 if |
|---|
| 471 |
none yet computed) |
|---|
| 472 |
|
|---|
| 473 |
EXAMPLES: |
|---|
| 474 |
sage: E = EllipticCurve(RationalField(), ['1/3', '2/3']) |
|---|
| 475 |
sage: e = E.pari_mincurve() |
|---|
| 476 |
sage: e[:5] |
|---|
| 477 |
[0, 0, 0, 27, 486] |
|---|
| 478 |
sage: E.conductor() |
|---|
| 479 |
47232 |
|---|
| 480 |
sage: e.ellglobalred() |
|---|
| 481 |
[47232, [1, 0, 0, 0], 2] |
|---|
| 482 |
""" |
|---|
| 483 |
if prec is None: |
|---|
| 484 |
try: |
|---|
| 485 |
L = self._pari_mincurve.keys() |
|---|
| 486 |
L.sort() |
|---|
| 487 |
return self._pari_mincurve[L[len(L) - 1]] |
|---|
| 488 |
except AttributeError: |
|---|
| 489 |
pass |
|---|
| 490 |
try: |
|---|
| 491 |
return self._pari_mincurve[prec] |
|---|
| 492 |
except AttributeError: |
|---|
| 493 |
prec = 10 |
|---|
| 494 |
self._pari_mincurve = {} |
|---|
| 495 |
except KeyError: |
|---|
| 496 |
pass |
|---|
| 497 |
e = self.pari_curve(prec) |
|---|
| 498 |
mc, change = e.ellminimalmodel() |
|---|
| 499 |
self._pari_mincurve[prec] = mc |
|---|
| 500 |
|
|---|
| 501 |
return mc |
|---|
| 502 |
|
|---|
| 503 |
def database_curve(self): |
|---|
| 504 |
""" |
|---|
| 505 |
Return the curve in the elliptic curve database isomorphic to |
|---|
| 506 |
this curve, if possible. Otherwise raise a RuntimeError |
|---|
| 507 |
exception. |
|---|
| 508 |
|
|---|
| 509 |
EXAMPLES: |
|---|
| 510 |
sage: E = EllipticCurve([0,1,2,3,4]) |
|---|
| 511 |
sage: E.database_curve() |
|---|
| 512 |
Elliptic Curve defined by y^2 = x^3 + x^2 + 3*x + 5 over Rational Field |
|---|
| 513 |
|
|---|
| 514 |
NOTES: The model of the curve in the database can be different |
|---|
| 515 |
than the Weierstrass model for this curve, e.g., |
|---|
| 516 |
database models are always minimal. |
|---|
| 517 |
""" |
|---|
| 518 |
try: |
|---|
| 519 |
return self.__database_curve |
|---|
| 520 |
except AttributeError: |
|---|
| 521 |
misc.verbose("Looking up %s in the database."%self) |
|---|
| 522 |
D = sage.databases.cremona.CremonaDatabase() |
|---|
| 523 |
ainvs = self.minimal_model().ainvs() |
|---|
| 524 |
try: |
|---|
| 525 |
self.__database_curve = D.elliptic_curve_from_ainvs(self.conductor(), ainvs) |
|---|
| 526 |
except RuntimeError: |
|---|
| 527 |
raise RuntimeError, "Elliptic curve %s not in the database."%self |
|---|
| 528 |
return self.__database_curve |
|---|
| 529 |
|
|---|
| 530 |
|
|---|
| 531 |
def Np(self, p): |
|---|
| 532 |
""" |
|---|
| 533 |
The number of points on E modulo p, where p is a prime, not |
|---|
| 534 |
necessarily of good reduction. (When p is a bad prime, also |
|---|
| 535 |
counts the singular point.) |
|---|
| 536 |
|
|---|
| 537 |
EXAMPLES: |
|---|
| 538 |
sage: E = EllipticCurve([0, -1, 1, -10, -20]) |
|---|
| 539 |
sage: E.Np(2) |
|---|
| 540 |
5 |
|---|
| 541 |
sage: E.Np(3) |
|---|
| 542 |
5 |
|---|
| 543 |
sage: E.conductor() |
|---|
| 544 |
11 |
|---|
| 545 |
sage: E.Np(11) |
|---|
| 546 |
11 |
|---|
| 547 |
""" |
|---|
| 548 |
if self.conductor() % p == 0: |
|---|
| 549 |
return p + 1 - self.ap(p) |
|---|
| 550 |
|
|---|
| 551 |
if p < 1125899906842624: |
|---|
| 552 |
return p+1 - self.ap(p) |
|---|
| 553 |
else: |
|---|
| 554 |
return self.sea(p) |
|---|
| 555 |
|
|---|
| 556 |
def sea(self, p, early_abort=False): |
|---|
| 557 |
r""" |
|---|
| 558 |
Return the number of points on $E$ over $\F_p$ computed using |
|---|
| 559 |
the SEA algorithm, as implemented in PARI by Christophe Doche |
|---|
| 560 |
and Sylvain Duquesne. |
|---|
| 561 |
|
|---|
| 562 |
INPUT: |
|---|
| 563 |
p -- a prime number |
|---|
| 564 |
early_abort -- bool (default: Falst); if True an early abort technique |
|---|
| 565 |
is used and the computation is interrupted as soon |
|---|
| 566 |
as a small divisor of the order is detected. |
|---|
| 567 |
|
|---|
| 568 |
\note{As of 2006-02-02 this function does not work on |
|---|
| 569 |
Microsoft Windows under Cygwin (though it works under |
|---|
| 570 |
vmware of course).} |
|---|
| 571 |
|
|---|
| 572 |
EXAMPLES: |
|---|
| 573 |
sage: E = EllipticCurve('37a') |
|---|
| 574 |
sage: E.sea(next_prime(10^30)) |
|---|
| 575 |
1000000000000001426441464441649 |
|---|
| 576 |
""" |
|---|
| 577 |
p = rings.Integer(p) |
|---|
| 578 |
return sea.ellsea(self.minimal_model().a_invariants(), p, early_abort=early_abort) |
|---|
| 579 |
|
|---|
| 580 |
|
|---|
| 581 |
|
|---|
| 582 |
|
|---|
| 583 |
|
|---|
| 584 |
|
|---|
| 585 |
|
|---|
| 586 |
|
|---|
| 587 |
|
|---|
| 588 |
|
|---|
| 589 |
|
|---|
| 590 |
def mwrank_curve(self, verbose=False): |
|---|
| 591 |
""" |
|---|
| 592 |
Construct an mwrank_EllipticCurve from this elliptic curve |
|---|
| 593 |
|
|---|
| 594 |
The resulting mwrank_EllipticCurve has available methods from |
|---|
| 595 |
John Cremona's eclib library. |
|---|
| 596 |
|
|---|
| 597 |
EXAMPLES: |
|---|
| 598 |
sage: E=EllipticCurve('11a1') |
|---|
| 599 |
sage: EE=E.mwrank_curve() |
|---|
| 600 |
sage: EE |
|---|
| 601 |
y^2+ y = x^3 - x^2 - 10*x - 20 |
|---|
| 602 |
sage: type(EE) |
|---|
| 603 |
<class 'sage.libs.mwrank.interface.mwrank_EllipticCurve'> |
|---|
| 604 |
sage: EE.isogeny_class() |
|---|
| 605 |
([[0, -1, 1, -10, -20], [0, -1, 1, -7820, -263580], [0, -1, 1, 0, 0]], |
|---|
| 606 |
[[0, 5, 5], [5, 0, 0], [5, 0, 0]]) |
|---|
| 607 |
""" |
|---|
| 608 |
try: |
|---|
| 609 |
return self.__mwrank_curve |
|---|
| 610 |
except AttributeError: |
|---|
| 611 |
pass |
|---|
| 612 |
self.__mwrank_curve = mwrank.mwrank_EllipticCurve( |
|---|
| 613 |
self.ainvs(), verbose=verbose) |
|---|
| 614 |
return self.__mwrank_curve |
|---|
| 615 |
|
|---|
| 616 |
def two_descent(self, verbose=True, |
|---|
| 617 |
selmer_only = False, |
|---|
| 618 |
first_limit = 20, |
|---|
| 619 |
second_limit = 8, |
|---|
| 620 |
n_aux = -1, |
|---|
| 621 |
second_descent = 1): |
|---|
| 622 |
""" |
|---|
| 623 |
Compute 2-descent data for this curve. |
|---|
| 624 |
|
|---|
| 625 |
INPUT: |
|---|
| 626 |
verbose -- (default: True) print what mwrank is doing |
|---|
| 627 |
If False, *no output* is |
|---|
| 628 |
selmer_only -- (default: False) selmer_only switch |
|---|
| 629 |
first_limit -- (default: 20) firstlim is bound on |x|+|z| |
|---|
| 630 |
second_limit-- (default: 8) secondlim is bound on log max {|x|,|z| }, |
|---|
| 631 |
i.e. logarithmic |
|---|
| 632 |
n_aux -- (default: -1) n_aux only relevant for general |
|---|
| 633 |
2-descent when 2-torsion trivial; n_aux=-1 causes default |
|---|
| 634 |
to be used (depends on method) |
|---|
| 635 |
second_descent -- (default: True) second_descent only relevant for |
|---|
| 636 |
descent via 2-isogeny |
|---|
| 637 |
OUTPUT: |
|---|
| 638 |
|
|---|
| 639 |
Nothing -- nothing is returned (though much is printed |
|---|
| 640 |
unless verbose=False) |
|---|
| 641 |
|
|---|
| 642 |
EXAMPLES: |
|---|
| 643 |
sage: E=EllipticCurve('37a1') |
|---|
| 644 |
sage: E.two_descent(verbose=False) # no output |
|---|
| 645 |
""" |
|---|
| 646 |
self.mwrank_curve().two_descent(verbose, selmer_only, |
|---|
| 647 |
first_limit, second_limit, |
|---|
| 648 |
n_aux, second_descent) |
|---|
| 649 |
|
|---|
| 650 |
|
|---|
| 651 |
|
|---|
| 652 |
|
|---|
| 653 |
|
|---|
| 654 |
|
|---|
| 655 |
def aplist(self, n, python_ints=False): |
|---|
| 656 |
r""" |
|---|
| 657 |
The Fourier coefficients $a_p$ of the modular form attached to |
|---|
| 658 |
this elliptic curve, for all primes $p\leq n$. |
|---|
| 659 |
|
|---|
| 660 |
INPUT: |
|---|
| 661 |
n -- integer |
|---|
| 662 |
python_ints -- bool (default: False); if True return a list of |
|---|
| 663 |
Python ints instead of SAGE integers. |
|---|
| 664 |
|
|---|
| 665 |
OUTPUT: |
|---|
| 666 |
-- list of integers |
|---|
| 667 |
|
|---|
| 668 |
EXAMPLES: |
|---|
| 669 |
sage: e = EllipticCurve('37a') |
|---|
| 670 |
sage: e.aplist(1) |
|---|
| 671 |
[] |
|---|
| 672 |
sage: e.aplist(2) |
|---|
| 673 |
[-2] |
|---|
| 674 |
sage: e.aplist(10) |
|---|
| 675 |
[-2, -3, -2, -1] |
|---|
| 676 |
sage: v = e.aplist(13); v |
|---|
| 677 |
[-2, -3, -2, -1, -5, -2] |
|---|
| 678 |
sage: type(v[0]) |
|---|
| 679 |
<type 'sage.rings.integer.Integer'> |
|---|
| 680 |
sage: type(e.aplist(13, python_ints=True)[0]) |
|---|
| 681 |
<type 'int'> |
|---|
| 682 |
""" |
|---|
| 683 |
|
|---|
| 684 |
e = self.pari_mincurve() |
|---|
| 685 |
v = e.ellaplist(n, python_ints=True) |
|---|
| 686 |
if python_ints: |
|---|
| 687 |
return v |
|---|
| 688 |
else: |
|---|
| 689 |
return [Integer(a) for a in v] |
|---|
| 690 |
|
|---|
| 691 |
|
|---|
| 692 |
|
|---|
| 693 |
def anlist(self, n, python_ints=False): |
|---|
| 694 |
""" |
|---|
| 695 |
The Fourier coefficients up to and including $a_n$ of the |
|---|
| 696 |
modular form attached to this elliptic curve. The ith element |
|---|
| 697 |
of the return list is a[i]. |
|---|
| 698 |
|
|---|
| 699 |
INPUT: |
|---|
| 700 |
n -- integer |
|---|
| 701 |
python_ints -- bool (default: False); if True return a list of |
|---|
| 702 |
Python ints instead of SAGE integers. |
|---|
| 703 |
|
|---|
| 704 |
OUTPUT: |
|---|
| 705 |
-- list of integers |
|---|
| 706 |
|
|---|
| 707 |
EXAMPLES: |
|---|
| 708 |
sage: E = EllipticCurve([0, -1, 1, -10, -20]) |
|---|
| 709 |
sage: E.anlist(3) |
|---|
| 710 |
[0, 1, -2, -1] |
|---|
| 711 |
|
|---|
| 712 |
sage: E = EllipticCurve([0,1]) |
|---|
| 713 |
sage: E.anlist(20) |
|---|
| 714 |
[0, 1, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 8, 0] |
|---|
| 715 |
""" |
|---|
| 716 |
n = int(n) |
|---|
| 717 |
|
|---|
| 718 |
e = self.pari_mincurve() |
|---|
| 719 |
if n >= 2147483648: |
|---|
| 720 |
raise RuntimeError, "anlist: n (=%s) must be < 2147483648."%n |
|---|
| 721 |
|
|---|
| 722 |
v = [0] + e.ellan(n, python_ints=True) |
|---|
| 723 |
if not python_ints: |
|---|
| 724 |
v = [Integer(x) for x in v] |
|---|
| 725 |
return v |
|---|
| 726 |
|
|---|
| 727 |
|
|---|
| 728 |
|
|---|
| 729 |
|
|---|
| 730 |
|
|---|
| 731 |
|
|---|
| 732 |
|
|---|
| 733 |
|
|---|
| 734 |
|
|---|
| 735 |
|
|---|
| 736 |
|
|---|
| 737 |
|
|---|
| 738 |
|
|---|
| 739 |
|
|---|
| 740 |
|
|---|
| 741 |
|
|---|
| 742 |
|
|---|
| 743 |
|
|---|
| 744 |
|
|---|
| 745 |
|
|---|
| 746 |
|
|---|
| 747 |
|
|---|
| 748 |
|
|---|
| 749 |
|
|---|
| 750 |
|
|---|
| 751 |
|
|---|
| 752 |
|
|---|
| 753 |
|
|---|
| 754 |
|
|---|
| 755 |
|
|---|
| 756 |
|
|---|
| 757 |
|
|---|
| 758 |
|
|---|
| 759 |
|
|---|
| 760 |
|
|---|
| 761 |
|
|---|
| 762 |
|
|---|
| 763 |
|
|---|
| 764 |
|
|---|
| 765 |
|
|---|
| 766 |
|
|---|
| 767 |
|
|---|
| 768 |
|
|---|
| 769 |
def q_expansion(self, prec): |
|---|
| 770 |
r""" |
|---|
| 771 |
Return the $q$-expansion to precision prec of the newform |
|---|