Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py
8821 views
1
"""
2
Hyperelliptic curves over a general ring
3
4
EXAMPLE::
5
6
sage: P.<x> = GF(5)[]
7
sage: f = x^5 - 3*x^4 - 2*x^3 + 6*x^2 + 3*x - 1
8
sage: C = HyperellipticCurve(f); C
9
Hyperelliptic Curve over Finite Field of size 5 defined by y^2 = x^5 + 2*x^4 + 3*x^3 + x^2 + 3*x + 4
10
11
EXAMPLE::
12
13
sage: P.<x> = QQ[]
14
sage: f = 4*x^5 - 30*x^3 + 45*x - 22
15
sage: C = HyperellipticCurve(f); C
16
Hyperelliptic Curve over Rational Field defined by y^2 = 4*x^5 - 30*x^3 + 45*x - 22
17
sage: C.genus()
18
2
19
20
sage: D = C.affine_patch(0)
21
sage: D.defining_polynomials()[0].parent()
22
Multivariate Polynomial Ring in x0, x1 over Rational Field
23
"""
24
25
#*****************************************************************************
26
# Copyright (C) 2006 David Kohel <[email protected]>
27
# Distributed under the terms of the GNU General Public License (GPL)
28
# http://www.gnu.org/licenses/
29
#*****************************************************************************
30
31
from sage.rings.all import PolynomialRing, RR, PowerSeriesRing, LaurentSeriesRing, O
32
from sage.functions.all import log
33
34
import sage.schemes.plane_curves.projective_curve as plane_curve
35
36
def is_HyperellipticCurve(C):
37
"""
38
EXAMPLES::
39
40
sage: R.<x> = QQ[]; C = HyperellipticCurve(x^3 + x - 1); C
41
Hyperelliptic Curve over Rational Field defined by y^2 = x^3 + x - 1
42
sage: sage.schemes.hyperelliptic_curves.hyperelliptic_generic.is_HyperellipticCurve(C)
43
True
44
"""
45
return isinstance(C,HyperellipticCurve_generic)
46
47
class HyperellipticCurve_generic(plane_curve.ProjectiveCurve_generic):
48
def __init__(self, PP, f, h=None, names=None, genus=None):
49
x, y, z = PP.gens()
50
df = f.degree()
51
F1 = sum([ f[i]*x**i*z**(df-i) for i in range(df+1) ])
52
if h is None:
53
F = y**2*z**(df-2) - F1
54
else:
55
dh = h.degree()
56
deg = max(df,dh+1)
57
F0 = sum([ h[i]*x**i*z**(dh-i) for i in range(dh+1) ])
58
F = y**2*z**(deg-2) + F0*y*z**(deg-dh-1) - F1*z**(deg-df)
59
plane_curve.ProjectiveCurve_generic.__init__(self,PP,F)
60
R = PP.base_ring()
61
if names == None:
62
names = ["x","y"]
63
elif isinstance(names,str):
64
names = names.split(",")
65
self._names = names
66
P1 = PolynomialRing(R,name=names[0])
67
P2 = PolynomialRing(P1,name=names[1])
68
self._PP = PP
69
self._printing_ring = P2
70
self._hyperelliptic_polynomials = (f,h)
71
self._genus = genus
72
73
def change_ring(self, R):
74
"""
75
Returns this HyperellipticCurve over a new base ring R.
76
77
EXAMPLES::
78
79
sage: R.<x> = QQ[]
80
sage: H = HyperellipticCurve(x^5 - 10*x + 9)
81
sage: K = Qp(3,5)
82
sage: L.<a> = K.extension(x^30-3)
83
sage: HK = H.change_ring(K)
84
sage: HL = HK.change_ring(L); HL
85
Hyperelliptic Curve over Eisenstein Extension of 3-adic Field with capped relative precision 5 in a defined by (1 + O(3^5))*x^30 + (O(3^6))*x^29 + (O(3^6))*x^28 + (O(3^6))*x^27 + (O(3^6))*x^26 + (O(3^6))*x^25 + (O(3^6))*x^24 + (O(3^6))*x^23 + (O(3^6))*x^22 + (O(3^6))*x^21 + (O(3^6))*x^20 + (O(3^6))*x^19 + (O(3^6))*x^18 + (O(3^6))*x^17 + (O(3^6))*x^16 + (O(3^6))*x^15 + (O(3^6))*x^14 + (O(3^6))*x^13 + (O(3^6))*x^12 + (O(3^6))*x^11 + (O(3^6))*x^10 + (O(3^6))*x^9 + (O(3^6))*x^8 + (O(3^6))*x^7 + (O(3^6))*x^6 + (O(3^6))*x^5 + (O(3^6))*x^4 + (O(3^6))*x^3 + (O(3^6))*x^2 + (O(3^6))*x + (2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + O(3^6)) defined by (1 + O(a^150))*y^2 = (1 + O(a^150))*x^5 + (2 + 2*a^30 + a^60 + 2*a^90 + 2*a^120 + O(a^150))*x + a^60 + O(a^210)
86
87
sage: R.<x> = FiniteField(7)[]
88
sage: H = HyperellipticCurve(x^8 + x + 5)
89
sage: H.base_extend(FiniteField(7^2, 'a'))
90
Hyperelliptic Curve over Finite Field in a of size 7^2 defined by y^2 = x^8 + x + 5
91
"""
92
from constructor import HyperellipticCurve
93
f, h = self._hyperelliptic_polynomials
94
y = self._printing_ring.variable_name()
95
x = self._printing_ring.base_ring().variable_name()
96
return HyperellipticCurve(f.change_ring(R), h.change_ring(R), "%s,%s"%(x,y))
97
98
base_extend = change_ring
99
100
def _repr_(self):
101
"""
102
String representation of hyperelliptic curves.
103
104
EXAMPLE::
105
106
sage: P.<x> = QQ[]
107
sage: f = 4*x^5 - 30*x^3 + 45*x - 22
108
sage: C = HyperellipticCurve(f); C
109
Hyperelliptic Curve over Rational Field defined by y^2 = 4*x^5 - 30*x^3 + 45*x - 22
110
sage: C = HyperellipticCurve(f,names='u,v'); C
111
Hyperelliptic Curve over Rational Field defined by v^2 = 4*u^5 - 30*u^3 + 45*u - 22
112
"""
113
114
f, h = self._hyperelliptic_polynomials
115
R = self.base_ring()
116
y = self._printing_ring.gen()
117
x = self._printing_ring.base_ring().gen()
118
if h == 0:
119
return "Hyperelliptic Curve over %s defined by %s = %s"%(R, y**2, f(x))
120
else:
121
return "Hyperelliptic Curve over %s defined by %s + %s = %s"%(R, y**2, h(x)*y, f(x))
122
123
def __cmp__(self, other):
124
if not isinstance(other, HyperellipticCurve_generic):
125
return -1
126
return cmp(self._hyperelliptic_polynomials, other._hyperelliptic_polynomials)
127
128
def hyperelliptic_polynomials(self, K=None, var='x'):
129
"""
130
EXAMPLES::
131
132
sage: R.<x> = QQ[]; C = HyperellipticCurve(x^3 + x - 1, x^3/5); C
133
Hyperelliptic Curve over Rational Field defined by y^2 + 1/5*x^3*y = x^3 + x - 1
134
sage: C.hyperelliptic_polynomials()
135
(x^3 + x - 1, 1/5*x^3)
136
"""
137
if K is None:
138
return self._hyperelliptic_polynomials
139
else:
140
f, h = self._hyperelliptic_polynomials
141
P = PolynomialRing(K, var)
142
return (P(f),P(h))
143
144
def is_singular(self):
145
r"""
146
Returns False, because hyperelliptic curves are smooth projective
147
curves, as checked on construction.
148
149
EXAMPLES::
150
151
sage: R.<x> = QQ[]
152
sage: H = HyperellipticCurve(x^5+1)
153
sage: H.is_singular()
154
False
155
156
A hyperelliptic curve with genus at least 2 always has a singularity at
157
infinity when viewed as a *plane* projective curve. This can be seen in
158
the following example.::
159
160
sage: R.<x> = QQ[]
161
sage: H = HyperellipticCurve(x^5+2)
162
sage: set_verbose(None)
163
sage: H.is_singular()
164
False
165
sage: from sage.schemes.plane_curves.projective_curve import ProjectiveCurve_generic
166
sage: ProjectiveCurve_generic.is_singular(H)
167
True
168
"""
169
return False
170
171
def is_smooth(self):
172
r"""
173
Returns True, because hyperelliptic curves are smooth projective
174
curves, as checked on construction.
175
176
EXAMPLES::
177
178
sage: R.<x> = GF(13)[]
179
sage: H = HyperellipticCurve(x^8+1)
180
sage: H.is_smooth()
181
True
182
183
A hyperelliptic curve with genus at least 2 always has a singularity at
184
infinity when viewed as a *plane* projective curve. This can be seen in
185
the following example.::
186
187
sage: R.<x> = GF(27, 'a')[]
188
sage: H = HyperellipticCurve(x^10+2)
189
sage: set_verbose(None)
190
sage: H.is_smooth()
191
True
192
sage: from sage.schemes.plane_curves.projective_curve import ProjectiveCurve_generic
193
sage: ProjectiveCurve_generic.is_smooth(H)
194
False
195
"""
196
return True
197
198
def lift_x(self, x, all=False):
199
f, h = self._hyperelliptic_polynomials
200
x += self.base_ring()(0)
201
one = x.parent()(1)
202
if h.is_zero():
203
y2 = f(x)
204
if y2.is_square():
205
if all:
206
return [self.point([x, y, one], check=False) for y in y2.sqrt(all=True)]
207
else:
208
return self.point([x, y2.sqrt(), one], check=False)
209
else:
210
b = h(x)
211
D = b*b + 4*f(x)
212
if D.is_square():
213
if all:
214
return [self.point([x, (-b+d)/2, one], check=False) for d in D.sqrt(all=True)]
215
else:
216
return self.point([x, (-b+D.sqrt())/2, one], check=False)
217
if all:
218
return []
219
else:
220
raise ValueError, "No point with x-coordinate %s on %s"%(x, self)
221
222
223
def genus(self):
224
return self._genus
225
226
def jacobian(self):
227
import jacobian_generic
228
return jacobian_generic.HyperellipticJacobian_generic(self)
229
230
def odd_degree_model(self):
231
r"""
232
Return an odd degree model of self, or raise ValueError if one does not exist over the field of definition.
233
234
EXAMPLES::
235
236
sage: x = QQ['x'].gen()
237
sage: H = HyperellipticCurve((x^2 + 2)*(x^2 + 3)*(x^2 + 5)); H
238
Hyperelliptic Curve over Rational Field defined by y^2 = x^6 + 10*x^4 + 31*x^2 + 30
239
sage: H.odd_degree_model()
240
Traceback (most recent call last):
241
...
242
ValueError: No odd degree model exists over field of definition
243
244
sage: K2 = QuadraticField(-2, 'a')
245
sage: Hp2 = H.change_ring(K2).odd_degree_model(); Hp2
246
Hyperelliptic Curve over Number Field in a with defining polynomial x^2 + 2 defined by y^2 = 6*a*x^5 - 29*x^4 - 20*x^2 + 6*a*x + 1
247
248
sage: K3 = QuadraticField(-3, 'b')
249
sage: Hp3 = H.change_ring(QuadraticField(-3, 'b')).odd_degree_model(); Hp3
250
Hyperelliptic Curve over Number Field in b with defining polynomial x^2 + 3 defined by y^2 = -4*b*x^5 - 14*x^4 - 20*b*x^3 - 35*x^2 + 6*b*x + 1
251
252
Of course, Hp2 and Hp3 are isomorphic over the composite
253
extension. One consequence of this is that odd degree models
254
reduced over "different" fields should have the same number of
255
points on their reductions. 43 and 67 split completely in the
256
compositum, so when we reduce we find:
257
258
sage: P2 = K2.factor(43)[0][0]
259
sage: P3 = K3.factor(43)[0][0]
260
sage: Hp2.change_ring(K2.residue_field(P2)).frobenius_polynomial()
261
x^4 - 16*x^3 + 134*x^2 - 688*x + 1849
262
sage: Hp3.change_ring(K3.residue_field(P3)).frobenius_polynomial()
263
x^4 - 16*x^3 + 134*x^2 - 688*x + 1849
264
sage: H.change_ring(GF(43)).odd_degree_model().frobenius_polynomial()
265
x^4 - 16*x^3 + 134*x^2 - 688*x + 1849
266
267
sage: P2 = K2.factor(67)[0][0]
268
sage: P3 = K3.factor(67)[0][0]
269
sage: Hp2.change_ring(K2.residue_field(P2)).frobenius_polynomial()
270
x^4 - 8*x^3 + 150*x^2 - 536*x + 4489
271
sage: Hp3.change_ring(K3.residue_field(P3)).frobenius_polynomial()
272
x^4 - 8*x^3 + 150*x^2 - 536*x + 4489
273
sage: H.change_ring(GF(67)).odd_degree_model().frobenius_polynomial()
274
x^4 - 8*x^3 + 150*x^2 - 536*x + 4489
275
276
TESTS::
277
sage: HyperellipticCurve(x^5 + 1, 1).odd_degree_model()
278
Traceback (most recent call last):
279
...
280
NotImplementedError: odd_degree_model only implemented for curves in Weierstrass form
281
282
sage: HyperellipticCurve(x^5 + 1, names="U, V").odd_degree_model()
283
Hyperelliptic Curve over Rational Field defined by V^2 = U^5 + 1
284
"""
285
f, h = self._hyperelliptic_polynomials
286
if h:
287
raise NotImplementedError, "odd_degree_model only implemented for curves in Weierstrass form"
288
if f.degree() % 2:
289
# already odd, so just yield self
290
return self
291
292
rts = f.roots(multiplicities=False)
293
if not rts:
294
raise ValueError, "No odd degree model exists over field of definition"
295
rt = rts[0]
296
x = f.parent().gen()
297
fnew = f((x*rt + 1)/x).numerator() # move rt to "infinity"
298
299
from constructor import HyperellipticCurve
300
return HyperellipticCurve(fnew, 0, names=self._names, PP=self._PP)
301
302
def has_odd_degree_model(self):
303
r"""
304
Return True if an odd degree model of self exists over the field of definition; False otherwise.
305
306
Use ``odd_degree_model`` to calculate an odd degree model.
307
308
EXAMPLES::
309
sage: x = QQ['x'].0
310
sage: HyperellipticCurve(x^5 + x).has_odd_degree_model()
311
True
312
sage: HyperellipticCurve(x^6 + x).has_odd_degree_model()
313
True
314
sage: HyperellipticCurve(x^6 + x + 1).has_odd_degree_model()
315
False
316
"""
317
try:
318
return bool(self.odd_degree_model())
319
except ValueError:
320
return False
321
322
def _magma_init_(self, magma):
323
"""
324
Internal function. Returns a string to initialize this elliptic
325
curve in the Magma subsystem.
326
327
EXAMPLES::
328
329
sage: R.<x> = QQ[]; C = HyperellipticCurve(x^3 + x - 1, x); C
330
Hyperelliptic Curve over Rational Field defined by y^2 + x*y = x^3 + x - 1
331
sage: magma(C) # optional - magma
332
Hyperelliptic Curve defined by y^2 + x*y = x^3 + x - 1 over Rational Field
333
sage: R.<x> = GF(9,'a')[]; C = HyperellipticCurve(x^3 + x - 1, x^10); C
334
Hyperelliptic Curve over Finite Field in a of size 3^2 defined by y^2 + x^10*y = x^3 + x + 2
335
sage: D = magma(C); D # optional - magma
336
Hyperelliptic Curve defined by y^2 + (x^10)*y = x^3 + x + 2 over GF(3^2)
337
sage: D.sage() # optional - magma
338
Hyperelliptic Curve over Finite Field in a of size 3^2 defined by y^2 + x^10*y = x^3 + x + 2
339
"""
340
f, h = self._hyperelliptic_polynomials
341
return 'HyperellipticCurve(%s, %s)'%(f._magma_init_(magma), h._magma_init_(magma))
342
343
344
def monsky_washnitzer_gens(self):
345
import sage.schemes.elliptic_curves.monsky_washnitzer as monsky_washnitzer
346
S = monsky_washnitzer.SpecialHyperellipticQuotientRing(self)
347
return S.gens()
348
349
def invariant_differential(self):
350
"""
351
Returns $dx/2y$, as an element of the Monsky-Washnitzer cohomology
352
of self
353
354
EXAMPLES::
355
356
sage: R.<x> = QQ['x']
357
sage: C = HyperellipticCurve(x^5 - 4*x + 4)
358
sage: C.invariant_differential()
359
1 dx/2y
360
361
"""
362
import sage.schemes.elliptic_curves.monsky_washnitzer as m_w
363
S = m_w.SpecialHyperellipticQuotientRing(self)
364
MW = m_w.MonskyWashnitzerDifferentialRing(S)
365
return MW.invariant_differential()
366
367
def local_coordinates_at_nonweierstrass(self, P, prec=20, name='t'):
368
"""
369
For a non-Weierstrass point P = (a,b) on the hyperelliptic
370
curve y^2 = f(x), returns (x(t), y(t)) such that (y(t))^2 = f(x(t)),
371
where t = x - a is the local parameter.
372
373
INPUT:
374
375
- P = (a,b) a non-Weierstrass point on self
376
- prec: desired precision of the local coordinates
377
- name: gen of the power series ring (default: 't')
378
379
OUTPUT:
380
(x(t),y(t)) such that y(t)^2 = f(x(t)) and t = x - a
381
is the local parameter at P
382
383
EXAMPLES::
384
385
sage: R.<x> = QQ['x']
386
sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x)
387
sage: P = H(1,6)
388
sage: x,y = H.local_coordinates_at_nonweierstrass(P,prec=5)
389
sage: x
390
1 + t + O(t^5)
391
sage: y
392
6 + t - 7/2*t^2 - 1/2*t^3 - 25/48*t^4 + O(t^5)
393
sage: Q = H(-2,12)
394
sage: x,y = H.local_coordinates_at_nonweierstrass(Q,prec=5)
395
sage: x
396
-2 + t + O(t^5)
397
sage: y
398
12 - 19/2*t - 19/32*t^2 + 61/256*t^3 - 5965/24576*t^4 + O(t^5)
399
400
AUTHOR:
401
402
- Jennifer Balakrishnan (2007-12)
403
"""
404
d = P[1]
405
if d == 0:
406
raise TypeError, "P = %s is a Weierstrass point. Use local_coordinates_at_weierstrass instead!"%P
407
pol = self.hyperelliptic_polynomials()[0]
408
L = PowerSeriesRing(self.base_ring(), name)
409
t = L.gen()
410
L.set_default_prec(prec)
411
K = PowerSeriesRing(L, 'x')
412
pol = K(pol)
413
x = K.gen()
414
b = P[0]
415
f = pol(t+b)
416
for i in range((RR(log(prec)/log(2))).ceil()):
417
d = (d + f/d)/2
418
return t+b+O(t**(prec)), d + O(t**(prec))
419
420
def local_coordinates_at_weierstrass(self, P, prec=20, name='t'):
421
"""
422
For a finite Weierstrass point on the hyperelliptic
423
curve y^2 = f(x), returns (x(t), y(t)) such that
424
(y(t))^2 = f(x(t)), where t = y is the local parameter.
425
426
INPUT:
427
- P a finite Weierstrass point on self
428
- prec: desired precision of the local coordinates
429
- name: gen of the power series ring (default: 't')
430
431
OUTPUT:
432
433
(x(t),y(t)) such that y(t)^2 = f(x(t)) and t = y
434
is the local parameter at P
435
436
EXAMPLES:
437
sage: R.<x> = QQ['x']
438
sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x)
439
sage: A = H(4, 0)
440
441
sage: x, y = H.local_coordinates_at_weierstrass(A, prec=7)
442
443
sage: x
444
4 + 1/360*t^2 - 191/23328000*t^4 + 7579/188956800000*t^6 + O(t^7)
445
sage: y
446
t + O(t^7)
447
sage: B = H(-5, 0)
448
sage: x, y = H.local_coordinates_at_weierstrass(B, prec=5)
449
sage: x
450
-5 + 1/1260*t^2 + 887/2000376000*t^4 + O(t^5)
451
sage: y
452
t + O(t^5)
453
454
AUTHOR:
455
- Jennifer Balakrishnan (2007-12)
456
457
- Francis Clarke (2012-08-26)
458
"""
459
if P[1] != 0:
460
raise TypeError, "P = %s is not a finite Weierstrass point. Use local_coordinates_at_nonweierstrass instead!"%P
461
L = PowerSeriesRing(self.base_ring(), name)
462
t = L.gen()
463
pol = self.hyperelliptic_polynomials()[0]
464
pol_prime = pol.derivative()
465
b = P[0]
466
t2 = t**2
467
c = b + t2/pol_prime(b)
468
c = c.add_bigoh(prec)
469
for _ in range(1 + log(prec, 2)):
470
c -= (pol(c) - t2)/pol_prime(c)
471
return (c, t.add_bigoh(prec))
472
473
def local_coordinates_at_infinity(self, prec = 20, name = 't'):
474
"""
475
For the genus g hyperelliptic curve y^2 = f(x), returns (x(t), y(t)) such that
476
(y(t))^2 = f(x(t)), where t = x^g/y is the local parameter at infinity
477
478
INPUT:
479
- prec: desired precision of the local coordinates
480
- name: gen of the power series ring (default: 't')
481
482
OUTPUT:
483
(x(t),y(t)) such that y(t)^2 = f(x(t)) and t = x^g/y
484
is the local parameter at infinity
485
486
487
EXAMPLES:
488
sage: R.<x> = QQ['x']
489
sage: H = HyperellipticCurve(x^5-5*x^2+1)
490
sage: x,y = H.local_coordinates_at_infinity(10)
491
sage: x
492
t^-2 + 5*t^4 - t^8 - 50*t^10 + O(t^12)
493
sage: y
494
t^-5 + 10*t - 2*t^5 - 75*t^7 + 50*t^11 + O(t^12)
495
496
sage: R.<x> = QQ['x']
497
sage: H = HyperellipticCurve(x^3-x+1)
498
sage: x,y = H.local_coordinates_at_infinity(10)
499
sage: x
500
t^-2 + t^2 - t^4 - t^6 + 3*t^8 + O(t^12)
501
sage: y
502
t^-3 + t - t^3 - t^5 + 3*t^7 - 10*t^11 + O(t^12)
503
504
505
AUTHOR:
506
- Jennifer Balakrishnan (2007-12)
507
"""
508
g = self.genus()
509
pol = self.hyperelliptic_polynomials()[0]
510
K = LaurentSeriesRing(self.base_ring(), name)
511
t = K.gen()
512
K.set_default_prec(prec+2)
513
L = PolynomialRing(self.base_ring(),'x')
514
x = L.gen()
515
i = 0
516
w = (x**g/t)**2-pol
517
wprime = w.derivative(x)
518
x = t**-2
519
for i in range((RR(log(prec+2)/log(2))).ceil()):
520
x = x-w(x)/wprime(x)
521
y = x**g/t
522
return x+O(t**(prec+2)) , y+O(t**(prec+2))
523
524
525
def local_coord(self, P, prec = 20, name = 't'):
526
"""
527
Calls the appropriate local_coordinates function
528
529
INPUT:
530
- P a point on self
531
- prec: desired precision of the local coordinates
532
- name: gen of the power series ring (default: 't')
533
534
OUTPUT:
535
(x(t),y(t)) such that y(t)^2 = f(x(t)), where t
536
is the local parameter at P
537
538
EXAMPLES:
539
sage: R.<x> = QQ['x']
540
sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x)
541
sage: H.local_coord(H(1 ,6), prec=5)
542
(1 + t + O(t^5), 6 + t - 7/2*t^2 - 1/2*t^3 - 25/48*t^4 + O(t^5))
543
sage: H.local_coord(H(4, 0), prec=7)
544
(4 + 1/360*t^2 - 191/23328000*t^4 + 7579/188956800000*t^6 + O(t^7), t + O(t^7))
545
sage: H.local_coord(H(0, 1, 0), prec=5)
546
(t^-2 + 23*t^2 - 18*t^4 - 569*t^6 + O(t^7), t^-5 + 46*t^-1 - 36*t - 609*t^3 + 1656*t^5 + O(t^6))
547
548
AUTHOR:
549
- Jennifer Balakrishnan (2007-12)
550
551
552
"""
553
if P[1] == 0:
554
return self.local_coordinates_at_weierstrass(P, prec, name)
555
elif P[2] == 0:
556
return self.local_coordinates_at_infinity(prec, name)
557
else:
558
return self.local_coordinates_at_nonweierstrass(P, prec, name)
559
560