def power_series(self, prec=20): r""" Computes and returns the power series of this modular parametrization. The curve must be a a minimal model. The prec parameter determines the number of significant terms. This means that X will be given up to O(q^(prec-2)) and Y will be given up to O(q^(prec-3)). OUTPUT: A list of two Laurent series ``[X(x),Y(x)]`` of degrees -2, -3 respectively, which satisfy the equation of the elliptic curve. There are modular functions on `\Gamma_0(N)` where `N` is the conductor. The series should satisfy the differential equation .. math:: \frac{\mathrm{d}X}{2Y + a_1 X + a_3} = \frac{f(q)\, \mathrm{d}q}{q} where `f` is ``self.curve().q_expansion()``. EXAMPLES:: sage: E=EllipticCurve('389a1') sage: phi = E.modular_parametrization() sage: X,Y = phi.power_series(prec = 10) sage: X q^-2 + 2*q^-1 + 4 + 7*q + 13*q^2 + 18*q^3 + 31*q^4 + 49*q^5 + 74*q^6 + 111*q^7 + O(q^8) sage: Y -q^-3 - 3*q^-2 - 8*q^-1 - 17 - 33*q - 61*q^2 - 110*q^3 - 186*q^4 - 320*q^5 - 528*q^6 + O(q^7) sage: X,Y = phi.power_series() sage: X q^-2 + 2*q^-1 + 4 + 7*q + 13*q^2 + 18*q^3 + 31*q^4 + 49*q^5 + 74*q^6 + 111*q^7 + 173*q^8 + 251*q^9 + 379*q^10 + 560*q^11 + 824*q^12 + 1199*q^13 + 1773*q^14 + 2548*q^15 + 3722*q^16 + 5374*q^17 + O(q^18) sage: Y -q^-3 - 3*q^-2 - 8*q^-1 - 17 - 33*q - 61*q^2 - 110*q^3 - 186*q^4 - 320*q^5 - 528*q^6 - 861*q^7 - 1383*q^8 - 2218*q^9 - 3472*q^10 - 5451*q^11 - 8447*q^12 - 13020*q^13 - 19923*q^14 - 30403*q^15 - 46003*q^16 + O(q^17) The following should give 0, but only approximately:: sage: q = X.parent().gen() sage: E.defining_polynomial()(X,Y,1) + O(q^11) == 0 True Note that below we have to change variable from x to q:: sage: a1,_,a3,_,_=E.a_invariants() sage: f=E.q_expansion(17) sage: q=f.parent().gen() sage: f/q == (X.derivative()/(2*Y+a1*X+a3)) True """ R = LaurentSeriesRing(RationalField(),'q') if not self._E.is_minimal(): raise NotImplementedError, "Only implemented for minimal curves." from sage.libs.all import pari old_prec = pari.get_series_precision() pari.set_series_precision(prec-1) XY = self._E.pari_mincurve().elltaniyama() pari.set_series_precision(old_prec) return R(XY[0]),R(XY[1])
def local_coordinates_at_infinity(self, prec=20, name='t'): """ For the genus `g` hyperelliptic curve `y^2 = f(x)`, return `(x(t), y(t))` such that `(y(t))^2 = f(x(t))`, where `t = x^g/y` is the local parameter at infinity INPUT: - ``prec`` -- desired precision of the local coordinates - ``name`` -- generator of the power series ring (default: ``t``) OUTPUT: `(x(t),y(t))` such that `y(t)^2 = f(x(t))` and `t = x^g/y` is the local parameter at infinity EXAMPLES:: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5-5*x^2+1) sage: x,y = H.local_coordinates_at_infinity(10) sage: x t^-2 + 5*t^4 - t^8 - 50*t^10 + O(t^12) sage: y t^-5 + 10*t - 2*t^5 - 75*t^7 + 50*t^11 + O(t^12) :: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^3-x+1) sage: x,y = H.local_coordinates_at_infinity(10) sage: x t^-2 + t^2 - t^4 - t^6 + 3*t^8 + O(t^12) sage: y t^-3 + t - t^3 - t^5 + 3*t^7 - 10*t^11 + O(t^12) Note: if even degree model, just returns local coordinate above one point AUTHOR: - Jennifer Balakrishnan (2007-12) """ g = self.genus() pol = self.hyperelliptic_polynomials()[0] K = LaurentSeriesRing(self.base_ring(), name) t = K.gen() K.set_default_prec(prec + 2) L = PolynomialRing(K, 'x') x = L.gen() i = 0 w = (x**g / t)**2 - pol wprime = w.derivative(x) if pol.degree() == 2 * g + 1: x = t**-2 else: x = t**-1 for i in range((RR(log(prec + 2) / log(2))).ceil()): x = x - w(x) / wprime(x) y = x**g / t return x + O(t**(prec + 2)), y + O(t**(prec + 2))
def approximate_series(self, prec, name=None): """ Return the Laurent series with absolute precision ``prec`` approximated from this series. INPUT: - ``prec`` -- an integer - ``name`` -- name of the variable; if it is ``None``, the name of the variable of the series is used OUTPUT: a Laurent series with absolute precision ``prec`` EXAMPLES:: sage: L = LazyLaurentSeriesRing(ZZ, 'z') sage: z = L.gen() sage: f = (z - 2*z^3)^5/(1 - 2*z) sage: f z^5 + 2*z^6 - 6*z^7 - 12*z^8 + 16*z^9 + 32*z^10 - 16*z^11 + ... sage: g = f.approximate_series(10) sage: g z^5 + 2*z^6 - 6*z^7 - 12*z^8 + 16*z^9 + O(z^10) sage: g.parent() Power Series Ring in z over Integer Ring :: sage: h = (f^-1).approximate_series(3) sage: h z^-5 - 2*z^-4 + 10*z^-3 - 20*z^-2 + 60*z^-1 - 120 + 280*z - 560*z^2 + O(z^3) sage: h.parent() Laurent Series Ring in z over Integer Ring """ S = self.parent() if name is None: name = S.variable_name() if self.valuation() < 0: from sage.rings.all import LaurentSeriesRing R = LaurentSeriesRing(S.base_ring(), name=name) n = self.valuation() return R([self.coefficient(i) for i in range(n, prec)], n).add_bigoh(prec) else: from sage.rings.all import PowerSeriesRing R = PowerSeriesRing(S.base_ring(), name=name) return R([self.coefficient(i) for i in range(prec)]).add_bigoh(prec)
def local_coordinates_at_infinity(self, prec=20, name='t'): """ For the genus g hyperelliptic curve y^2 = f(x), returns (x(t), y(t)) such that (y(t))^2 = f(x(t)), where t = x^g/y is the local parameter at infinity INPUT: - prec: desired precision of the local coordinates - name: gen of the power series ring (default: 't') OUTPUT: (x(t),y(t)) such that y(t)^2 = f(x(t)) and t = x^g/y is the local parameter at infinity EXAMPLES: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5-5*x^2+1) sage: x,y = H.local_coordinates_at_infinity(10) sage: x t^-2 + 5*t^4 - t^8 - 50*t^10 + O(t^12) sage: y t^-5 + 10*t - 2*t^5 - 75*t^7 + 50*t^11 + O(t^12) sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^3-x+1) sage: x,y = H.local_coordinates_at_infinity(10) sage: x t^-2 + t^2 - t^4 - t^6 + 3*t^8 + O(t^12) sage: y t^-3 + t - t^3 - t^5 + 3*t^7 - 10*t^11 + O(t^12) AUTHOR: - Jennifer Balakrishnan (2007-12) """ g = self.genus() pol = self.hyperelliptic_polynomials()[0] K = LaurentSeriesRing(self.base_ring(), name) t = K.gen() K.set_default_prec(prec + 2) L = PolynomialRing(self.base_ring(), 'x') x = L.gen() i = 0 w = (x**g / t)**2 - pol wprime = w.derivative(x) x = t**-2 for i in range((RR(log(prec + 2) / log(2))).ceil()): x = x - w(x) / wprime(x) y = x**g / t return x + O(t**(prec + 2)), y + O(t**(prec + 2))