Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/elliptic_curves/ell_generic.py
4128 views
1
r"""
2
Elliptic curves over a general ring
3
4
Sage defines an elliptic curve over a ring `R` as a 'Weierstrass Model' with
5
five coefficients `[a_1,a_2,a_3,a_4,a_6]` in `R` given by
6
7
`y^2 + a_1 xy + a_3 y = x^3 +a_2 x^2 +a_4 x +a_6`.
8
9
Note that the (usual) scheme-theoretic definition of an elliptic curve over `R` would require the discriminant to be a unit in `R`, Sage only imposes that the discriminant is non-zero. Also, in Magma, 'Weierstrass Model' means a model with `a1=a2=a3=0`, which is called 'Short Weierstrass Model' in Sage; these do not always exist in characteristics 2 and 3.
10
11
EXAMPLES:
12
13
We construct an elliptic curve over an elaborate base ring::
14
15
sage: p = 97; a=1; b=3
16
sage: R, u = PolynomialRing(GF(p), 'u').objgen()
17
sage: S, v = PolynomialRing(R, 'v').objgen()
18
sage: T = S.fraction_field()
19
sage: E = EllipticCurve(T, [a, b]); E
20
Elliptic Curve defined by y^2 = x^3 + x + 3 over Fraction Field of Univariate Polynomial Ring in v over Univariate Polynomial Ring in u over Finite Field of size 97
21
sage: latex(E)
22
y^2 = x^3 + x + 3
23
24
AUTHORS:
25
26
- William Stein (2005): Initial version
27
28
- Robert Bradshaw et al....
29
30
- John Cremona (2008-01): isomorphisms, automorphisms and twists in all characteristics
31
"""
32
33
#*****************************************************************************
34
# Copyright (C) 2005 William Stein <[email protected]>
35
#
36
# Distributed under the terms of the GNU General Public License (GPL)
37
#
38
# This code is distributed in the hope that it will be useful,
39
# but WITHOUT ANY WARRANTY; without even the implied warranty of
40
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41
# General Public License for more details.
42
#
43
# The full text of the GPL is available at:
44
#
45
# http://www.gnu.org/licenses/
46
#*****************************************************************************
47
48
import math
49
50
from sage.rings.all import PolynomialRing
51
import sage.groups.additive_abelian.additive_abelian_group as groups
52
import sage.groups.generic as generic
53
import sage.plot.all as plot
54
from sage.plot.plot import generate_plot_points
55
56
import sage.rings.arith as arith
57
import sage.rings.all as rings
58
from sage.rings.number_field.all import is_NumberField
59
import sage.misc.misc as misc
60
61
62
# Schemes
63
import sage.schemes.generic.projective_space as projective_space
64
import sage.schemes.generic.homset as homset
65
66
import ell_point
67
import ell_torsion
68
import constructor
69
import formal_group
70
import weierstrass_morphism as wm
71
72
73
factor = arith.factor
74
sqrt = math.sqrt
75
exp = math.exp
76
mul = misc.mul
77
next_prime = arith.next_prime
78
79
oo = rings.infinity # infinity
80
O = rings.O # big oh
81
82
import sage.schemes.plane_curves.projective_curve as plane_curve
83
84
def is_EllipticCurve(x):
85
r"""
86
Utility function to test if ``x`` is an instance of an Elliptic Curve class.
87
88
EXAMPLES::
89
90
sage: from sage.schemes.elliptic_curves.ell_generic import is_EllipticCurve
91
sage: E = EllipticCurve([1,2,3/4,7,19])
92
sage: is_EllipticCurve(E)
93
True
94
sage: is_EllipticCurve(0)
95
False
96
"""
97
return isinstance(x, EllipticCurve_generic)
98
99
class EllipticCurve_generic(plane_curve.ProjectiveCurve_generic):
100
r"""
101
Elliptic curve over a generic base ring.
102
103
EXAMPLES::
104
105
sage: E = EllipticCurve([1,2,3/4,7,19]); E
106
Elliptic Curve defined by y^2 + x*y + 3/4*y = x^3 + 2*x^2 + 7*x + 19 over Rational Field
107
sage: loads(E.dumps()) == E
108
True
109
sage: E = EllipticCurve([1,3])
110
sage: P = E([-1,1,1])
111
sage: -5*P
112
(179051/80089 : -91814227/22665187 : 1)
113
"""
114
def __init__(self, ainvs, extra=None):
115
r"""
116
Constructor from `a`-invariants (long or short Weierstrass coefficients).
117
118
INPUT:
119
120
- ``ainvs`` (list) -- either `[a_1,a_2,a_3,a_4,a_6]` or
121
`[a_4,a_6]` (with `a_1=a_2=a_3=0` in the second case).
122
123
.. note::
124
125
See constructor.py for more variants.
126
127
EXAMPLES::
128
129
sage: E = EllipticCurve([1,2,3,4,5]); E
130
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
131
sage: E = EllipticCurve(GF(7),[1,2,3,4,5]); E
132
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Finite Field of size 7
133
134
Constructor from `[a_4,a_6]` sets `a_1=a_2=a_3=0`::
135
136
sage: EllipticCurve([4,5]).ainvs()
137
(0, 0, 0, 4, 5)
138
139
The base ring need not be a field::
140
141
sage: EllipticCurve(IntegerModRing(91),[1,2,3,4,5])
142
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Ring of integers modulo 91
143
"""
144
if extra != None: # possibility of two arguments
145
K, ainvs = ainvs, extra
146
else:
147
K = ainvs[0].parent()
148
assert len(ainvs) == 2 or len(ainvs) == 5
149
self.__base_ring = K
150
ainvs = [K(x) for x in ainvs]
151
if len(ainvs) == 2:
152
ainvs = [K(0),K(0),K(0)] + ainvs
153
self.__ainvs = tuple(ainvs)
154
if self.discriminant() == 0:
155
raise ArithmeticError, \
156
"Invariants %s define a singular curve."%ainvs
157
PP = projective_space.ProjectiveSpace(2, K, names='xyz');
158
x, y, z = PP.coordinate_ring().gens()
159
a1, a2, a3, a4, a6 = ainvs
160
f = y**2*z + (a1*x + a3*z)*y*z \
161
- (x**3 + a2*x**2*z + a4*x*z**2 + a6*z**3)
162
plane_curve.ProjectiveCurve_generic.__init__(self, PP, f)
163
# TODO: cleanup, are these two point classes redundant?
164
165
# See #1975: we deliberately set the class to
166
# EllipticCurvePoint_finite_field for finite rings, so that we
167
# can do some arithmetic on points over Z/NZ, for teaching
168
# purposes.
169
from sage.rings.all import is_FiniteField, is_IntegerModRing
170
if is_FiniteField(K) or is_IntegerModRing(K):
171
self._morphism = self._point = ell_point.EllipticCurvePoint_finite_field
172
elif K.is_field():
173
if is_NumberField(K):
174
self._morphism = self._point = ell_point.EllipticCurvePoint_number_field
175
else:
176
self._morphism = self._point = ell_point.EllipticCurvePoint_field
177
else:
178
self._morphism = self._point = ell_point.EllipticCurvePoint
179
180
def _defining_params_(self):
181
r"""
182
Internal function. Returns a tuple of the base ring of this
183
elliptic curve and its `a`-invariants, from which it can be
184
reconstructed.
185
186
EXAMPLES::
187
188
sage: E=EllipticCurve(QQ,[1,1])
189
sage: E._defining_params_()
190
(Rational Field, [0, 0, 0, 1, 1])
191
sage: EllipticCurve(*E._defining_params_()) == E
192
True
193
"""
194
return (self.__base_ring, list(self.__ainvs))
195
196
def __hash__(self):
197
"""
198
TESTS::
199
200
sage: E = EllipticCurve('37a')
201
sage: hash(E)
202
-1437250549 # 32-bit
203
-2189969105152029685 # 64-bit
204
sage: hash(E) != hash(E.change_ring(GF(7)))
205
True
206
"""
207
return hash((self.__base_ring, self.__ainvs))
208
209
def _repr_(self):
210
"""
211
String representation of elliptic curve.
212
213
EXAMPLES::
214
215
sage: E=EllipticCurve([1,2,3,4,5]); E._repr_()
216
'Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field'
217
218
::
219
220
sage: R.<x> = QQ['x']
221
sage: K.<a> = NumberField(x^3-17)
222
sage: EllipticCurve([a^2-3, -2/3*a + 3])
223
Elliptic Curve defined by y^2 = x^3 + (a^2-3)*x + (-2/3*a+3) over Number Field in a
224
with defining polynomial x^3 - 17
225
"""
226
#return "Elliptic Curve with a-invariants %s over %s"%(self.ainvs(), self.base_ring())
227
b = self.ainvs()
228
#return "y^2 + %s*x*y + %s*y = x^3 + %s*x^2 + %s*x + %s"%\
229
# (a[0], a[2], a[1], a[3], a[4])
230
a = [z._coeff_repr() for z in b]
231
s = "Elliptic Curve defined by "
232
s += "y^2 "
233
if a[0] == "-1":
234
s += "- x*y "
235
elif a[0] == '1':
236
s += "+ x*y "
237
elif b[0]:
238
s += "+ %s*x*y "%a[0]
239
if a[2] == "-1":
240
s += "- y "
241
elif a[2] == '1':
242
s += "+ y "
243
elif b[2]:
244
s += "+ %s*y "%a[2]
245
s += "= x^3 "
246
if a[1] == "-1":
247
s += "- x^2 "
248
elif a[1] == '1':
249
s += "+ x^2 "
250
elif b[1]:
251
s += "+ %s*x^2 "%a[1]
252
if a[3] == "-1":
253
s += "- x "
254
elif a[3] == '1':
255
s += "+ x "
256
elif b[3]:
257
s += "+ %s*x "%a[3]
258
if a[4] == '-1':
259
s += "- 1 "
260
elif a[4] == '1':
261
s += "+ 1 "
262
elif b[4]:
263
s += "+ %s "%a[4]
264
s = s.replace("+ -","- ")
265
s += "over %s"%self.base_ring()
266
return s
267
268
def _latex_(self):
269
"""
270
Internal function. Returns a latex string for this elliptic curve.
271
Users will normally use latex() instead.
272
273
EXAMPLES::
274
275
sage: E=EllipticCurve(QQ,[1,1])
276
sage: E._latex_()
277
'y^2 = x^3 + x + 1 '
278
sage: latex(E)
279
y^2 = x^3 + x + 1
280
"""
281
b = self.ainvs()
282
a = [z._latex_coeff_repr() for z in b]
283
s = "y^2 "
284
if a[0] == '-1':
285
s += "- xy "
286
elif a[0] == '1':
287
s += "+ xy "
288
elif b[0]:
289
s += "+ %sxy "%a[0]
290
if a[2] == '-1':
291
s += "- y "
292
elif a[2] == '1':
293
s += "+ y "
294
elif b[2]:
295
s += "+ %sy "%a[2]
296
s += "= x^3 "
297
if a[1] == '-1':
298
s += "- x^2 "
299
elif a[1] == '1':
300
s += "+ x^2 "
301
elif b[1]:
302
s += "+ %sx^2 "%a[1]
303
if a[3] == '-1':
304
s += "- x "
305
elif a[3] == '1':
306
s += "+ x "
307
elif b[3]:
308
s += "+ %sx "%a[3]
309
if a[4] == '-1':
310
s += "- 1 "
311
elif a[4] == '1':
312
s += "+ 1 "
313
elif b[4]:
314
s += "+ %s "%a[4]
315
s = s.replace("+ -","- ")
316
return s
317
318
def _pari_init_(self):
319
"""
320
Internal function. Returns a string to initialize this elliptic
321
curve in the PARI system.
322
323
EXAMPLES::
324
325
sage: E=EllipticCurve(QQ,[1,1])
326
sage: E._pari_init_()
327
'ellinit([0/1,0/1,0/1,1/1,1/1])'
328
"""
329
return 'ellinit([%s])'%(','.join([x._pari_init_() for x in self.ainvs()]))
330
331
def _magma_init_(self, magma):
332
"""
333
Internal function. Returns a string to initialize this elliptic
334
curve in the Magma subsystem.
335
336
EXAMPLES::
337
338
sage: E = EllipticCurve(QQ,[1,1])
339
sage: E._magma_init_(magma) # optional - magma
340
'EllipticCurve([_sage_ref...|0/1,0/1,0/1,1/1,1/1])'
341
sage: E = EllipticCurve(GF(41),[2,5]) # optional - magma
342
sage: E._magma_init_(magma) # optional - magma
343
'EllipticCurve([_sage_ref...|GF(41)!0,GF(41)!0,GF(41)!0,GF(41)!2,GF(41)!5])'
344
sage: E = EllipticCurve(GF(25,'a'), [0,0,1,4,0])
345
sage: magma(E) # optional - magma
346
Elliptic Curve defined by y^2 + y = x^3 + 4*x over GF(5^2)
347
sage: magma(EllipticCurve([1/2,2/3,-4/5,6/7,8/9])) # optional - magma
348
Elliptic Curve defined by y^2 + 1/2*x*y - 4/5*y = x^3 + 2/3*x^2 + 6/7*x + 8/9 over Rational Field
349
sage: R.<x> = Frac(QQ['x'])
350
sage: magma(EllipticCurve([x,1+x])) # optional - magma
351
Elliptic Curve defined by y^2 = x^3 + x*x + (x + 1) over Univariate rational function field over Rational Field
352
"""
353
kmn = magma(self.base_ring())._ref()
354
return 'EllipticCurve([%s|%s])'%(kmn,','.join([x._magma_init_(magma) for x in self.ainvs()]))
355
356
357
def _symbolic_(self, SR):
358
r"""
359
Many elliptic curves can be converted into a symbolic expression
360
using the ``symbolic_expression`` command.
361
362
EXAMPLES: We find a torsion point on 11a.
363
364
::
365
366
sage: E = EllipticCurve('11a')
367
sage: E._symbolic_(SR)
368
y^2 + y == x^3 - x^2 - 10*x - 20
369
sage: E.torsion_subgroup().gens()
370
((5 : 5 : 1),)
371
372
We find the corresponding symbolic equality::
373
374
sage: eqn = symbolic_expression(E); eqn
375
y^2 + y == x^3 - x^2 - 10*x - 20
376
377
We verify that the given point is on the curve::
378
379
sage: eqn(x=5,y=5)
380
30 == 30
381
sage: bool(eqn(x=5,y=5))
382
True
383
384
We create a single expression::
385
386
sage: F = eqn.lhs() - eqn.rhs(); F
387
-x^3 + x^2 + y^2 + 10*x + y + 20
388
sage: y = var('y')
389
sage: F.solve(y)
390
[y == -1/2*sqrt(4*x^3 - 4*x^2 - 40*x - 79) - 1/2,
391
y == 1/2*sqrt(4*x^3 - 4*x^2 - 40*x - 79) - 1/2]
392
393
You can also solve for x in terms of y, but the result is
394
horrendous. Continuing with the above example, we can explicitly
395
find points over random fields by substituting in values for x::
396
397
sage: v = F.solve(y)[0].rhs(); v
398
-1/2*sqrt(4*x^3 - 4*x^2 - 40*x - 79) - 1/2
399
sage: v = v.function(x)
400
sage: v(3)
401
-1/2*sqrt(-127) - 1/2
402
sage: v(7)
403
-1/2*sqrt(817) - 1/2
404
sage: v(-7)
405
-1/2*sqrt(-1367) - 1/2
406
sage: v(sqrt(2))
407
-1/2*sqrt(-32*sqrt(2) - 87) - 1/2
408
409
We can even do arithmetic with them, as follows::
410
411
sage: E2 = E.change_ring(SR); E2
412
Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20) over Symbolic Ring
413
sage: P = E2.point((3, v(3), 1), check=False) # the check=False option doesn't verify that y^2 = f(x)
414
sage: P
415
(3 : -1/2*sqrt(-127) - 1/2 : 1)
416
sage: P + P
417
(-756/127 : 41143/32258*sqrt(-127) - 1/2 : 1)
418
419
We can even throw in a transcendental::
420
421
sage: w = E2.point((pi,v(pi),1), check=False); w
422
(pi : -1/2*sqrt(-40*pi + 4*pi^3 - 4*pi^2 - 79) - 1/2 : 1)
423
sage: x, y, z = w; ((y^2 + y) - (x^3 - x^2 - 10*x - 20)).expand()
424
0
425
426
sage: 2*w
427
(-2*pi + (2*pi - 3*pi^2 + 10)^2/(-40*pi + 4*pi^3 - 4*pi^2 - 79) + 1 : (2*pi - 3*pi^2 + 10)*(3*pi - (2*pi - 3*pi^2 + 10)^2/(-40*pi + 4*pi^3 - 4*pi^2 - 79) - 1)/sqrt(-40*pi + 4*pi^3 - 4*pi^2 - 79) + 1/2*sqrt(-40*pi + 4*pi^3 - 4*pi^2 - 79) - 1/2 : 1)
428
429
sage: x, y, z = 2*w; temp = ((y^2 + y) - (x^3 - x^2 - 10*x - 20))
430
431
This is a point on the curve::
432
433
sage: bool(temp == 0)
434
True
435
"""
436
a = [SR(x) for x in self.a_invariants()]
437
x, y = SR.var('x, y')
438
return y**2 + a[0]*x*y + a[2]*y == x**3 + a[1]*x**2 + a[3]*x + a[4]
439
440
def __cmp__(self, other):
441
"""
442
Standard comparison function for elliptic curves, to allow sorting
443
and equality testing.
444
445
EXAMPLES::
446
447
sage: E=EllipticCurve(QQ,[1,1])
448
sage: F=EllipticCurve(QQ,[0,0,0,1,1])
449
sage: E==F
450
True
451
"""
452
if not isinstance(other, EllipticCurve_generic):
453
return -1
454
t = cmp(self.base_ring(), other.base_ring())
455
if t:
456
return t
457
return cmp(self.ainvs(), other.ainvs())
458
459
def __contains__(self, P):
460
"""
461
Returns True if and only if P is a point on the elliptic curve. P
462
just has to be something that can be coerced to a point.
463
464
EXAMPLES::
465
466
sage: E = EllipticCurve([0, 0, 1, -1, 0])
467
sage: (0,0) in E
468
True
469
sage: (1,3) in E
470
False
471
sage: E = EllipticCurve([GF(7)(0), 1])
472
sage: [0,0] in E
473
False
474
sage: [0,8] in E
475
True
476
sage: P = E(0,8)
477
sage: P
478
(0 : 1 : 1)
479
sage: P in E
480
True
481
"""
482
if not isinstance(P, ell_point.EllipticCurvePoint):
483
try:
484
P = self(P)
485
except TypeError:
486
return False
487
if P.curve() == self:
488
return True
489
x, y, a = P[0], P[1], self.ainvs()
490
return y**2 + a[0]*x*y + a[2]*y == x**3 + a[1]*x**2 + a[3]*x + a[4]
491
492
def __call__(self, *args, **kwds):
493
r"""
494
EXAMPLES::
495
496
sage: E = EllipticCurve([0, 0, 1, -1, 0])
497
498
The point at infinity, which is the 0 element of the group::
499
500
sage: E(0)
501
(0 : 1 : 0)
502
503
The origin is a point on our curve::
504
505
sage: P = E([0,0])
506
sage: P
507
(0 : 0 : 1)
508
509
The curve associated to a point::
510
511
sage: P.curve()
512
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
513
514
Points can be specified by given a 2-tuple or 3-tuple::
515
516
sage: E([0,0])
517
(0 : 0 : 1)
518
sage: E([0,1,0])
519
(0 : 1 : 0)
520
521
Over a field, points are normalized so the 3rd entry (if non-zero)
522
is 1::
523
524
sage: E(105, -69, 125)
525
(21/25 : -69/125 : 1)
526
527
We create points on an elliptic curve over a prime finite field::
528
529
sage: E = EllipticCurve([GF(7)(0), 1])
530
sage: E([2,3])
531
(2 : 3 : 1)
532
sage: E([0,0])
533
Traceback (most recent call last):
534
...
535
TypeError: Coordinates [0, 0, 1] do not define a point on Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7
536
537
We create a point on an elliptic curve over a number field::
538
539
sage: x = polygen(RationalField())
540
sage: K = NumberField(x**3 + x + 1, 'a'); a = K.gen()
541
sage: E = EllipticCurve([a,a])
542
sage: E
543
Elliptic Curve defined by y^2 = x^3 + a*x + a over Number Field in a with defining polynomial x^3 + x + 1
544
sage: E = EllipticCurve([K(1),1])
545
sage: E
546
Elliptic Curve defined by y^2 = x^3 + x + 1 over Number Field in a with defining polynomial x^3 + x + 1
547
sage: P = E([a,0,1])
548
sage: P
549
(a : 0 : 1)
550
sage: P+P
551
(0 : 1 : 0)
552
553
Another example involving p-adics::
554
555
sage: E = EllipticCurve('37a1')
556
sage: P = E([0,0]); P
557
(0 : 0 : 1)
558
sage: R = pAdicField(3,20)
559
sage: Ep = E.base_extend(R); Ep
560
Elliptic Curve defined by y^2 + (1+O(3^20))*y = x^3 + (2+2*3+2*3^2+2*3^3+2*3^4+2*3^5+2*3^6+2*3^7+2*3^8+2*3^9+2*3^10+2*3^11+2*3^12+2*3^13+2*3^14+2*3^15+2*3^16+2*3^17+2*3^18+2*3^19+O(3^20))*x over 3-adic Field with capped relative precision 20
561
sage: Ep(P)
562
(0 : 0 : 1 + O(3^20))
563
564
Constructing points from the torsion subgroup (which is an abstract
565
abelian group)::
566
567
sage: E = EllipticCurve('14a1')
568
sage: T = E.torsion_subgroup()
569
sage: [E(t) for t in T]
570
[(0 : 1 : 0),
571
(9 : 23 : 1),
572
(2 : 2 : 1),
573
(1 : -1 : 1),
574
(2 : -5 : 1),
575
(9 : -33 : 1)]
576
577
::
578
579
sage: E = EllipticCurve([0,0,0,-49,0])
580
sage: T = E.torsion_subgroup()
581
sage: [E(t) for t in T]
582
[(0 : 1 : 0), (7 : 0 : 1), (0 : 0 : 1), (-7 : 0 : 1)]
583
584
::
585
586
sage: E = EllipticCurve('37a1')
587
sage: T = E.torsion_subgroup()
588
sage: [E(t) for t in T]
589
[(0 : 1 : 0)]
590
"""
591
if len(args) == 1 and args[0] == 0:
592
R = self.base_ring()
593
return self.point([R(0),R(1),R(0)], check=False)
594
P = args[0]
595
if isinstance(P, groups.AdditiveAbelianGroupElement) and isinstance(P.parent(),ell_torsion.EllipticCurveTorsionSubgroup):
596
return self(P.element())
597
if isinstance(args[0],
598
(ell_point.EllipticCurvePoint_field, \
599
ell_point.EllipticCurvePoint_number_field, \
600
ell_point.EllipticCurvePoint)):
601
# check if denominator of the point contains a factor of the
602
# characteristic of the base ring. if so, coerce the point to
603
# infinity.
604
characteristic = self.base_ring().characteristic()
605
if characteristic != 0 and isinstance(args[0][0], rings.Rational) and isinstance(args[0][1], rings.Rational):
606
if rings.mod(args[0][0].denominator(),characteristic) == 0 or rings.mod(args[0][1].denominator(),characteristic) == 0:
607
return self._reduce_point(args[0], characteristic)
608
args = tuple(args[0])
609
610
return plane_curve.ProjectiveCurve_generic.__call__(self, *args, **kwds)
611
612
def _reduce_point(self, R, p):
613
r"""
614
Reduces a point R on an ellipitc curve to the corresponding point on
615
the elliptic curve reduced modulo p. Used to coerce points between
616
curves when p is a factor of the denominator of one of the
617
coordinates.
618
619
This functionality is used internally in the \code{call} method for
620
elliptic curves.
621
622
INPUT:
623
R -- a point on an elliptic curve
624
p -- a prime
625
626
OUTPUT:
627
S -- the corresponding point of the elliptic curve containing R, but
628
reduced modulo p
629
630
EXAMPLES:
631
Suppose we have a point with large height on a rational elliptic curve
632
whose denominator contains a factor of 11::
633
634
sage: E = EllipticCurve([1,-1,0,94,9])
635
sage: R = E([0,3]) + 5*E([8,31])
636
sage: factor(R.xy()[0].denominator())
637
2^2 * 11^2 * 1457253032371^2
638
639
Since 11 is a factor of the denominator, this point corresponds to the
640
point at infinity on the same curve but reduced modulo 11. The reduce
641
function tells us this::
642
643
sage: E11 = E.change_ring(GF(11))
644
sage: S = E11._reduce_point(R, 11)
645
sage: E11(S)
646
(0 : 1 : 0)
647
648
The 0 point reduces as expected::
649
650
sage: E11._reduce_point(E(0), 11)
651
(0 : 1 : 0)
652
653
Note that one need not explicitly call
654
\code{EllipticCurve._reduce_point}
655
"""
656
if R.is_zero():
657
return R.curve().change_ring(rings.GF(p))(0)
658
x, y = R.xy()
659
d = arith.LCM(x.denominator(), y.denominator())
660
return R.curve().change_ring(rings.GF(p))([x*d, y*d, d])
661
662
def is_x_coord(self, x):
663
r"""
664
Returns True if ``x`` is the `x`-coordinate of a point on this curve.
665
666
.. note::
667
668
See also ``lift_x()`` to find the point(s) with a given
669
`x`-coordinate. This function may be useful in cases where
670
testing an element of the base field for being a square is
671
faster than finding its square root.
672
673
EXAMPLES::
674
675
sage: E = EllipticCurve('37a'); E
676
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
677
sage: E.is_x_coord(1)
678
True
679
sage: E.is_x_coord(2)
680
True
681
682
There are no rational points with x-coordinate 3::
683
684
sage: E.is_x_coord(3)
685
False
686
687
However, there are such points in `E(\RR)`::
688
689
sage: E.change_ring(RR).is_x_coord(3)
690
True
691
692
And of course it always works in `E(\CC)`::
693
694
sage: E.change_ring(RR).is_x_coord(-3)
695
False
696
sage: E.change_ring(CC).is_x_coord(-3)
697
True
698
699
AUTHORS:
700
701
- John Cremona (2008-08-07): adapted from lift_x()
702
703
TEST::
704
705
sage: E=EllipticCurve('5077a1')
706
sage: [x for x in srange(-10,10) if E.is_x_coord (x)]
707
[-3, -2, -1, 0, 1, 2, 3, 4, 8]
708
709
::
710
711
sage: F=GF(32,'a')
712
sage: E=EllipticCurve(F,[1,0,0,0,1])
713
sage: set([P[0] for P in E.points() if P!=E(0)]) == set([x for x in F if E.is_x_coord(x)])
714
True
715
"""
716
K = self.base_ring()
717
try:
718
x = K(x)
719
except TypeError:
720
raise TypeError, 'x must be coercible into the base ring of the curve'
721
a1, a2, a3, a4, a6 = self.ainvs()
722
fx = ((x + a2) * x + a4) * x + a6
723
if a1.is_zero() and a3.is_zero():
724
return fx.is_square()
725
b = (a1*x + a3)
726
if K.characteristic() == 2:
727
R = PolynomialRing(K, 'y')
728
F = R([-fx,b,1])
729
return len(F.roots())>0
730
D = b*b + 4*fx
731
return D.is_square()
732
733
def lift_x(self, x, all=False):
734
r"""
735
Returns one or all points with given `x`-coordinate.
736
737
INPUT:
738
739
- ``x`` -- an element of the base ring of the curve.
740
741
- ``all`` (bool, default False) -- if True, return a (possibly
742
empty) list of all points; if False, return just one point,
743
or raise a ValueError if there are none.
744
745
.. note::
746
747
See also ``is_x_coord()``.
748
749
EXAMPLES::
750
751
sage: E = EllipticCurve('37a'); E
752
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
753
sage: E.lift_x(1)
754
(1 : 0 : 1)
755
sage: E.lift_x(2)
756
(2 : 2 : 1)
757
sage: E.lift_x(1/4, all=True)
758
[(1/4 : -3/8 : 1), (1/4 : -5/8 : 1)]
759
760
There are no rational points with `x`-coordinate 3::
761
762
sage: E.lift_x(3)
763
Traceback (most recent call last):
764
...
765
ValueError: No point with x-coordinate 3 on Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
766
767
However, there are two such points in `E(\RR)`::
768
769
sage: E.change_ring(RR).lift_x(3, all=True)
770
[(3.00000000000000 : 4.42442890089805 : 1.00000000000000), (3.00000000000000 : -5.42442890089805 : 1.00000000000000)]
771
772
And of course it always works in `E(\CC)`::
773
774
sage: E.change_ring(RR).lift_x(.5, all=True)
775
[]
776
sage: E.change_ring(CC).lift_x(.5)
777
(0.500000000000000 : -0.500000000000000 + 0.353553390593274*I : 1.00000000000000)
778
779
We can perform these operations over finite fields too::
780
781
sage: E = E.change_ring(GF(17)); E
782
Elliptic Curve defined by y^2 + y = x^3 + 16*x over Finite Field of size 17
783
sage: E.lift_x(7)
784
(7 : 11 : 1)
785
sage: E.lift_x(3)
786
Traceback (most recent call last):
787
...
788
ValueError: No point with x-coordinate 3 on Elliptic Curve defined by y^2 + y = x^3 + 16*x over Finite Field of size 17
789
790
Note that there is only one lift with `x`-coordinate 10 in
791
`E(\GF{17})`::
792
793
sage: E.lift_x(10, all=True)
794
[(10 : 8 : 1)]
795
796
We can lift over more exotic rings too::
797
798
sage: E = EllipticCurve('37a');
799
sage: E.lift_x(pAdicField(17, 5)(6))
800
(6 + O(17^5) : 2 + 16*17 + 16*17^2 + 16*17^3 + 16*17^4 + O(17^5) : 1 + O(17^5))
801
sage: K.<t> = PowerSeriesRing(QQ, 't', 5)
802
sage: E.lift_x(1+t)
803
(1 + t : 2*t - t^2 + 5*t^3 - 21*t^4 + O(t^5) : 1)
804
sage: K.<a> = GF(16)
805
sage: E = E.change_ring(K)
806
sage: E.lift_x(a^3)
807
(a^3 : a^3 + a : 1)
808
809
AUTHOR:
810
811
- Robert Bradshaw (2007-04-24)
812
813
TEST::
814
815
sage: E = EllipticCurve('37a').short_weierstrass_model().change_ring(GF(17))
816
sage: E.lift_x(3, all=True)
817
[]
818
sage: E.lift_x(7, all=True)
819
[(7 : 3 : 1), (7 : 14 : 1)]
820
"""
821
a1, a2, a3, a4, a6 = self.ainvs()
822
f = ((x + a2) * x + a4) * x + a6
823
K = self.base_ring()
824
x += K(0)
825
one = x.parent()(1)
826
if a1.is_zero() and a3.is_zero():
827
if f.is_square():
828
if all:
829
ys = f.sqrt(all=True)
830
return [self.point([x, y, one], check=False) for y in ys]
831
else:
832
return self.point([x, f.sqrt(), one], check=False)
833
else:
834
b = (a1*x + a3)
835
D = b*b + 4*f
836
if K.characteristic() == 2:
837
R = PolynomialRing(K, 'y')
838
F = R([-f,b,1])
839
ys = F.roots(multiplicities=False)
840
if all:
841
return [self.point([x, y, one], check=False) for y in ys]
842
elif len(ys) > 0:
843
return self.point([x, ys[0], one], check=False)
844
elif D.is_square():
845
if all:
846
return [self.point([x, (-b+d)/2, one], check=False) for d in D.sqrt(all=True)]
847
else:
848
return self.point([x, (-b+D.sqrt())/2, one], check=False)
849
if all:
850
return []
851
else:
852
raise ValueError, "No point with x-coordinate %s on %s"%(x, self)
853
854
def _point_homset(self, *args, **kwds):
855
r"""
856
Internal function. Returns the (abstract) group of points on this
857
elliptic curve over a ring.
858
859
EXAMPLES::
860
861
sage: E=EllipticCurve(GF(5),[1,1])
862
sage: E._point_homset(Spec(GF(5^10,'a'),GF(5)), E)
863
Abelian group of points on Elliptic Curve defined
864
by y^2 = x^3 + x + 1 over Finite Field in a of size 5^10
865
"""
866
return homset.SchemeHomset_points_abelian_variety_field(*args, **kwds)
867
868
def __getitem__(self, n):
869
r"""
870
Placeholder for standard indexing function.
871
872
EXAMPLES::
873
874
sage: E=EllipticCurve(QQ,[1,1])
875
sage: E[2]
876
Traceback (most recent call last):
877
...
878
NotImplementedError: not implemented.
879
"""
880
raise NotImplementedError, "not implemented."
881
882
def __is_over_RationalField(self):
883
r"""
884
Internal function. Returns true iff the base ring of this elliptic
885
curve is the field of rational numbers.
886
887
EXAMPLES::
888
889
sage: E=EllipticCurve(QQ,[1,1])
890
sage: E._EllipticCurve_generic__is_over_RationalField()
891
True
892
sage: E=EllipticCurve(GF(5),[1,1])
893
sage: E._EllipticCurve_generic__is_over_RationalField()
894
False
895
"""
896
return isinstance(self.base_ring(), rings.RationalField)
897
898
def is_on_curve(self, x, y):
899
r"""
900
Returns True if `(x,y)` is an affine point on this curve.
901
902
INPUT:
903
904
- ``x``, ``y`` - elements of the base ring of the curve.
905
906
EXAMPLES::
907
908
sage: E=EllipticCurve(QQ,[1,1])
909
sage: E.is_on_curve(0,1)
910
True
911
sage: E.is_on_curve(1,1)
912
False
913
"""
914
a = self.ainvs()
915
return y**2 +a[0]*x*y + a[2]*y == x**3 + a[1]*x**2 + a[3]*x + a[4]
916
917
def a_invariants(self):
918
r"""
919
The `a`-invariants of this elliptic curve, as a tuple.
920
921
OUTPUT:
922
923
(tuple) - a 5-tuple of the `a`-invariants of this elliptic curve.
924
925
EXAMPLES::
926
927
sage: E = EllipticCurve([1,2,3,4,5])
928
sage: E.a_invariants()
929
(1, 2, 3, 4, 5)
930
sage: E = EllipticCurve([0,1])
931
sage: E
932
Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
933
sage: E.a_invariants()
934
(0, 0, 0, 0, 1)
935
sage: E = EllipticCurve([GF(7)(3),5])
936
sage: E.a_invariants()
937
(0, 0, 0, 3, 5)
938
939
::
940
941
sage: E = EllipticCurve([1,0,0,0,1])
942
sage: E.a_invariants()[0] = 100000000
943
Traceback (most recent call last):
944
...
945
TypeError: 'tuple' object does not support item assignment
946
947
"""
948
return self.__ainvs
949
950
ainvs = a_invariants
951
952
def a1(self):
953
r"""
954
Returns the `a_1` invariant of this elliptic curve.
955
956
EXAMPLES::
957
958
sage: E = EllipticCurve([1,2,3,4,6])
959
sage: E.a1()
960
1
961
"""
962
return self.__ainvs[0]
963
964
def a2(self):
965
r"""
966
Returns the `a_2` invariant of this elliptic curve.
967
968
EXAMPLES::
969
970
sage: E = EllipticCurve([1,2,3,4,6])
971
sage: E.a2()
972
2
973
"""
974
return self.__ainvs[1]
975
976
def a3(self):
977
r"""
978
Returns the `a_3` invariant of this elliptic curve.
979
980
EXAMPLES::
981
982
sage: E = EllipticCurve([1,2,3,4,6])
983
sage: E.a3()
984
3
985
"""
986
return self.__ainvs[2]
987
988
def a4(self):
989
r"""
990
Returns the `a_4` invariant of this elliptic curve.
991
992
EXAMPLES::
993
994
sage: E = EllipticCurve([1,2,3,4,6])
995
sage: E.a4()
996
4
997
"""
998
return self.__ainvs[3]
999
1000
def a6(self):
1001
r"""
1002
Returns the `a_6` invariant of this elliptic curve.
1003
1004
EXAMPLES::
1005
1006
sage: E = EllipticCurve([1,2,3,4,6])
1007
sage: E.a6()
1008
6
1009
"""
1010
return self.__ainvs[4]
1011
1012
def b_invariants(self):
1013
r"""
1014
Returns the `b`-invariants of this elliptic curve, as a tuple.
1015
1016
OUTPUT:
1017
1018
(tuple) - a 4-tuple of the `b`-invariants of this elliptic curve.
1019
1020
EXAMPLES::
1021
1022
sage: E = EllipticCurve([0, -1, 1, -10, -20])
1023
sage: E.b_invariants()
1024
(-4, -20, -79, -21)
1025
sage: E = EllipticCurve([-4,0])
1026
sage: E.b_invariants()
1027
(0, -8, 0, -16)
1028
1029
::
1030
1031
sage: E = EllipticCurve([1,2,3,4,5])
1032
sage: E.b_invariants()
1033
(9, 11, 29, 35)
1034
sage: E.b2()
1035
9
1036
sage: E.b4()
1037
11
1038
sage: E.b6()
1039
29
1040
sage: E.b8()
1041
35
1042
1043
ALGORITHM:
1044
1045
These are simple functions of the `a`-invariants.
1046
1047
AUTHORS:
1048
1049
- William Stein (2005-04-25)
1050
"""
1051
try:
1052
return self.__b_invariants
1053
except AttributeError:
1054
a1,a2,a3,a4,a6 = self.ainvs()
1055
self.__b_invariants = a1*a1 + 4*a2, \
1056
a1*a3 + 2*a4, \
1057
a3**2 + 4*a6, \
1058
a1**2 * a6 + 4*a2*a6 - a1*a3*a4 + a2*a3**2 - a4**2
1059
return self.__b_invariants
1060
1061
def b2(self):
1062
r"""
1063
Returns the `b_2` invariant of this elliptic curve.
1064
1065
EXAMPLES::
1066
1067
sage: E = EllipticCurve([1,2,3,4,5])
1068
sage: E.b2()
1069
9
1070
"""
1071
try:
1072
return self.__b_invariants[0]
1073
except AttributeError:
1074
return self.b_invariants()[0]
1075
1076
def b4(self):
1077
r"""
1078
Returns the `b_4` invariant of this elliptic curve.
1079
1080
EXAMPLES::
1081
1082
sage: E = EllipticCurve([1,2,3,4,5])
1083
sage: E.b4()
1084
11
1085
"""
1086
try:
1087
return self.__b_invariants[1]
1088
except AttributeError:
1089
return self.b_invariants()[1]
1090
1091
def b6(self):
1092
r"""
1093
Returns the `b_6` invariant of this elliptic curve.
1094
1095
EXAMPLES::
1096
1097
sage: E = EllipticCurve([1,2,3,4,5])
1098
sage: E.b6()
1099
29
1100
"""
1101
try:
1102
return self.__b_invariants[2]
1103
except AttributeError:
1104
return self.b_invariants()[2]
1105
1106
def b8(self):
1107
r"""
1108
Returns the `b_8` invariant of this elliptic curve.
1109
1110
EXAMPLES::
1111
1112
sage: E = EllipticCurve([1,2,3,4,5])
1113
sage: E.b8()
1114
35
1115
"""
1116
try:
1117
return self.__b_invariants[3]
1118
except AttributeError:
1119
return self.b_invariants()[3]
1120
1121
def c_invariants(self):
1122
r"""
1123
Returns the `c`-invariants of this elliptic curve, as a tuple.
1124
1125
OUTPUT:
1126
1127
(tuple) - a 2-tuple of the `c`-invariants of the elliptic curve.
1128
1129
EXAMPLES::
1130
1131
sage: E = EllipticCurve([0, -1, 1, -10, -20])
1132
sage: E.c_invariants()
1133
(496, 20008)
1134
sage: E = EllipticCurve([-4,0])
1135
sage: E.c_invariants()
1136
(192, 0)
1137
1138
ALGORITHM:
1139
1140
These are simple functions of the `a`-invariants.
1141
1142
AUTHORS:
1143
1144
- William Stein (2005-04-25)
1145
"""
1146
try:
1147
return self.__c_invariants
1148
except AttributeError:
1149
b2,b4,b6,b8 = self.b_invariants()
1150
self.__c_invariants = b2**2 - 24*b4,\
1151
-b2**3 + 36*b2*b4 - 216*b6 # note: c6 is wrong in Silverman, but right in Cremona
1152
return self.__c_invariants
1153
1154
def c4(self):
1155
r"""
1156
Returns the `c_4` invariant of this elliptic curve.
1157
1158
EXAMPLES::
1159
1160
sage: E = EllipticCurve([0, -1, 1, -10, -20])
1161
sage: E.c4()
1162
496
1163
"""
1164
try:
1165
return self.__c_invariants[0]
1166
except AttributeError:
1167
pass
1168
return self.c_invariants()[0]
1169
1170
def c6(self):
1171
r"""
1172
Returns the `c_6` invariant of this elliptic curve.
1173
1174
EXAMPLES::
1175
1176
sage: E = EllipticCurve([0, -1, 1, -10, -20])
1177
sage: E.c6()
1178
20008
1179
"""
1180
try:
1181
return self.__c_invariants[1]
1182
except AttributeError:
1183
pass
1184
return self.c_invariants()[1]
1185
1186
def discriminant(self):
1187
r"""
1188
Returns the discriminant of this elliptic curve.
1189
1190
EXAMPLES::
1191
1192
sage: E = EllipticCurve([0,0,1,-1,0])
1193
sage: E.discriminant()
1194
37
1195
sage: E = EllipticCurve([0, -1, 1, -10, -20])
1196
sage: E.discriminant()
1197
-161051
1198
1199
::
1200
1201
sage: E = EllipticCurve([GF(7)(2),1])
1202
sage: E.discriminant()
1203
1
1204
"""
1205
try:
1206
return self.__discriminant
1207
except AttributeError:
1208
b2, b4, b6, b8 = self.b_invariants()
1209
self.__discriminant = -b2**2*b8 - 8*b4**3 - 27*b6**2 + 9*b2*b4*b6
1210
return self.__discriminant
1211
1212
def j_invariant(self):
1213
r"""
1214
Returns the `j`-invariant of this elliptic curve.
1215
1216
EXAMPLES::
1217
1218
sage: E = EllipticCurve([0,0,1,-1,0])
1219
sage: E.j_invariant()
1220
110592/37
1221
sage: E = EllipticCurve([0, -1, 1, -10, -20])
1222
sage: E.j_invariant()
1223
-122023936/161051
1224
sage: E = EllipticCurve([-4,0])
1225
sage: E.j_invariant()
1226
1728
1227
1228
::
1229
1230
sage: E = EllipticCurve([GF(7)(2),1])
1231
sage: E.j_invariant()
1232
1
1233
"""
1234
try:
1235
return self.__j_invariant
1236
except AttributeError:
1237
c4, _ = self.c_invariants()
1238
self.__j_invariant = c4**3 / self.discriminant()
1239
return self.__j_invariant
1240
1241
1242
def base_extend(self, R):
1243
r"""
1244
Returns a new curve with the same `a`-invariants but defined over a new ring.
1245
1246
INPUT:
1247
1248
- ``R`` -- either a ring into which the curve's `a`-invariants
1249
may be coerced, or a morphism which may be applied to them.
1250
1251
OUTPUT:
1252
1253
A new elliptic curve with the same `a`-invariants, defined over the new ring.
1254
1255
EXAMPLES::
1256
1257
sage: E=EllipticCurve(GF(5),[1,1]); E
1258
Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
1259
sage: E1=E.base_extend(GF(125,'a')); E1
1260
Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in a of size 5^3
1261
sage: F2=GF(5^2,'a'); a=F2.gen()
1262
sage: F4=GF(5^4,'b'); b=F4.gen()
1263
sage: h=F2.hom([a.charpoly().roots(ring=F4,multiplicities=False)[0]],F4)
1264
sage: E=EllipticCurve(F2,[1,a]); E
1265
Elliptic Curve defined by y^2 = x^3 + x + a over Finite Field in a of size 5^2
1266
sage: E.base_extend(h)
1267
Elliptic Curve defined by y^2 = x^3 + x + (4*b^3+4*b^2+4*b+3) over Finite Field in b of size 5^4
1268
"""
1269
return constructor.EllipticCurve([R(a) for a in self.a_invariants()])
1270
1271
change_ring = base_extend
1272
1273
def base_ring(self):
1274
r"""
1275
Returns the base ring of the elliptic curve.
1276
1277
EXAMPLES::
1278
1279
sage: E = EllipticCurve(GF(49, 'a'), [3,5])
1280
sage: E.base_ring()
1281
Finite Field in a of size 7^2
1282
1283
::
1284
1285
sage: E = EllipticCurve([1,1])
1286
sage: E.base_ring()
1287
Rational Field
1288
1289
::
1290
1291
sage: E = EllipticCurve(ZZ, [3,5])
1292
sage: E.base_ring()
1293
Integer Ring
1294
"""
1295
return self.__base_ring
1296
1297
def gens(self):
1298
r"""
1299
Placeholder function to return generators of an elliptic curve.
1300
1301
.. note::
1302
1303
This functionality is implemented in certain derived
1304
classes, such as EllipticCurve_rational_field.
1305
1306
EXAMPLES::
1307
1308
sage: R.<a1,a2,a3,a4,a6>=QQ[]
1309
sage: E=EllipticCurve([a1,a2,a3,a4,a6])
1310
sage: E.gens()
1311
Traceback (most recent call last):
1312
...
1313
NotImplementedError: not implemented.
1314
sage: E=EllipticCurve(QQ,[1,1])
1315
sage: E.gens()
1316
[(0 : 1 : 1)]
1317
"""
1318
raise NotImplementedError, "not implemented."
1319
1320
def gen(self, i):
1321
r"""
1322
Function returning the i'th generator of this elliptic curve.
1323
1324
.. note::
1325
1326
Relies on gens() being implemented.
1327
1328
EXAMPLES::
1329
1330
sage: R.<a1,a2,a3,a4,a6>=QQ[]
1331
sage: E=EllipticCurve([a1,a2,a3,a4,a6])
1332
sage: E.gen(0)
1333
Traceback (most recent call last):
1334
...
1335
NotImplementedError: not implemented.
1336
"""
1337
return self.gens()[i]
1338
1339
def rst_transform(self, r, s, t):
1340
r"""
1341
Returns the transform of the curve by `(r,s,t)` (with `u=1`).
1342
1343
INPUT:
1344
1345
- ``r``, ``s``, ``t`` -- three elements of the base ring.
1346
1347
OUTPUT:
1348
1349
The elliptic curve obtained from self by the standard
1350
Weierstrass transformation `(u,r,s,t)` with `u=1`.
1351
1352
.. note::
1353
1354
This is just a special case of ``change_weierstrass_model()``, with `u=1`.
1355
1356
EXAMPLES::
1357
1358
sage: R.<r,s,t>=QQ[]
1359
sage: E=EllipticCurve([1,2,3,4,5])
1360
sage: E.rst_transform(r,s,t)
1361
Elliptic Curve defined by y^2 + (2*s+1)*x*y + (r+2*t+3)*y = x^3 + (-s^2+3*r-s+2)*x^2 + (3*r^2-r*s-2*s*t+4*r-3*s-t+4)*x + (r^3+2*r^2-r*t-t^2+4*r-3*t+5) over Multivariate Polynomial Ring in r, s, t over Rational Field
1362
"""
1363
return self.change_weierstrass_model(1,r,s,t)
1364
1365
def scale_curve(self, u):
1366
r"""
1367
Returns the transform of the curve by scale factor `u`.
1368
1369
INPUT:
1370
1371
- ``u`` -- an invertible element of the base ring.
1372
1373
OUTPUT:
1374
1375
The elliptic curve obtained from self by the standard
1376
Weierstrass transformation `(u,r,s,t)` with `r=s=t=0`.
1377
1378
.. note::
1379
1380
This is just a special case of ``change_weierstrass_model()``, with `r=s=t=0`.
1381
1382
EXAMPLES::
1383
1384
sage: K=Frac(PolynomialRing(QQ,'u'))
1385
sage: u=K.gen()
1386
sage: E=EllipticCurve([1,2,3,4,5])
1387
sage: E.scale_curve(u)
1388
Elliptic Curve defined by y^2 + u*x*y + 3*u^3*y = x^3 + 2*u^2*x^2 + 4*u^4*x + 5*u^6 over Fraction Field of Univariate Polynomial Ring in u over Rational Field
1389
"""
1390
if isinstance(u, (int,long)):
1391
u=self.base_ring()(u) # because otherwise 1/u would round!
1392
return self.change_weierstrass_model(1/u,0,0,0)
1393
1394
def discriminant(self):
1395
r"""
1396
Returns the discriminant of this elliptic curve.
1397
1398
EXAMPLES::
1399
1400
sage: E = EllipticCurve([0,0,1,-1,0])
1401
sage: E.discriminant()
1402
37
1403
sage: E = EllipticCurve([0, -1, 1, -10, -20])
1404
sage: E.discriminant()
1405
-161051
1406
1407
::
1408
1409
sage: E = EllipticCurve([GF(7)(2),1])
1410
sage: E.discriminant()
1411
1
1412
"""
1413
try:
1414
return self.__discriminant
1415
except AttributeError:
1416
b2, b4, b6, b8 = self.b_invariants()
1417
self.__discriminant = -b2**2*b8 - 8*b4**3 - 27*b6**2 + 9*b2*b4*b6
1418
return self.__discriminant
1419
1420
def j_invariant(self):
1421
r"""
1422
Returns the j-invariant of this elliptic curve.
1423
1424
EXAMPLES::
1425
1426
sage: E = EllipticCurve([0,0,1,-1,0])
1427
sage: E.j_invariant()
1428
110592/37
1429
sage: E = EllipticCurve([0, -1, 1, -10, -20])
1430
sage: E.j_invariant()
1431
-122023936/161051
1432
sage: E = EllipticCurve([-4,0])
1433
sage: E.j_invariant()
1434
1728
1435
1436
::
1437
1438
sage: E = EllipticCurve([GF(7)(2),1])
1439
sage: E.j_invariant()
1440
1
1441
"""
1442
try:
1443
return self.__j_invariant
1444
except AttributeError:
1445
c4, _ = self.c_invariants()
1446
self.__j_invariant = c4**3 / self.discriminant()
1447
return self.__j_invariant
1448
1449
#############################################################
1450
#
1451
# Explanation of the division (also known as torsion) polynomial
1452
# functions in Sage.
1453
#
1454
# The main user function division_polynomial() (also aliased as
1455
# torsion_polynomial()) is used to compute polynomials whose roots
1456
# determine the $m$-torsion points on the curve. Three options are
1457
# available, which effect the result when $m$ is even and also the
1458
# parent ring of the returned value. The function can return either a
1459
# polynomial or the evaluation of that polynomial at a point,
1460
# depending on the input. Values are cached.
1461
#
1462
# The options are controlled by the value of the parameter
1463
# two_torsion_multiplicity, which may be 0, 1 or 2. If it is 0 or 2,
1464
# then a univariate polynomial will be returned (or evaluated at the
1465
# parameter x if x is not None). This is the polynomial whose roots
1466
# are the values of $x(P)$ at the nonzero points $P$ where $m*P=0$
1467
# (when two_torsion_multiplicity==2), or the points where $m*P=0$ but
1468
# $2*P\not=0$ (when two_torsion_multiplicity==0).
1469
#
1470
# If two_torsion_multiplicity==1, then a bivariate polynomial is
1471
# returned, which (as a function on the curve) has a simple zero at
1472
# each nonzero point $P$ such that $m*P=0$. When $m$ is odd this is a
1473
# polynomial in $x$ alone, but is still returned as an element of a
1474
# polynomial ring in two variables; when $m$ is even it has a factor
1475
# $2y+a_1x+a_3$. In this case if the parameter x is not None then it
1476
# should be a tuple of length 2, or a point P on the curve, and the
1477
# returned value is the value of the bivariate polynomial at this
1478
# point.
1479
#
1480
# Comparison with Magma: Magma's function DivisionPolynomial(E,m)
1481
# returns a triple of univariate polynomials $f,g,h$ where $f$ is
1482
# \code{E.division_polynomial(m,two_torsion_multiplicity=2)}, $g$ is
1483
# \code{E.division_polynomial(m,two_torsion_multiplicity=0)} and $h$
1484
# is the quotient, so that $h=1$ when $m$ is odd.
1485
1486
#############################################################
1487
1488
def division_polynomial_0(self, n, x=None, cache=None):
1489
r"""
1490
Returns the `n^{th}` torsion (division) polynomial, without
1491
the 2-torsion factor if `n` is even, as a polynomial in `x`.
1492
1493
These are the polynomials `g_n` defined in Mazur/Tate
1494
("The p-adic sigma function"), but with the sign flipped for even
1495
`n`, so that the leading coefficient is always positive.
1496
1497
.. note::
1498
1499
This function is intended for internal use; users should use
1500
:meth:`.division_polynomial`.
1501
1502
.. seealso::
1503
1504
:meth:`multiple_x_numerator`
1505
:meth:`multiple_x_denominator`
1506
:meth:`division_polynomial`
1507
1508
INPUT:
1509
1510
1511
- ``n`` - positive integer, or the special values `-1`
1512
and `-2` which mean `B_6 = (2y + a_1 x + a_3)^2` and
1513
`B_6^2` respectively (in the notation of Mazur/Tate).
1514
1515
- ``x`` - optional ring element to use as the "x"
1516
variable. If x is None, then a new polynomial ring will be
1517
constructed over the base ring of the elliptic curve, and its
1518
generator will be used as x. Note that x does not need to be a
1519
generator of a polynomial ring; any ring element is ok. This
1520
permits fast calculation of the torsion polynomial *evaluated* on
1521
any element of a ring.
1522
1523
- ``cache`` - optional dictionary, with integer keys.
1524
If the key m is in cache, then cache[m] is assumed to be the value
1525
of division_polynomial_0(m) for the supplied x. New entries will
1526
be added to the cache as they are computed.
1527
1528
1529
ALGORITHM:
1530
1531
Recursion described in Mazur/Tate. The recursive
1532
formulae are evaluated `O((log n)^2)` times.
1533
1534
AUTHORS:
1535
1536
- David Harvey (2006-09-24): initial version
1537
1538
- John Cremona (2008-08-26): unified division polynomial code
1539
1540
EXAMPLES::
1541
1542
sage: E = EllipticCurve("37a")
1543
sage: E.division_polynomial_0(1)
1544
1
1545
sage: E.division_polynomial_0(2)
1546
1
1547
sage: E.division_polynomial_0(3)
1548
3*x^4 - 6*x^2 + 3*x - 1
1549
sage: E.division_polynomial_0(4)
1550
2*x^6 - 10*x^4 + 10*x^3 - 10*x^2 + 2*x + 1
1551
sage: E.division_polynomial_0(5)
1552
5*x^12 - 62*x^10 + 95*x^9 - 105*x^8 - 60*x^7 + 285*x^6 - 174*x^5 - 5*x^4 - 5*x^3 + 35*x^2 - 15*x + 2
1553
sage: E.division_polynomial_0(6)
1554
3*x^16 - 72*x^14 + 168*x^13 - 364*x^12 + 1120*x^10 - 1144*x^9 + 300*x^8 - 540*x^7 + 1120*x^6 - 588*x^5 - 133*x^4 + 252*x^3 - 114*x^2 + 22*x - 1
1555
sage: E.division_polynomial_0(7)
1556
7*x^24 - 308*x^22 + 986*x^21 - 2954*x^20 + 28*x^19 + 17171*x^18 - 23142*x^17 + 511*x^16 - 5012*x^15 + 43804*x^14 - 7140*x^13 - 96950*x^12 + 111356*x^11 - 19516*x^10 - 49707*x^9 + 40054*x^8 - 124*x^7 - 18382*x^6 + 13342*x^5 - 4816*x^4 + 1099*x^3 - 210*x^2 + 35*x - 3
1557
sage: E.division_polynomial_0(8)
1558
4*x^30 - 292*x^28 + 1252*x^27 - 5436*x^26 + 2340*x^25 + 39834*x^24 - 79560*x^23 + 51432*x^22 - 142896*x^21 + 451596*x^20 - 212040*x^19 - 1005316*x^18 + 1726416*x^17 - 671160*x^16 - 954924*x^15 + 1119552*x^14 + 313308*x^13 - 1502818*x^12 + 1189908*x^11 - 160152*x^10 - 399176*x^9 + 386142*x^8 - 220128*x^7 + 99558*x^6 - 33528*x^5 + 6042*x^4 + 310*x^3 - 406*x^2 + 78*x - 5
1559
1560
::
1561
1562
sage: E.division_polynomial_0(18) % E.division_polynomial_0(6) == 0
1563
True
1564
1565
An example to illustrate the relationship with torsion points::
1566
1567
sage: F = GF(11)
1568
sage: E = EllipticCurve(F, [0, 2]); E
1569
Elliptic Curve defined by y^2 = x^3 + 2 over Finite Field of size 11
1570
sage: f = E.division_polynomial_0(5); f
1571
5*x^12 + x^9 + 8*x^6 + 4*x^3 + 7
1572
sage: f.factor()
1573
(5) * (x^2 + 5) * (x^2 + 2*x + 5) * (x^2 + 5*x + 7) * (x^2 + 7*x + 7) * (x^2 + 9*x + 5) * (x^2 + 10*x + 7)
1574
1575
This indicates that the x-coordinates of all the 5-torsion points
1576
of `E` are in `GF(11^2)`, and therefore the
1577
`y`-coordinates are in `\GF(11^4)`::
1578
1579
sage: K = GF(11^4, 'a')
1580
sage: X = E.change_ring(K)
1581
sage: f = X.division_polynomial_0(5)
1582
sage: x_coords = f.roots(multiplicities=False); x_coords
1583
[10*a^3 + 4*a^2 + 5*a + 6,
1584
9*a^3 + 8*a^2 + 10*a + 8,
1585
8*a^3 + a^2 + 4*a + 10,
1586
8*a^3 + a^2 + 4*a + 8,
1587
8*a^3 + a^2 + 4*a + 4,
1588
6*a^3 + 9*a^2 + 3*a + 4,
1589
5*a^3 + 2*a^2 + 8*a + 7,
1590
3*a^3 + 10*a^2 + 7*a + 8,
1591
3*a^3 + 10*a^2 + 7*a + 3,
1592
3*a^3 + 10*a^2 + 7*a + 1,
1593
2*a^3 + 3*a^2 + a + 7,
1594
a^3 + 7*a^2 + 6*a]
1595
1596
Now we check that these are exactly the `x`-coordinates of the
1597
5-torsion points of `E`::
1598
1599
sage: for x in x_coords:
1600
... assert X.lift_x(x).order() == 5
1601
1602
The roots of the polynomial are the `x`-coordinates of the points `P`
1603
such that `mP=0` but `2P\not=0`::
1604
1605
sage: E=EllipticCurve('14a1')
1606
sage: T=E.torsion_subgroup()
1607
sage: [n*T.0 for n in range(6)]
1608
[(0 : 1 : 0),
1609
(9 : 23 : 1),
1610
(2 : 2 : 1),
1611
(1 : -1 : 1),
1612
(2 : -5 : 1),
1613
(9 : -33 : 1)]
1614
sage: pol=E.division_polynomial_0(6)
1615
sage: xlist=pol.roots(multiplicities=False); xlist
1616
[9, 2, -1/3, -5]
1617
sage: [E.lift_x(x, all=True) for x in xlist]
1618
[[(9 : 23 : 1), (9 : -33 : 1)], [(2 : 2 : 1), (2 : -5 : 1)], [], []]
1619
1620
.. note::
1621
1622
The point of order 2 and the identity do not appear.
1623
The points with `x=-1/3` and `x=-5` are not rational.
1624
"""
1625
if cache is None:
1626
cache = {}
1627
else:
1628
try:
1629
return cache[n]
1630
except KeyError:
1631
pass
1632
1633
if x is None:
1634
x = rings.PolynomialRing(self.base_ring(), 'x').gen()
1635
1636
b2, b4, b6, b8 = self.b_invariants()
1637
1638
n = int(n)
1639
if n <= 4:
1640
if n == -1:
1641
answer = 4*x**3 + b2*x**2 + 2*b4*x + b6
1642
elif n == -2:
1643
answer = self.division_polynomial_0(-1, x, cache) ** 2
1644
elif n == 1 or n == 2:
1645
answer = x.parent()(1)
1646
elif n == 3:
1647
answer = 3*x**4 + b2*x**3 + 3*b4*x**2 + 3*b6*x + b8
1648
elif n == 4:
1649
answer = -self.division_polynomial_0(-2, x, cache) + \
1650
(6*x**2 + b2*x + b4) * \
1651
self.division_polynomial_0(3, x, cache)
1652
else:
1653
raise ValueError, "n must be a positive integer (or -1 or -2)"
1654
else:
1655
if n % 2 == 0:
1656
m = (n-2) // 2
1657
g_mplus3 = self.division_polynomial_0(m+3, x, cache)
1658
g_mplus2 = self.division_polynomial_0(m+2, x, cache)
1659
g_mplus1 = self.division_polynomial_0(m+1, x, cache)
1660
g_m = self.division_polynomial_0(m, x, cache)
1661
g_mless1 = self.division_polynomial_0(m-1, x, cache)
1662
answer = g_mplus1 * \
1663
(g_mplus3 * g_m**2 - g_mless1 * g_mplus2**2)
1664
else:
1665
m = (n-1) // 2
1666
g_mplus2 = self.division_polynomial_0(m+2, x, cache)
1667
g_mplus1 = self.division_polynomial_0(m+1, x, cache)
1668
g_m = self.division_polynomial_0(m, x, cache)
1669
g_mless1 = self.division_polynomial_0(m-1, x, cache)
1670
B6_sqr = self.division_polynomial_0(-2, x, cache)
1671
if m % 2 == 0:
1672
answer = B6_sqr * g_mplus2 * g_m**3 - \
1673
g_mless1 * g_mplus1**3
1674
else:
1675
answer = g_mplus2 * g_m**3 - \
1676
B6_sqr * g_mless1 * g_mplus1**3
1677
1678
cache[n] = answer
1679
return answer
1680
1681
def two_division_polynomial(self, x = None):
1682
r"""
1683
Returns the 2-division polynomial of this elliptic curve evaluated
1684
at ``x``.
1685
1686
INPUT:
1687
1688
- ``x`` - optional ring element to use as the `x` variable. If
1689
``x`` is ``None``, then a new polynomial ring will be
1690
constructed over the base ring of the elliptic curve, and
1691
its generator will be used as ``x``. Note that ``x`` does
1692
not need to be a generator of a polynomial ring; any ring
1693
element is ok. This permits fast calculation of the torsion
1694
polynomial *evaluated* on any element of a ring.
1695
1696
1697
EXAMPLES::
1698
1699
sage: E=EllipticCurve('5077a1')
1700
sage: E.two_division_polynomial()
1701
4*x^3 - 28*x + 25
1702
sage: E=EllipticCurve(GF(3^2,'a'),[1,1,1,1,1])
1703
sage: E.two_division_polynomial()
1704
x^3 + 2*x^2 + 2
1705
sage: E.two_division_polynomial().roots()
1706
[(2, 1), (2*a, 1), (a + 2, 1)]
1707
"""
1708
return self.division_polynomial_0(-1,x)
1709
1710
def division_polynomial(self, m, x=None, two_torsion_multiplicity=2):
1711
r"""
1712
Returns the `m^{th}` division polynomial of this elliptic
1713
curve evaluated at ``x``.
1714
1715
INPUT:
1716
1717
1718
- ``m`` - positive integer.
1719
1720
- ``x`` - optional ring element to use as the "x"
1721
variable. If x is None, then a new polynomial ring will be
1722
constructed over the base ring of the elliptic curve, and its
1723
generator will be used as x. Note that x does not need to be a
1724
generator of a polynomial ring; any ring element is ok. This
1725
permits fast calculation of the torsion polynomial *evaluated* on
1726
any element of a ring.
1727
1728
- ``two_torsion_multiplicity`` - 0,1 or 2
1729
1730
If 0: for even `m` when x is None, a univariate polynomial
1731
over the base ring of the curve is returned, which omits
1732
factors whose roots are the `x`-coordinates of the
1733
`2`-torsion points. Similarly when `x` is not none, the
1734
evaluation of such a polynomial at `x` is returned.
1735
1736
If 2: for even `m` when x is None, a univariate polynomial
1737
over the base ring of the curve is returned, which includes a
1738
factor of degree 3 whose roots are the `x`-coordinates of
1739
the `2`-torsion points. Similarly when `x` is not
1740
none, the evaluation of such a polynomial at `x` is
1741
returned.
1742
1743
If 1: when x is None, a bivariate polynomial over the base
1744
ring of the curve is returned, which includes a factor
1745
`2*y+a1*x+a3` which has simple zeros at the `2`-torsion
1746
points. When `x` is not none, it should be a tuple of
1747
length 2, and the evaluation of such a polynomial at `x`
1748
is returned.
1749
1750
EXAMPLES::
1751
1752
sage: E = EllipticCurve([0,0,1,-1,0])
1753
sage: E.division_polynomial(1)
1754
1
1755
sage: E.division_polynomial(2, two_torsion_multiplicity=0)
1756
1
1757
sage: E.division_polynomial(2, two_torsion_multiplicity=1)
1758
2*y + 1
1759
sage: E.division_polynomial(2, two_torsion_multiplicity=2)
1760
4*x^3 - 4*x + 1
1761
sage: E.division_polynomial(2)
1762
4*x^3 - 4*x + 1
1763
sage: [E.division_polynomial(3, two_torsion_multiplicity=i) for i in range(3)]
1764
[3*x^4 - 6*x^2 + 3*x - 1, 3*x^4 - 6*x^2 + 3*x - 1, 3*x^4 - 6*x^2 + 3*x - 1]
1765
sage: [type(E.division_polynomial(3, two_torsion_multiplicity=i)) for i in range(3)]
1766
[<type 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>,
1767
<type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>,
1768
<type 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>]
1769
1770
::
1771
1772
sage: E = EllipticCurve([0, -1, 1, -10, -20])
1773
sage: R.<z>=PolynomialRing(QQ)
1774
sage: E.division_polynomial(4,z,0)
1775
2*z^6 - 4*z^5 - 100*z^4 - 790*z^3 - 210*z^2 - 1496*z - 5821
1776
sage: E.division_polynomial(4,z)
1777
8*z^9 - 24*z^8 - 464*z^7 - 2758*z^6 + 6636*z^5 + 34356*z^4 + 53510*z^3 + 99714*z^2 + 351024*z + 459859
1778
1779
This does not work, since when two_torsion_multiplicity is 1, we
1780
compute a bivariate polynomial, and must evaluate at a tuple of
1781
length 2::
1782
1783
sage: E.division_polynomial(4,z,1)
1784
Traceback (most recent call last):
1785
...
1786
ValueError: x should be a tuple of length 2 (or None) when two_torsion_multiplicity is 1
1787
sage: R.<z,w>=PolynomialRing(QQ,2)
1788
sage: E.division_polynomial(4,(z,w),1).factor()
1789
(2*w + 1) * (2*z^6 - 4*z^5 - 100*z^4 - 790*z^3 - 210*z^2 - 1496*z - 5821)
1790
1791
We can also evaluate this bivariate polynomial at a point::
1792
1793
sage: P = E(5,5)
1794
sage: E.division_polynomial(4,P,two_torsion_multiplicity=1)
1795
-1771561
1796
"""
1797
1798
if not two_torsion_multiplicity in [0,1,2]:
1799
raise ValueError, "two_torsion_multiplicity must be 0,1 or 2"
1800
1801
# Coerce the input m to be an integer
1802
m = rings.Integer(m)
1803
1804
if two_torsion_multiplicity == 0:
1805
try:
1806
return self.__divpoly0[(m,x)]
1807
except AttributeError:
1808
self.__divpoly0 = {}
1809
except KeyError:
1810
pass
1811
f = self.division_polynomial_0(m,x)
1812
self.__divpoly0[(m,x)] = f
1813
return f
1814
1815
if two_torsion_multiplicity == 1:
1816
try:
1817
return self.__divpoly1[(m,x)]
1818
except AttributeError:
1819
self.__divpoly1 = {}
1820
except KeyError:
1821
pass
1822
xy = x
1823
R, (x,y) = PolynomialRing(self.base_ring(), 2, 'x,y').objgens()
1824
a1,a2,a3,a4,a6 = self.a_invariants()
1825
f = self.division_polynomial_0(m,x)
1826
if m % 2 == 0:
1827
f *= (2*y+a1*x+a3)
1828
if xy is None:
1829
self.__divpoly1[(m,(x,y))] = f
1830
return f
1831
else:
1832
if isinstance(xy,tuple) and len(xy)==2 or isinstance(xy, ell_point.EllipticCurvePoint_field):
1833
fxy = f(xy[0],xy[1])
1834
self.__divpoly1[(m,xy)] = fxy
1835
return fxy
1836
else:
1837
raise ValueError, "x should be a tuple of length 2 (or None) when two_torsion_multiplicity is 1"
1838
1839
if two_torsion_multiplicity == 2:
1840
try:
1841
return self.__divpoly2[(m,x)]
1842
except AttributeError:
1843
self.__divpoly2 = {}
1844
except KeyError:
1845
pass
1846
f = self.division_polynomial_0(m,x)
1847
if m%2 == 0:
1848
f *= self.division_polynomial_0(-1,x)
1849
self.__divpoly2[(m,x)] = f
1850
return f
1851
1852
torsion_polynomial = division_polynomial
1853
1854
def _multiple_x_numerator(self, n, x=None, cache=None):
1855
r"""
1856
Returns the numerator of the `x`-coordinate of the `n\th` multiple of a
1857
point, using torsion polynomials (division polynomials).
1858
1859
INPUT:
1860
1861
- ``n``, ``x``, ``cache`` -- as described in ``division_polynomial_0()``.
1862
1863
The result is cached. This is so that on calling
1864
``P.division_points(n)`` for the same `n` and different
1865
points `P` (on the same curve), we do not have to recompute
1866
the polynomials.
1867
1868
.. warning::
1869
1870
There may of course be cancellation between the numerator
1871
and the denominator (_multiple_x_denominator()). Be
1872
careful. E.g. if a point on an elliptic curve with
1873
coefficients in ZZ reduces to a singular point modulo a
1874
prime, then there will be cancellation, otherwise not, see
1875
Chris Wuthrich' p-adic heights in families of elliptic
1876
curves'.
1877
1878
.. seealso::
1879
1880
:meth:`_multiple_x_denominator`
1881
1882
AUTHORS:
1883
1884
- David Harvey (2006-09-24)
1885
1886
EXAMPLES::
1887
1888
sage: E = EllipticCurve("37a")
1889
sage: P = E.gens()[0]
1890
sage: x = P[0]
1891
1892
::
1893
1894
sage: (35*P)[0]
1895
-804287518035141565236193151/1063198259901027900600665796
1896
sage: E._multiple_x_numerator(35, x)
1897
-804287518035141565236193151
1898
sage: E._multiple_x_denominator(35, x)
1899
1063198259901027900600665796
1900
1901
::
1902
1903
sage: (36*P)[0]
1904
54202648602164057575419038802/15402543997324146892198790401
1905
sage: E._multiple_x_numerator(36, x)
1906
54202648602164057575419038802
1907
sage: E._multiple_x_denominator(36, x)
1908
15402543997324146892198790401
1909
1910
An example where cancellation occurs::
1911
1912
sage: E = EllipticCurve("88a1")
1913
sage: P = E([2,2]) # fixed choice of generator
1914
sage: n = E._multiple_x_numerator(11, P[0]); n
1915
442446784738847563128068650529343492278651453440
1916
sage: d = E._multiple_x_denominator(11, P[0]); d
1917
1427247692705959881058285969449495136382746624
1918
sage: n/d
1919
310
1920
sage: 11*P
1921
(310 : -5458 : 1)
1922
"""
1923
try:
1924
return self._mul_x_num_cache[n]
1925
except AttributeError:
1926
self._mul_x_num_cache = {}
1927
except KeyError:
1928
pass
1929
1930
if cache is None:
1931
cache = {}
1932
1933
if x is None:
1934
x = rings.PolynomialRing(self.base_ring(), 'x').gen()
1935
1936
n = int(n)
1937
if n < 2:
1938
print "n must be at least 2"
1939
1940
self.division_polynomial_0( -2, x, cache)
1941
self.division_polynomial_0(n-1, x, cache)
1942
self.division_polynomial_0(n , x, cache)
1943
self.division_polynomial_0(n+1, x, cache)
1944
1945
if n % 2 == 0:
1946
self._mul_x_num_cache[n] = x * cache[-1] * cache[n]**2 - cache[n-1] * cache[n+1]
1947
else:
1948
self._mul_x_num_cache[n] = x * cache[n]**2 - cache[-1] * cache[n-1] * cache[n+1]
1949
return self._mul_x_num_cache[n]
1950
1951
1952
def _multiple_x_denominator(self, n, x=None, cache=None):
1953
r"""
1954
Returns the denominator of the x-coordinate of the nth multiple of
1955
a point, using torsion polynomials (division polynomials).
1956
1957
INPUT:
1958
1959
- ``n``, ``x``, ``cache`` -- as described in ``division_polynomial_0()``.
1960
1961
The result is cached. This is so that calling
1962
P.division_points(n) for the same n and different points P
1963
(on the same curve) does not have to recompute the
1964
polynomials.
1965
1966
.. seealso::
1967
1968
:meth:`multiple_x_numerator`
1969
1970
TODO: the numerator and denominator versions share a calculation,
1971
namely squaring `\psi_n`. Maybe would be good to offer a
1972
combined version to make this more efficient.
1973
1974
EXAMPLES::
1975
1976
sage: E = EllipticCurve("43a")
1977
sage: P = E.gens()[0]
1978
sage: x = P[0]
1979
sage: (31*P)[0]
1980
-33058398375463796474831580/154693637754223970056975321
1981
sage: E._multiple_x_numerator(31, x)
1982
-33058398375463796474831580
1983
sage: E._multiple_x_denominator(31, x)
1984
154693637754223970056975321
1985
1986
AUTHORS:
1987
1988
- David Harvey (2006-09-24)
1989
"""
1990
try:
1991
return self._mul_x_den_cache[n]
1992
except AttributeError:
1993
self._mul_x_den_cache = {}
1994
except KeyError:
1995
pass
1996
1997
if cache is None:
1998
cache = {}
1999
2000
if x is None:
2001
x = rings.PolynomialRing(self.base_ring(), 'x').gen()
2002
2003
n = int(n)
2004
if n < 2:
2005
print "n must be at least 2"
2006
2007
self.division_polynomial_0(-2, x, cache)
2008
self.division_polynomial_0(n , x, cache)
2009
2010
if n % 2 == 0:
2011
self._mul_x_den_cache[n] = cache[-1] * cache[n]**2
2012
else:
2013
self._mul_x_den_cache[n] = cache[n]**2
2014
return self._mul_x_den_cache[n]
2015
2016
2017
def multiplication_by_m(self, m, x_only=False):
2018
r"""
2019
Return the multiplication-by-`m` map from self to self as a pair of
2020
rational functions in two variables `x`,`y`.
2021
2022
INPUT:
2023
2024
- ``m`` - a nonzero integer
2025
2026
- ``x_only`` - bool (default: False) if True, return
2027
only the `x`-coordinate of the map.
2028
2029
2030
OUTPUT:
2031
2032
(2-tuple) `(f(x), g(x,y))`, where `f` and `g` are rational
2033
functions with the degree of `y` in `g(x,y)` exactly 1.
2034
2035
2036
.. note:
2037
2038
The result is not cached.
2039
2040
``m`` is allowed to be negative (but not 0).
2041
2042
EXAMPLES::
2043
2044
sage: E = EllipticCurve([-1,3])
2045
2046
We verify that multiplication by 1 is just the identity::
2047
2048
sage: E.multiplication_by_m(1)
2049
(x, y)
2050
2051
Multiplication by 2 is more complicated::
2052
2053
sage: f = E.multiplication_by_m(2)
2054
sage: f
2055
((x^4 + 2*x^2 - 24*x + 1)/(4*x^3 - 4*x + 12), (8*x^6*y - 40*x^4*y + 480*x^3*y - 40*x^2*y + 96*x*y - 568*y)/(64*x^6 - 128*x^4 + 384*x^3 + 64*x^2 - 384*x + 576))
2056
2057
Grab only the x-coordinate (less work)::
2058
2059
sage: E.multiplication_by_m(2, x_only=True)
2060
(x^4 + 2*x^2 - 24*x + 1)/(4*x^3 - 4*x + 12)
2061
2062
We check that it works on a point::
2063
2064
sage: P = E([2,3])
2065
sage: eval = lambda f,P: [fi(P[0],P[1]) for fi in f]
2066
sage: assert E(eval(f,P)) == 2*P
2067
2068
We do the same but with multiplication by 3::
2069
2070
sage: f = E.multiplication_by_m(3)
2071
sage: assert E(eval(f,P)) == 3*P
2072
2073
And the same with multiplication by 4::
2074
2075
sage: f = E.multiplication_by_m(4)
2076
sage: assert E(eval(f,P)) == 4*P
2077
2078
And the same with multiplication by -1,-2,-3,-4::
2079
2080
sage: for m in [-1,-2,-3,-4]:
2081
... f = E.multiplication_by_m(m)
2082
... assert E(eval(f,P)) == m*P
2083
2084
TESTS:
2085
2086
Verify for this fairly random looking curve and point that
2087
multiplication by m returns the right result for the first 10
2088
integers::
2089
2090
sage: E = EllipticCurve([23,-105])
2091
sage: P = E([129/4, 1479/8])
2092
sage: for n in [1..10]:
2093
... f = E.multiplication_by_m(n)
2094
... Q = n*P
2095
... assert Q == E(eval(f,P))
2096
... f = E.multiplication_by_m(-n)
2097
... Q = -n*P
2098
... assert Q == E(eval(f,P))
2099
2100
The following test shows that \#4364 is indeed fixed::
2101
2102
sage: p = next_prime(2^30-41)
2103
sage: a = GF(p)(1)
2104
sage: b = GF(p)(1)
2105
sage: E = EllipticCurve([a, b])
2106
sage: P = E.random_point()
2107
sage: my_eval = lambda f,P: [fi(P[0],P[1]) for fi in f]
2108
sage: f = E.multiplication_by_m(2)
2109
sage: assert(E(eval(f,P)) == 2*P)
2110
"""
2111
# Coerce the input m to be an integer
2112
m = rings.Integer(m)
2113
2114
if m==0:
2115
raise ValueError, "m must be a non-zero integer"
2116
2117
R = PolynomialRing(self.base_ring(), 2, 'x,y')
2118
2119
# Kxy is the function field, containing the full division polynomial.
2120
Kxy = R.fraction_field()
2121
x,y = Kxy.gens()
2122
2123
# Special case of multiplication by 1 is easy.
2124
if m == 1:
2125
return (x, y)
2126
2127
# Grab curve invariants
2128
a1,a2,a3,a4,a6 = self.a_invariants()
2129
2130
if m == -1:
2131
return (x, -y-a1*x-a3)
2132
2133
# the x-coordinate does not depend on the sign of m. The work
2134
# here is done by functions defined earlier:
2135
2136
mx = self._multiple_x_numerator(m.abs(),x) / self._multiple_x_denominator(m.abs(),x)
2137
2138
if x_only:
2139
# Return it if the optional parameter x_only is set.
2140
return mx
2141
2142
# Consideration of the invariant differential
2143
# w=dx/(2*y+a1*x+a3) shows that m*w = d(mx)/(2*my+a1*mx+a3)
2144
# and hence 2*my+a1*mx+a3 = (1/m)*(2*y+a1*x+a3)*d(mx)/dx
2145
2146
my = ((2*y+a1*x+a3)*mx.derivative(x)/m - a1*mx-a3)/2
2147
2148
return mx, my
2149
2150
def multiplication_by_m_isogeny(self, m):
2151
r"""
2152
Return the ``EllipticCurveIsogeny`` object associated to the
2153
multiplication-by-`m` map on self. The resulting isogeny will
2154
have the associated rational maps (i.e. those returned by
2155
`self.multiplication_by_m()`) already computed.
2156
2157
NOTE: This function is currently *much* slower than the
2158
result of ``self.multiplication_by_m()``, because
2159
constructing an isogeny precomputes a significant amount
2160
of information. See trac tickets #7368 and #8014 for the
2161
status of improving this situation.
2162
2163
INPUT:
2164
2165
- ``m`` - a nonzero integer
2166
2167
OUTPUT:
2168
2169
- An ``EllipticCurveIsogeny`` object associated to the
2170
multiplication-by-`m` map on self.
2171
2172
EXAMPLES::
2173
2174
sage: E = EllipticCurve('11a1')
2175
sage: E.multiplication_by_m_isogeny(7)
2176
Isogeny of degree 49 from Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
2177
2178
"""
2179
mx, my = self.multiplication_by_m(m)
2180
2181
torsion_poly = self.torsion_polynomial(m).monic()
2182
phi = self.isogeny(torsion_poly, codomain=self)
2183
phi._EllipticCurveIsogeny__initialize_rational_maps(precomputed_maps=(mx, my))
2184
2185
return phi
2186
2187
def isomorphism_to(self, other):
2188
"""
2189
Given another weierstrass model ``other`` of self, return an
2190
isomorphism from self to ``other``.
2191
2192
INPUT:
2193
2194
- ``other`` -- an elliptic curve isomorphic to ``self``.
2195
2196
OUTPUT:
2197
2198
(Weierstrassmorphism) An isomorphism from self to other.
2199
2200
.. note::
2201
2202
If the curves in question are not isomorphic, a ValueError is raised.
2203
2204
EXAMPLES::
2205
2206
sage: E = EllipticCurve('37a')
2207
sage: F = E.short_weierstrass_model()
2208
sage: w = E.isomorphism_to(F); w
2209
Generic morphism:
2210
From: Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
2211
To: Abelian group of points on Elliptic Curve defined by y^2 = x^3 - 16*x + 16 over Rational Field
2212
Via: (u,r,s,t) = (1/2, 0, 0, -1/2)
2213
sage: P = E(0,-1,1)
2214
sage: w(P)
2215
(0 : -4 : 1)
2216
sage: w(5*P)
2217
(1 : 1 : 1)
2218
sage: 5*w(P)
2219
(1 : 1 : 1)
2220
sage: 120*w(P) == w(120*P)
2221
True
2222
2223
We can also handle injections to different base rings::
2224
2225
sage: K.<a> = NumberField(x^3-7)
2226
sage: E.isomorphism_to(E.change_ring(K))
2227
Generic morphism:
2228
From: Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
2229
To: Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 + (-1)*x over Number Field in a with defining polynomial x^3 - 7
2230
Via: (u,r,s,t) = (1, 0, 0, 0)
2231
"""
2232
return wm.WeierstrassIsomorphism(self, None, other)
2233
2234
def automorphisms(self, field=None):
2235
"""
2236
Return the set of isomorphisms from self to itself (as a list).
2237
2238
INPUT:
2239
2240
- ``field`` (default None) -- a field into which the
2241
coefficients of the curve may be coerced (by default, uses
2242
the base field of the curve).
2243
2244
OUTPUT:
2245
2246
(list) A list of ``WeierstrassIsomorphism`` objects
2247
consisting of all the isomorphisms from the curve ``self`` to
2248
itself defined over ``field``.
2249
2250
EXAMPLES::
2251
2252
sage: E = EllipticCurve_from_j(QQ(0)) # a curve with j=0 over QQ
2253
sage: E.automorphisms();
2254
[Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Rational Field
2255
Via: (u,r,s,t) = (-1, 0, 0, -1), Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Rational Field
2256
Via: (u,r,s,t) = (1, 0, 0, 0)]
2257
2258
We can also find automorphisms defined over extension fields::
2259
2260
sage: K.<a> = NumberField(x^2+3) # adjoin roots of unity
2261
sage: E.automorphisms(K)
2262
[Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^2 + 3
2263
Via: (u,r,s,t) = (1, 0, 0, 0),
2264
...
2265
Generic endomorphism of Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^2 + 3
2266
Via: (u,r,s,t) = (-1/2*a - 1/2, 0, 0, 0)]
2267
2268
::
2269
2270
sage: [ len(EllipticCurve_from_j(GF(q,'a')(0)).automorphisms()) for q in [2,4,3,9,5,25,7,49]]
2271
[2, 24, 2, 12, 2, 6, 6, 6]
2272
"""
2273
if field==None:
2274
return [wm.WeierstrassIsomorphism(self, urst, self)
2275
for urst in wm.isomorphisms(self,self)]
2276
E=self.change_ring(field)
2277
return [wm.WeierstrassIsomorphism(E, urst, E)
2278
for urst in wm.isomorphisms(E,E)]
2279
2280
def isomorphisms(self, other, field=None):
2281
"""
2282
Return the set of isomorphisms from self to other (as a list).
2283
2284
INPUT:
2285
2286
- ``other`` -- another elliptic curve.
2287
2288
- ``field`` (default None) -- a field into which the
2289
coefficients of the curves may be coerced (by default, uses
2290
the base field of the curves).
2291
2292
OUTPUT:
2293
2294
(list) A list of ``WeierstrassIsomorphism`` objects consisting of all
2295
the isomorphisms from the curve ``self`` to the curve
2296
``other`` defined over ``field``.
2297
2298
EXAMPLES::
2299
2300
sage: E = EllipticCurve_from_j(QQ(0)) # a curve with j=0 over QQ
2301
sage: F = EllipticCurve('27a3') # should be the same one
2302
sage: E.isomorphisms(F);
2303
[Generic morphism:
2304
From: Abelian group of points on Elliptic Curve defined
2305
by y^2 + y = x^3 over Rational Field
2306
To: Abelian group of points on Elliptic Curve defined
2307
by y^2 + y = x^3 over Rational Field
2308
Via: (u,r,s,t) = (-1, 0, 0, -1), Generic morphism:
2309
From: Abelian group of points on Elliptic Curve defined
2310
by y^2 + y = x^3 over Rational Field
2311
To: Abelian group of points on Elliptic Curve defined
2312
by y^2 + y = x^3 over Rational Field
2313
Via: (u,r,s,t) = (1, 0, 0, 0)]
2314
2315
2316
We can also find isomorphisms defined over extension fields::
2317
2318
sage: E=EllipticCurve(GF(7),[0,0,0,1,1])
2319
sage: F=EllipticCurve(GF(7),[0,0,0,1,-1])
2320
sage: E.isomorphisms(F)
2321
[]
2322
sage: E.isomorphisms(F,GF(49,'a'))
2323
[Generic morphism:
2324
From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in a of size 7^2
2325
To: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x + 6 over Finite Field in a of size 7^2
2326
Via: (u,r,s,t) = (a + 3, 0, 0, 0), Generic morphism:
2327
From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in a of size 7^2
2328
To: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x + 6 over Finite Field in a of size 7^2
2329
Via: (u,r,s,t) = (6*a + 4, 0, 0, 0)]
2330
"""
2331
if field==None:
2332
return [wm.WeierstrassIsomorphism(self, urst, other)
2333
for urst in wm.isomorphisms(self,other)]
2334
E=self.change_ring(field)
2335
F=other.change_ring(field)
2336
return [wm.WeierstrassIsomorphism(E, urst, F)
2337
for urst in wm.isomorphisms(E,F)]
2338
2339
def is_isomorphic(self, other, field=None):
2340
"""
2341
Returns whether or not self is isomorphic to other.
2342
2343
INPUT:
2344
2345
- ``other`` -- another elliptic curve.
2346
2347
- ``field`` (default None) -- a field into which the
2348
coefficients of the curves may be coerced (by default, uses
2349
the base field of the curves).
2350
2351
OUTPUT:
2352
2353
(bool) True if there is an isomorphism from curve ``self`` to
2354
curve ``other`` defined over ``field``.
2355
2356
EXAMPLES::
2357
2358
sage: E = EllipticCurve('389a')
2359
sage: F = E.change_weierstrass_model([2,3,4,5]); F
2360
Elliptic Curve defined by y^2 + 4*x*y + 11/8*y = x^3 - 3/2*x^2 - 13/16*x over Rational Field
2361
sage: E.is_isomorphic(F)
2362
True
2363
sage: E.is_isomorphic(F.change_ring(CC))
2364
False
2365
"""
2366
if not is_EllipticCurve(other):
2367
return False
2368
if field==None:
2369
if self.base_ring() != other.base_ring():
2370
return False
2371
elif self.j_invariant() != other.j_invariant(): # easy check
2372
return False
2373
else:
2374
return wm.isomorphisms(self,other,True) != None
2375
else:
2376
E=self.base_extend(field)
2377
F=other.base_extend(field)
2378
if E.j_invariant() != F.j_invariant(): # easy check
2379
return False
2380
else:
2381
return wm.isomorphisms(E,other,F) != None
2382
2383
def change_weierstrass_model(self, *urst):
2384
r"""
2385
Return a new Weierstrass model of self under the standard transformation `(u,r,s,t)`
2386
2387
.. math::
2388
2389
(x,y) \mapsto (x',y') = (u^2x + r , u^3y + su^2x + t).
2390
2391
2392
EXAMPLES::
2393
2394
sage: E = EllipticCurve('15a')
2395
sage: F1 = E.change_weierstrass_model([1/2,0,0,0]); F1
2396
Elliptic Curve defined by y^2 + 2*x*y + 8*y = x^3 + 4*x^2 - 160*x - 640 over Rational Field
2397
sage: F2 = E.change_weierstrass_model([7,2,1/3,5]); F2
2398
Elliptic Curve defined by y^2 + 5/21*x*y + 13/343*y = x^3 + 59/441*x^2 - 10/7203*x - 58/117649 over Rational Field
2399
sage: F1.is_isomorphic(F2)
2400
True
2401
"""
2402
if isinstance(urst[0], (tuple, list)):
2403
urst = urst[0]
2404
return constructor.EllipticCurve((wm.baseWI(*urst))(self.ainvs()))
2405
2406
def short_weierstrass_model(self, complete_cube=True):
2407
"""
2408
Returns a short Weierstrass model for self.
2409
2410
INPUT:
2411
2412
- ``complete_cube`` - bool (default: True); for
2413
meaning, see below.
2414
2415
OUTPUT:
2416
2417
An elliptic curve.
2418
2419
If ``complete_cube=True``: Return a model of the form
2420
`y^2 = x^3 + a*x + b` for this curve. The characteristic
2421
must not be 2; in characteristic 3, it is only possible if `b_2=0`.
2422
2423
If ``complete_cube=False``: Return a model of the form
2424
`y^2 = x^3 + ax^2 + bx + c` for this curve. The
2425
characteristic must not be 2.
2426
2427
EXAMPLES::
2428
2429
sage: E = EllipticCurve([1,2,3,4,5])
2430
sage: print E
2431
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
2432
sage: F = E.short_weierstrass_model()
2433
sage: print F
2434
Elliptic Curve defined by y^2 = x^3 + 4941*x + 185166 over Rational Field
2435
sage: E.is_isomorphic(F)
2436
True
2437
sage: F = E.short_weierstrass_model(complete_cube=False)
2438
sage: print F
2439
Elliptic Curve defined by y^2 = x^3 + 9*x^2 + 88*x + 464 over Rational Field
2440
sage: print E.is_isomorphic(F)
2441
True
2442
2443
::
2444
2445
sage: E = EllipticCurve(GF(3),[1,2,3,4,5])
2446
sage: E.short_weierstrass_model(complete_cube=False)
2447
Elliptic Curve defined by y^2 = x^3 + x + 2 over Finite Field of size 3
2448
2449
This used to be different see trac #3973::
2450
2451
sage: E.short_weierstrass_model()
2452
Elliptic Curve defined by y^2 = x^3 + x + 2 over Finite Field of size 3
2453
2454
More tests in characteristic 3::
2455
2456
sage: E = EllipticCurve(GF(3),[0,2,1,2,1])
2457
sage: E.short_weierstrass_model()
2458
Traceback (most recent call last):
2459
...
2460
ValueError: short_weierstrass_model(): no short model for Elliptic Curve defined by y^2 + y = x^3 + 2*x^2 + 2*x + 1 over Finite Field of size 3 (characteristic is 3)
2461
sage: E.short_weierstrass_model(complete_cube=False)
2462
Elliptic Curve defined by y^2 = x^3 + 2*x^2 + 2*x + 2 over Finite Field of size 3
2463
sage: E.short_weierstrass_model(complete_cube=False).is_isomorphic(E)
2464
True
2465
"""
2466
import constructor
2467
K = self.base_ring()
2468
2469
# any curve of the form y^2 = x^3 +.. is singular in characteristic 2
2470
if K.characteristic() == 2:
2471
raise ValueError, "short_weierstrass_model(): no short model for %s (characteristic is %s)"%(self,K.characteristic())
2472
2473
# in characteristic 3 we can complete the square but we can only complete the cube if b2 is 0
2474
if K.characteristic() == 3:
2475
b2,b4,b6,_ = self.b_invariants()
2476
if complete_cube and b2 != 0:
2477
raise ValueError, "short_weierstrass_model(): no short model for %s (characteristic is %s)"%(self,K.characteristic())
2478
else:
2479
return constructor.EllipticCurve([0,b2,0,8*b4,16*b6])
2480
2481
a1,a2,a3,_,_ = self.a_invariants()
2482
if complete_cube:
2483
if a1==0 and a2==0 and a3==0:
2484
return self
2485
else:
2486
b2,b4,b6,_ = self.b_invariants()
2487
if b2==0:
2488
return constructor.EllipticCurve([0,0,0,8*b4,16*b6])
2489
else:
2490
c4, c6 = self.c_invariants()
2491
return constructor.EllipticCurve([0,0,0,-27*c4, -54*c6])
2492
else:
2493
if a1==0 and a3==0:
2494
return self
2495
else:
2496
b2,b4,b6,_ = self.b_invariants()
2497
return constructor.EllipticCurve([0,b2,0,8*b4,16*b6])
2498
2499
2500
2501
# Plotting
2502
2503
2504
def plot(self, xmin=None, xmax=None, components='both', **args):
2505
"""
2506
Draw a graph of this elliptic curve.
2507
2508
INPUT:
2509
2510
- ``xmin, xmax`` - (optional) points will be computed at
2511
least within this range, but possibly farther.
2512
2513
- ``components`` - a string, one of the following:
2514
2515
- ``both`` -- (default), scale so that both bounded and
2516
unbounded components appear
2517
2518
- ``bounded`` -- scale the plot to show the bounded
2519
component. Raises an error if there is only one real
2520
component.
2521
2522
- ``unbounded`` -- scale the plot to show the unbounded
2523
component, including the two flex points.
2524
2525
- ``plot_points`` -- passed to
2526
:func:`sage.plot.generate_plot_points`
2527
2528
- ``adaptive_tolerance`` -- passed to
2529
:func:`sage.plot.generate_plot_points`
2530
2531
- ``adaptive_recursion`` -- passed to
2532
:func:`sage.plot.generate_plot_points`
2533
2534
- ``randomize`` -- passed to
2535
:func:`sage.plot.generate_plot_points`
2536
2537
- ``**args`` - all other options are passed to
2538
:class:`sage.plot.line.Line`
2539
2540
EXAMPLES::
2541
2542
sage: E = EllipticCurve([0,-1])
2543
sage: plot(E, rgbcolor=hue(0.7))
2544
sage: E = EllipticCurve('37a')
2545
sage: plot(E)
2546
sage: plot(E, xmin=25,xmax=26)
2547
2548
With #12766 we added the components keyword::
2549
2550
sage: E.real_components()
2551
2
2552
sage: E.plot(components='bounded')
2553
sage: E.plot(components='unbounded')
2554
2555
If there is only one component then specifying
2556
components='bounded' raises a ValueError::
2557
2558
sage: E = EllipticCurve('9990be2')
2559
sage: E.plot(components='bounded')
2560
Traceback (most recent call last):
2561
...
2562
ValueError: no bounded component for this curve
2563
"""
2564
RR = rings.RealField()
2565
K = self.base_ring()
2566
try:
2567
RR._coerce_(K(1))
2568
except TypeError:
2569
raise NotImplementedError, "Plotting of curves over %s not implemented yet"%K
2570
if components not in ['both', 'bounded', 'unbounded']:
2571
raise ValueError("component must be one of 'both', 'bounded' or 'unbounded'")
2572
2573
a1, a2, a3, a4, a6 = self.ainvs()
2574
d = self.division_polynomial(2)
2575
# Internal function for plotting first branch of the curve
2576
f1 = lambda z: (-(a1*z + a3) + sqrt(abs(d(z))))/2
2577
# Internal function for plotting second branch of the curve
2578
f2 = lambda z: (-(a1*z + a3) - sqrt(abs(d(z))))/2
2579
r = d.roots(RR, multiplicities=False)
2580
r.sort()
2581
if components == 'bounded' and len(r) == 1:
2582
raise ValueError("no bounded component for this curve")
2583
if isinstance(xmin, (tuple, list)):
2584
if xmax is not None:
2585
raise ValueError("xmax must be None if xmin is a tuple")
2586
if len(xmin) != 2:
2587
raise ValueError("if xmin is a tuple it must have length 2")
2588
xmin, xmax = xmin
2589
if xmin is None or xmax is None:
2590
xmins = []
2591
xmaxs = []
2592
if components in ['both','bounded'] and len(r) > 1:
2593
xmins.append(r[0])
2594
xmaxs.append(r[1])
2595
2596
# The following 3 is an aesthetic choice. It's possible
2597
# that we should compute both of the following when
2598
# components=='both' and len(r) > 1 and take the maximum
2599
# generated xmax.
2600
if components == 'unbounded' or components == 'both' and (len(r) == 1 or r[2] - r[1] > 3*(r[1] - r[0])):
2601
flex = self.division_polynomial(3).roots(RR, multiplicities=False)
2602
flex.sort()
2603
flex = flex[-1]
2604
xmins.append(r[-1])
2605
# The doubling here is an aesthetic choice
2606
xmaxs.append(flex + 2*(flex - r[-1]))
2607
elif components == 'both':
2608
# First the easy part.
2609
xmins.append(r[-1])
2610
# There are two components and the unbounded component
2611
# is not too far from the bounded one. We scale so
2612
# that the unbounded component is twice as tall as the
2613
# bounded component. The y values corresponding to
2614
# horizontal tangent lines are determined as follows.
2615
# We implicitly differentiate the equation for this
2616
# curve and get
2617
# 2 yy' + a1 y + a1 xy' + a3 y' = 3 x^2 + 2a2 x + a4
2618
2619
R = RR['x']
2620
x = R.gen()
2621
if a1 == 0:
2622
# a horizontal tangent line can only occur at a root of
2623
Ederiv = 3*x**2 + 2*a2*x + a4
2624
else:
2625
# y' = 0 ==> y = (3*x^2 + 2*a2*x + a4) / a1
2626
y = (3*x**2 + 2*a2*x + a4) / a1
2627
Ederiv = y**2 + a1*x*y + a3*y - (x**3 + a2*x**2 + a4*x + a6)
2628
critx = [a for a in Ederiv.roots(RR, multiplicities=False) if r[0] < a < r[1]]
2629
if len(critx) == 0:
2630
raise RuntimeError("No horizontal tangent lines on bounded component")
2631
# The 2.5 here is an aesthetic choice
2632
ymax = 2.5 * max([f1(a) for a in critx])
2633
ymin = 2.5 * min([f2(a) for a in critx])
2634
top_branch = ymax**2 + a1*x*ymax + a3*ymax - (x**3 + a2*x**2 + a4*x + a6)
2635
bottom_branch = ymin**2 + a1*x*ymin + a3*ymin - (x**3 + a2*x**2 + a4*x + a6)
2636
xmaxs.append(max(top_branch.roots(RR,multiplicities=False) + bottom_branch.roots(RR,multiplicities=False)))
2637
xmins = min(xmins)
2638
xmaxs = max(xmaxs)
2639
span = xmaxs - xmins
2640
if xmin is None:
2641
xmin = xmins - .02*span
2642
if xmax is None:
2643
xmax = xmaxs + .02*span
2644
elif xmin >= xmax:
2645
raise ValueError("xmin must be less than xmax")
2646
2647
I = []
2648
if components in ['unbounded', 'both'] and xmax > r[-1]:
2649
# one real root; 1 component
2650
if xmin <= r[-1]:
2651
I.append((r[-1],xmax,'<'))
2652
else:
2653
I.append((xmin, xmax,'='))
2654
if components in ['bounded','both'] and len(r) > 1 and (xmin < r[1] or xmax > r[0]):
2655
if xmin <= r[0]:
2656
if xmax >= r[1]:
2657
I.append((r[0],r[1],'o'))
2658
else:
2659
I.append((r[0],xmax,'<'))
2660
elif xmax >= r[1]:
2661
I.append((xmin, r[1], '>'))
2662
else:
2663
I.append((xmin, xmax, '='))
2664
2665
g = plot.Graphics()
2666
plot_points = int(args.pop('plot_points',200))
2667
adaptive_tolerance = args.pop('adaptive_tolerance',0.01)
2668
adaptive_recursion = args.pop('adaptive_recursion',5)
2669
randomize = args.pop('randomize',True)
2670
for j in range(len(I)):
2671
a,b,shape = I[j]
2672
v = generate_plot_points(f1, (a, b), plot_points, adaptive_tolerance, adaptive_recursion, randomize)
2673
w = generate_plot_points(f2, (a, b), plot_points, adaptive_tolerance, adaptive_recursion, randomize)
2674
if shape == 'o':
2675
g += plot.line(v + list(reversed(w)) + [v[0]], **args)
2676
elif shape == '<':
2677
g += plot.line(list(reversed(v)) + w, **args)
2678
elif shape == '>':
2679
g += plot.line(v + list(reversed(w)), **args)
2680
else:
2681
g += plot.line(v, **args)
2682
g += plot.line(w, **args)
2683
return g
2684
2685
def formal_group(self):
2686
r"""
2687
The formal group associated to this elliptic curve.
2688
2689
EXAMPLES::
2690
2691
sage: E = EllipticCurve("37a")
2692
sage: E.formal_group()
2693
Formal Group associated to the Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
2694
"""
2695
try:
2696
return self.__formal_group
2697
except AttributeError:
2698
self.__formal_group = formal_group.EllipticCurveFormalGroup(self)
2699
return self.__formal_group
2700
2701
formal = formal_group
2702
2703
def _p_primary_torsion_basis(self,p,m=None):
2704
r"""
2705
Find a basis for the `p`-primary part of the torsion
2706
subgroup of this elliptic curve.
2707
2708
INPUT:
2709
2710
- ``p`` (integer) -- a prime number.
2711
2712
- ``m`` (integer or None) -- if not None, the $p$-primary torsion will be assumed to have order at most $p^m$.
2713
2714
OUTPUT:
2715
2716
A list of 0, 1 or 2 pairs `[T,k]` where `T` is a generator of
2717
order `p^k`. That is, either `[]` or `[[T_1,k_1]]` or
2718
`[[T_1,k_1],[T_2,k_2]]` with `[]`, `[T_1]`, or `[T_1,T_2]` a
2719
basis and `p^{k_1} \ge p^{k_2} \ge 1` their orders.
2720
2721
.. warning::
2722
2723
1. Do not call this on a curve whose group is
2724
`p`-divisible (i.e., whose `p`-primary part
2725
is infinite)!
2726
2727
2. The code uses division polynomials and will be slow for
2728
large `p`.
2729
2730
EXAMPLES::
2731
2732
sage: E = EllipticCurve('11a1')
2733
sage: E._p_primary_torsion_basis(5)
2734
[[(5 : -6 : 1), 1]]
2735
sage: K.<t> = NumberField(x^4 + x^3 + 11*x^2 + 41*x + 101)
2736
sage: EK = E.base_extend(K)
2737
sage: EK._p_primary_torsion_basis(5) # long time (2s on sage.math, 2011)
2738
[[(16 : 60 : 1), 1], [(t : 1/11*t^3 + 6/11*t^2 + 19/11*t + 48/11 : 1), 1]]
2739
sage: EF = E.change_ring(GF(101))
2740
sage: EF._p_primary_torsion_basis(5)
2741
[[(0 : 13 : 1), 1], [(5 : 5 : 1), 1]]
2742
2743
sage: F.<z> = CyclotomicField(21)
2744
sage: E = EllipticCurve([2,-z^7,-z^7,0,0])
2745
sage: E._p_primary_torsion_basis(7,2) # long time (8s on sage.math, 2011)
2746
[[(0 : z^7 : 1), 1],
2747
[(z^7 - z^6 + z^4 - z^3 + z^2 - 1 : z^8 - 2*z^7 + z^6 + 2*z^5 - 3*z^4 + 2*z^3 - 2*z + 2 : 1), 1]]
2748
2749
TESTS:
2750
2751
This shows that the bug at trac #4937 is fixed::
2752
2753
sage: a=804515977734860566494239770982282063895480484302363715494873
2754
sage: b=584772221603632866665682322899297141793188252000674256662071
2755
sage: E = EllipticCurve(GF(10^60+3201),[0,a,0,b,0])
2756
sage: [t[1] for t in E._p_primary_torsion_basis(2)] # long time (3s on sage.math, 2011)
2757
[16, 1]
2758
"""
2759
p = rings.Integer(p)
2760
if not p.is_prime():
2761
raise ValueError, "p (=%s) should be prime"%p
2762
2763
if m is None:
2764
from sage.rings.infinity import Infinity
2765
m = Infinity
2766
2767
if m == 0:
2768
return []
2769
2770
# First find the p-torsion:
2771
Ep = self(0).division_points(p)
2772
p_rank = rings.Integer(len(Ep)).exact_log(p)
2773
assert p_rank in [0,1,2]
2774
2775
if p_rank == 0:
2776
return []
2777
2778
assert p_rank in [1,2]
2779
2780
if p_rank == 1:
2781
P = Ep[0]
2782
if P.is_zero(): P=Ep[1]
2783
k = 1
2784
if m==1:
2785
return [[P,k]]
2786
pts = P.division_points(p) # length 0 or p
2787
while len(pts)>0:
2788
k += 1
2789
P = pts[0]
2790
if m<=k:
2791
return [[P,k]]
2792
pts = P.division_points(p)
2793
# now P generates the p-power-torsion and has order p^k
2794
return [[P,k]]
2795
2796
assert p_rank == 2
2797
2798
Epi = iter(Ep) # used to iterate through Ep
2799
# Find P1,P2 which generate the p-torsion:
2800
P1 = Epi.next()
2801
while P1.is_zero(): P1 = Epi.next()
2802
P2 = Epi.next()
2803
while generic.linear_relation(P1,P2,'+')[0] != 0: P2 = Epi.next()
2804
2805
k = 1
2806
log_order = 2
2807
if m<=log_order:
2808
return [[P1,1],[P2,1]]
2809
2810
pts1 = P1.division_points(p)
2811
pts2 = P2.division_points(p)
2812
while len(pts1)>0 and len(pts2)>0:
2813
k += 1
2814
P1 = pts1[0]
2815
P2 = pts2[0]
2816
log_order += 2
2817
if m<=log_order:
2818
return [[P1,k],[P2,k]]
2819
pts1 = P1.division_points(p)
2820
pts2 = P2.division_points(p)
2821
2822
# Now P1,P2 are a basis for the p^k torsion, which is
2823
# isomorphic to (Z/p^k)^2, and k is the maximal integer for
2824
# which this is the case.
2825
2826
# We now determine whether a combination (P2 or P1+a*P2 for
2827
# some a) can be further divided for some a mod p; if so,
2828
# replace P1 by that combination, set pts to be the list of
2829
# solutions Q to p*Q=P1. If no combination can be divided,
2830
# then the structure is (p^k,p^k) and we can stop.
2831
2832
if len(pts1) > 0:
2833
pts = pts1
2834
elif len(pts2) > 0:
2835
P1, P2 = P2, P1
2836
pts = pts2
2837
else:
2838
for Q in generic.multiples(P2,p-1,P1+P2,operation='+'):
2839
# Q runs through P1+a*P2 for a=1,2,...,p-1
2840
pts = Q.division_points(p)
2841
if len(pts) > 0:
2842
P1 = Q
2843
break
2844
2845
if len(pts)==0:
2846
return [[P1,k],[P2,k]]
2847
2848
# Now the structure is (p^n,p^k) for some n>k. We need to
2849
# replace P1 by an element of maximal order p^n. So far we
2850
# have pts = list of Q satisfying p*Q=P1, and all such Q have
2851
# order p^{k+1}.
2852
2853
# We keep trying to divide P1 by p. At each step, if we
2854
# succeed, replace P1 by any of the results and increment n.
2855
# If we fails try again with P1+a*P2 for a in [1..p-1]. If any
2856
# succeed, replace P1 by one of the resulting divided points.
2857
# If all fail, the structure is (p^n,p^k) and P1,P2 are
2858
# generators.
2859
2860
n=k
2861
while True:
2862
P1=pts[0]
2863
n += 1
2864
log_order += 1
2865
if m<=log_order:
2866
return [[P1,n],[P2,k]]
2867
pts = P1.division_points(p)
2868
if len(pts)==0:
2869
for Q in generic.multiples(P2,p-1,P1+P2,operation='+'):
2870
# Q runs through P1+a*P2 for a=1,2,...,p-1
2871
pts = Q.division_points(p)
2872
if len(pts)>0:
2873
break
2874
if len(pts)==0:
2875
return [[P1,n],[P2,k]]
2876
2877
2878
def hyperelliptic_polynomials(self):
2879
r"""
2880
Returns a pair of polynomials `g(x)`, `h(x)` such that this elliptic
2881
curve can be defined by the standard hyperelliptic equation
2882
2883
.. math::
2884
2885
y^2 + h(x)y = g(x).
2886
2887
EXAMPLES::
2888
2889
sage: R.<a1,a2,a3,a4,a6>=QQ[]
2890
sage: E=EllipticCurve([a1,a2,a3,a4,a6])
2891
sage: E.hyperelliptic_polynomials()
2892
(x^3 + a2*x^2 + a4*x + a6, a1*x + a3)
2893
"""
2894
K = self.base_ring()
2895
R = PolynomialRing(K, 'x')
2896
x = R.gen(0)
2897
a1, a2, a3, a4, a6 = self.ainvs()
2898
return R([a6, a4, a2, 1]), R([a3, a1])
2899
2900
def pari_curve(self):
2901
"""
2902
Return the PARI curve corresponding to this elliptic curve.
2903
2904
The result is cached.
2905
2906
EXAMPLES::
2907
2908
sage: E = EllipticCurve([RR(0), RR(0), RR(1), RR(-1), RR(0)])
2909
sage: e = E.pari_curve()
2910
sage: type(e)
2911
<type 'sage.libs.pari.gen.gen'>
2912
sage: e.type()
2913
't_VEC'
2914
sage: e.disc()
2915
37.0000000000000
2916
2917
Over a finite field::
2918
2919
sage: EllipticCurve(GF(41),[2,5]).pari_curve()
2920
[Mod(0, 41), Mod(0, 41), Mod(0, 41), Mod(2, 41), Mod(5, 41), Mod(0, 41), Mod(4, 41), Mod(20, 41), Mod(37, 41), Mod(27, 41), Mod(26, 41), Mod(4, 41), Mod(11, 41), 0, 0, 0, 0, 0, 0]
2921
2922
Over a `p`-adic field::
2923
2924
sage: Qp = pAdicField(5, prec=3)
2925
sage: E = EllipticCurve(Qp,[3, 4])
2926
sage: E.pari_curve()
2927
[O(5^3), O(5^3), O(5^3), 3 + O(5^3), 4 + O(5^3), O(5^3), 1 + 5 + O(5^3), 1 + 3*5 + O(5^3), 1 + 3*5 + 4*5^2 + O(5^3), 1 + 5 + 4*5^2 + O(5^3), 4 + 3*5 + 5^2 + O(5^3), 2*5 + 4*5^2 + O(5^3), 3*5^-1 + O(5), [4 + 4*5 + 4*5^2 + O(5^3)], 1 + 2*5 + 4*5^2 + O(5^3), 1 + 5 + 4*5^2 + O(5^3), 2*5 + 4*5^2 + O(5^3), 3 + 3*5 + 3*5^2 + O(5^3), 0]
2928
sage: E.j_invariant()
2929
3*5^-1 + O(5)
2930
2931
The `j`-invariant must have negative `p`-adic valuation::
2932
2933
sage: E = EllipticCurve(Qp,[1, 1])
2934
sage: E.j_invariant() # the j-invariant is a p-adic integer
2935
2 + 4*5^2 + O(5^3)
2936
sage: E.pari_curve()
2937
Traceback (most recent call last):
2938
...
2939
PariError: (5)
2940
"""
2941
try:
2942
return self._pari_curve
2943
except AttributeError:
2944
pass
2945
2946
from sage.libs.pari.all import pari
2947
self._pari_curve = pari(list(self.a_invariants())).ellinit()
2948
return self._pari_curve
2949
2950
# This method is defined so that pari(E) returns exactly the same
2951
# as E.pari_curve(). This works even for classes that inherit from
2952
# EllipticCurve_generic, such as EllipticCurve_rational_field.
2953
def _pari_(self):
2954
"""
2955
Return the PARI curve corresponding to this elliptic curve
2956
with the default precision of 64 bits.
2957
2958
EXAMPLES::
2959
2960
sage: E = EllipticCurve('11a1')
2961
sage: pari(E)
2962
[0, -1, 1, -10, -20, -4, -20, -79, -21, 496, 20008, -161051, -122023936/161051, [4.34630815820539, -1.67315407910270 + 1.32084892226908*I, -1.67315407910270 - 1.32084892226908*I]~, ...]
2963
sage: E.pari_curve(prec=64)
2964
[0, -1, 1, -10, -20, -4, -20, -79, -21, 496, 20008, -161051, -122023936/161051, [4.34630815820539, -1.67315407910270 + 1.32084892226908*I, -1.67315407910270 - 1.32084892226908*I]~, ...]
2965
2966
Over a finite field::
2967
2968
sage: EllipticCurve(GF(2), [0,0,1,1,1])._pari_()
2969
[Mod(0, 2), Mod(0, 2), Mod(1, 2), Mod(1, 2), Mod(1, 2), Mod(0, 2), Mod(0, 2), Mod(1, 2), Mod(1, 2), Mod(0, 2), Mod(0, 2), Mod(1, 2), Mod(0, 2), 0, 0, 0, 0, 0, 0]
2970
"""
2971
return self.pari_curve()
2972
2973