def local_coordinates_at_nonweierstrass(self, P, prec=20, name='t'): """ For a non-Weierstrass point `P = (a,b)` on the hyperelliptic curve `y^2 = f(x)`, return `(x(t), y(t))` such that `(y(t))^2 = f(x(t))`, where `t = x - a` is the local parameter. INPUT: - ``P = (a, b)`` -- a non-Weierstrass point on self - ``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 - a` is the local parameter at `P` EXAMPLES:: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x) sage: P = H(1,6) sage: x,y = H.local_coordinates_at_nonweierstrass(P,prec=5) sage: x 1 + t + O(t^5) sage: y 6 + t - 7/2*t^2 - 1/2*t^3 - 25/48*t^4 + O(t^5) sage: Q = H(-2,12) sage: x,y = H.local_coordinates_at_nonweierstrass(Q,prec=5) sage: x -2 + t + O(t^5) sage: y 12 - 19/2*t - 19/32*t^2 + 61/256*t^3 - 5965/24576*t^4 + O(t^5) AUTHOR: - Jennifer Balakrishnan (2007-12) """ d = P[1] if d == 0: raise TypeError( "P = %s is a Weierstrass point. Use local_coordinates_at_weierstrass instead!" % P) pol = self.hyperelliptic_polynomials()[0] L = PowerSeriesRing(self.base_ring(), name) t = L.gen() L.set_default_prec(prec) K = PowerSeriesRing(L, 'x') pol = K(pol) x = K.gen() b = P[0] f = pol(t + b) for i in range((RR(log(prec) / log(2))).ceil()): d = (d + f / d) / 2 return t + b + O(t**(prec)), d + O(t**(prec))
def local_coordinates_at_nonweierstrass(self, P, prec=20, name='t'): """ For a non-Weierstrass point `P = (a,b)` on the hyperelliptic curve `y^2 = f(x)`, return `(x(t), y(t))` such that `(y(t))^2 = f(x(t))`, where `t = x - a` is the local parameter. INPUT: - ``P = (a, b)`` -- a non-Weierstrass point on self - ``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 - a` is the local parameter at `P` EXAMPLES:: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x) sage: P = H(1,6) sage: x,y = H.local_coordinates_at_nonweierstrass(P,prec=5) sage: x 1 + t + O(t^5) sage: y 6 + t - 7/2*t^2 - 1/2*t^3 - 25/48*t^4 + O(t^5) sage: Q = H(-2,12) sage: x,y = H.local_coordinates_at_nonweierstrass(Q,prec=5) sage: x -2 + t + O(t^5) sage: y 12 - 19/2*t - 19/32*t^2 + 61/256*t^3 - 5965/24576*t^4 + O(t^5) AUTHOR: - Jennifer Balakrishnan (2007-12) """ d = P[1] if d == 0: raise TypeError("P = %s is a Weierstrass point. Use local_coordinates_at_weierstrass instead!"%P) pol = self.hyperelliptic_polynomials()[0] L = PowerSeriesRing(self.base_ring(), name) t = L.gen() L.set_default_prec(prec) K = PowerSeriesRing(L, 'x') pol = K(pol) x = K.gen() b = P[0] f = pol(t+b) for i in range((RR(log(prec)/log(2))).ceil()): d = (d + f/d)/2 return t+b+O(t**(prec)), d + O(t**(prec))
def local_coordinates_at_weierstrass(self, P, prec=20, name='t'): """ For a finite Weierstrass point on the hyperelliptic curve y^2 = f(x), returns (x(t), y(t)) such that (y(t))^2 = f(x(t)), where t = y is the local parameter. INPUT: - P a finite Weierstrass point on self - 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 = y is the local parameter at P EXAMPLES: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x) sage: A = H(4,0) sage: x,y = H.local_coordinates_at_weierstrass(A,prec =5) sage: x 4 + 1/360*t^2 - 191/23328000*t^4 + 7579/188956800000*t^6 + O(t^7) sage: y t + O(t^7) sage: B = H(-5,0) sage: x,y = H.local_coordinates_at_weierstrass(B,prec = 5) sage: x -5 + 1/1260*t^2 + 887/2000376000*t^4 + 643759/1587898468800000*t^6 + O(t^7) sage: y t + O(t^7) AUTHOR: - Jennifer Balakrishnan (2007-12) """ if P[1] != 0: raise TypeError, "P = %s is not a finite Weierstrass point. Use local_coordinates_at_nonweierstrass instead!" % P pol = self.hyperelliptic_polynomials()[0] L = PowerSeriesRing(self.base_ring(), name) t = L.gen() L.set_default_prec(prec + 2) K = PowerSeriesRing(L, 'x') pol = K(pol) x = K.gen() b = P[0] g = pol / (x - b) c = b + 1 / g(b) * t**2 f = pol - t**2 fprime = f.derivative() for i in range((RR(log(prec + 2) / log(2))).ceil()): c = c - f(c) / fprime(c) return c + O(t**(prec + 2)), t + O(t**(prec + 2))
def local_coordinates_at_weierstrass(self, P, prec=20, name="t"): """ For a finite Weierstrass point on the hyperelliptic curve y^2 = f(x), returns (x(t), y(t)) such that (y(t))^2 = f(x(t)), where t = y is the local parameter. INPUT: - P a finite Weierstrass point on self - 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 = y is the local parameter at P EXAMPLES: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x) sage: A = H(4,0) sage: x,y = H.local_coordinates_at_weierstrass(A,prec =5) sage: x 4 + 1/360*t^2 - 191/23328000*t^4 + 7579/188956800000*t^6 + O(t^7) sage: y t + O(t^7) sage: B = H(-5,0) sage: x,y = H.local_coordinates_at_weierstrass(B,prec = 5) sage: x -5 + 1/1260*t^2 + 887/2000376000*t^4 + 643759/1587898468800000*t^6 + O(t^7) sage: y t + O(t^7) AUTHOR: - Jennifer Balakrishnan (2007-12) """ if P[1] != 0: raise TypeError, "P = %s is not a finite Weierstrass point. Use local_coordinates_at_nonweierstrass instead!" % P pol = self.hyperelliptic_polynomials()[0] L = PowerSeriesRing(self.base_ring(), name) t = L.gen() L.set_default_prec(prec + 2) K = PowerSeriesRing(L, "x") pol = K(pol) x = K.gen() b = P[0] g = pol / (x - b) c = b + 1 / g(b) * t ** 2 f = pol - t ** 2 fprime = f.derivative() for i in range((RR(log(prec + 2) / log(2))).ceil()): c = c - f(c) / fprime(c) return c + O(t ** (prec + 2)), t + O(t ** (prec + 2))
def get_basic_integral(G, cocycle, gamma, center, j, prec=None): p = G.p HOC = cocycle.parent() V = HOC.coefficient_module() if prec is None: prec = V.precision_cap() Cp = Qp(p, prec) verbose('precision = %s' % prec) R = PolynomialRing(Cp, names='t') PS = PowerSeriesRing(Cp, names='z') t = R.gen() z = PS.gen() if prec is None: prec = V.precision_cap() try: coeff_depth = V.precision_cap() except AttributeError: coeff_depth = V.coefficient_module().precision_cap() resadd = ZZ(0) edgelist = G.get_covering(1)[1:] for rev, h in edgelist: a, b, c, d = [Cp(o) for o in G.embed(h, prec).list()] try: c0val = 0 pol = PS(d * z + b) / PS(c * z + a) pol -= Cp.teichmuller(center) pol = pol**j pol = pol.polynomial() newgamma = G.Gpn( G.reduce_in_amalgam(h * gamma.quaternion_rep, return_word=False)) if rev: # DEBUG newgamma = newgamma.conjugate_by(G.wp()) print 'reversing' if G.use_shapiro(): mu_e = cocycle.evaluate_and_identity(newgamma) else: mu_e = cocycle.evaluate(newgamma) if newgamma.quaternion_rep != 1: print 'newgamma = ', newgamma except AttributeError: verbose('...') continue if HOC._use_ps_dists: tmp = sum(a * mu_e.moment(i) for a, i in izip(pol.coefficients(), pol.exponents()) if i < len(mu_e._moments)) else: tmp = mu_e.evaluate_at_poly(pol, Cp, coeff_depth) resadd += tmp try: if G.use_shapiro(): tmp = cocycle.get_liftee().evaluate_and_identity(newgamma) else: tmp = cocycle.get_liftee().evaluate(newgamma) except IndexError: pass return resadd
def _e_bounds(self, n, prec): p = self._p prec = max(2,prec) R = PowerSeriesRing(ZZ,'T',prec+1) T = R(R.gen(),prec +1) w = (1+T)**(p**n) - 1 return [infinity] + [valuation(w[j],p) for j in range(1,min(w.degree()+1,prec))]
def local_coordinates_at_weierstrass(self, P, prec=20, name='t'): """ For a finite Weierstrass point on the hyperelliptic curve y^2 = f(x), returns (x(t), y(t)) such that (y(t))^2 = f(x(t)), where t = y is the local parameter. INPUT: - P a finite Weierstrass point on self - 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 = y is the local parameter at P EXAMPLES: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x) sage: A = H(4, 0) sage: x, y = H.local_coordinates_at_weierstrass(A, prec=7) sage: x 4 + 1/360*t^2 - 191/23328000*t^4 + 7579/188956800000*t^6 + O(t^7) sage: y t + O(t^7) sage: B = H(-5, 0) sage: x, y = H.local_coordinates_at_weierstrass(B, prec=5) sage: x -5 + 1/1260*t^2 + 887/2000376000*t^4 + O(t^5) sage: y t + O(t^5) AUTHOR: - Jennifer Balakrishnan (2007-12) - Francis Clarke (2012-08-26) """ if P[1] != 0: raise TypeError( "P = %s is not a finite Weierstrass point. Use local_coordinates_at_nonweierstrass instead!" % P) L = PowerSeriesRing(self.base_ring(), name) t = L.gen() pol = self.hyperelliptic_polynomials()[0] pol_prime = pol.derivative() b = P[0] t2 = t**2 c = b + t2 / pol_prime(b) c = c.add_bigoh(prec) for _ in range(1 + log(prec, 2)): c -= (pol(c) - t2) / pol_prime(c) return (c, t.add_bigoh(prec))
def zeta_series(self, n, t): """ Return the zeta series. Compute a power series approximation to the zeta function of a scheme over a finite field. INPUT: - ``n`` -- the number of terms of the power series to compute - ``t`` -- the variable which the series should be returned OUTPUT: A power series approximating the zeta function of self EXAMPLES:: sage: P.<x> = PolynomialRing(GF(3)) sage: C = HyperellipticCurve(x^3+x^2+1) sage: R.<t> = PowerSeriesRing(Integers()) sage: C.zeta_series(4,t) 1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5) sage: (1+2*t+3*t^2)/(1-t)/(1-3*t) + O(t^5) 1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5) Note that this function depends on count_points, which is only defined for prime order fields for general schemes. Nonetheless, since :trac:`15108` and :trac:`15148`, it supports hyperelliptic curves over non-prime fields:: sage: C.base_extend(GF(9,'a')).zeta_series(4,t) 1 + 12*t + 120*t^2 + 1092*t^3 + 9840*t^4 + O(t^5) """ F = self.base_ring() if not F.is_finite(): raise TypeError( 'zeta functions only defined for schemes over finite fields') try: a = self.count_points(n) except AttributeError: raise NotImplementedError( 'count_points() required but not implemented') R = PowerSeriesRing(Rationals(), 'u') u = R.gen() temp = sum(a[i - 1] * (u.O(n + 1))**i / i for i in range(1, n + 1)) temp2 = temp.exp() return (temp2(t).O(n + 1))
def local_coordinates_at_weierstrass(self, P, prec=20, name="t"): """ For a finite Weierstrass point on the hyperelliptic curve y^2 = f(x), returns (x(t), y(t)) such that (y(t))^2 = f(x(t)), where t = y is the local parameter. INPUT: - P a finite Weierstrass point on self - 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 = y is the local parameter at P EXAMPLES: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x) sage: A = H(4, 0) sage: x, y = H.local_coordinates_at_weierstrass(A, prec=7) sage: x 4 + 1/360*t^2 - 191/23328000*t^4 + 7579/188956800000*t^6 + O(t^7) sage: y t + O(t^7) sage: B = H(-5, 0) sage: x, y = H.local_coordinates_at_weierstrass(B, prec=5) sage: x -5 + 1/1260*t^2 + 887/2000376000*t^4 + O(t^5) sage: y t + O(t^5) AUTHOR: - Jennifer Balakrishnan (2007-12) - Francis Clarke (2012-08-26) """ if P[1] != 0: raise TypeError, "P = %s is not a finite Weierstrass point. Use local_coordinates_at_nonweierstrass instead!" % P L = PowerSeriesRing(self.base_ring(), name) t = L.gen() pol = self.hyperelliptic_polynomials()[0] pol_prime = pol.derivative() b = P[0] t2 = t ** 2 c = b + t2 / pol_prime(b) c = c.add_bigoh(prec) for _ in range(1 + log(prec, 2)): c -= (pol(c) - t2) / pol_prime(c) return (c, t.add_bigoh(prec))
def zeta_series(self, n, t): """ Return the zeta series. Compute a power series approximation to the zeta function of a scheme over a finite field. INPUT: - ``n`` -- the number of terms of the power series to compute - ``t`` -- the variable which the series should be returned OUTPUT: A power series approximating the zeta function of self EXAMPLES:: sage: P.<x> = PolynomialRing(GF(3)) sage: C = HyperellipticCurve(x^3+x^2+1) sage: R.<t> = PowerSeriesRing(Integers()) sage: C.zeta_series(4,t) 1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5) sage: (1+2*t+3*t^2)/(1-t)/(1-3*t) + O(t^5) 1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5) Note that this function depends on count_points, which is only defined for prime order fields for general schemes. Nonetheless, since :trac:`15108` and :trac:`15148`, it supports hyperelliptic curves over non-prime fields:: sage: C.base_extend(GF(9,'a')).zeta_series(4,t) 1 + 12*t + 120*t^2 + 1092*t^3 + 9840*t^4 + O(t^5) """ F = self.base_ring() if not F.is_finite(): raise TypeError("zeta functions only defined for schemes over finite fields") try: a = self.count_points(n) except AttributeError: raise NotImplementedError("count_points() required but not implemented") R = PowerSeriesRing(Rationals(), "u") u = R.gen() temp = sum(a[i - 1] * (u.O(n + 1)) ** i / i for i in range(1, n + 1)) temp2 = temp.exp() return temp2(t).O(n + 1)
def zeta_series(self, n, t): """ Return the zeta series. Compute a power series approximation to the zeta function of a scheme over a finite field. INPUT: - ``n`` -- the number of terms of the power series to compute - ``t`` -- the variable which the series should be returned OUTPUT: A power series approximating the zeta function of self EXAMPLES:: sage: P.<x> = PolynomialRing(GF(3)) sage: C = HyperellipticCurve(x^3+x^2+1) sage: R.<t> = PowerSeriesRing(Integers()) sage: C.zeta_series(4,t) 1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5) sage: (1+2*t+3*t^2)/(1-t)/(1-3*t) + O(t^5) 1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5) Note that this function depends on count_points, which is only defined for prime order fields:: sage: C.base_extend(GF(9,'a')).zeta_series(4,t) Traceback (most recent call last): ... NotImplementedError: Point counting only implemented for schemes over prime fields """ F = self.base_ring() if not F.is_finite(): raise TypeError('zeta functions only defined for schemes over finite fields') try: a = self.count_points(n) except AttributeError: raise NotImplementedError('count_points() required but not implemented') R = PowerSeriesRing(Rationals(), 'u') u = R.gen() temp = sum(a[i-1]*(u.O(n+1))**i/i for i in range(1,n+1)) temp2 = temp.exp() return(temp2(t).O(n+1))
def zeta_series(self, n, t): """ Return the zeta series. Compute a power series approximation to the zeta function of a scheme over a finite field. INPUT: - ``n`` - the number of terms of the power series to compute - ``t`` - the variable which the series should be returned OUTPUT: A power series approximating the zeta function of self EXAMPLES:: sage: P.<x> = PolynomialRing(GF(3)) sage: C = HyperellipticCurve(x^3+x^2+1) sage: R.<t> = PowerSeriesRing(Integers()) sage: C.zeta_series(4,t) 1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5) sage: (1+2*t+3*t^2)/(1-t)/(1-3*t) + O(t^5) 1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5) Note that this function depends on count_points, which is only defined for prime order fields:: sage: C.base_extend(GF(9,'a')).zeta_series(4,t) Traceback (most recent call last): ... NotImplementedError: Point counting only implemented for schemes over prime fields """ F = self.base_ring() if not F.is_finite(): raise TypeError, "Zeta functions only defined for schemes over finite fields" a = self.count_points(n) R = PowerSeriesRing(Rationals(), 'u') u = R.gen() temp = sum(a[i - 1] * (u.O(n + 1))**i / i for i in range(1, n + 1)) temp2 = temp.exp() return (temp2(t).O(n + 1))
class MFSeriesConstructor(SageObject,UniqueRepresentation): r""" Constructor for the Fourier expansion of some (specific, basic) modular forms. The constructor is used by forms elements in case their Fourier expansion is needed or requested. """ @staticmethod def __classcall__(cls, group = HeckeTriangleGroup(3), prec=ZZ(10)): r""" Return a (cached) instance with canonical parameters. .. NOTE: For each choice of group and precision the constructor is cached (only) once. Further calculations with different base rings and possibly numerical parameters are based on the same cached instance. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor() == MFSeriesConstructor(3, 10) True sage: MFSeriesConstructor(group=4).hecke_n() 4 sage: MFSeriesConstructor(group=5, prec=12).prec() 12 """ if (group==infinity): group = HeckeTriangleGroup(infinity) else: try: group = HeckeTriangleGroup(ZZ(group)) except TypeError: group = HeckeTriangleGroup(group.n()) prec=ZZ(prec) # We don't need this assumption the precision may in principle also be negative. # if (prec<1): # raise Exception("prec must be an Integer >=1") return super(MFSeriesConstructor,cls).__classcall__(cls, group, prec) def __init__(self, group, prec): r""" Constructor for the Fourier expansion of some (specific, basic) modular forms. INPUT: - ``group`` -- A Hecke triangle group (default: HeckeTriangleGroup(3)). - ``prec`` -- An integer (default: 10), the default precision used in calculations in the LaurentSeriesRing or PowerSeriesRing. OUTPUT: The constructor for Fourier expansion with the specified settings. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFC = MFSeriesConstructor() sage: MFC Power series constructor for Hecke modular forms for n=3 with (basic series) precision 10 sage: MFC.group() Hecke triangle group for n = 3 sage: MFC.prec() 10 sage: MFC._series_ring Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=4) Power series constructor for Hecke modular forms for n=4 with (basic series) precision 10 sage: MFSeriesConstructor(group=5, prec=12) Power series constructor for Hecke modular forms for n=5 with (basic series) precision 12 sage: MFSeriesConstructor(group=infinity) Power series constructor for Hecke modular forms for n=+Infinity with (basic series) precision 10 """ self._group = group self._prec = prec self._series_ring = PowerSeriesRing(QQ,'q',default_prec=self._prec) def _repr_(self): r""" Return the string representation of ``self``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(group=4) Power series constructor for Hecke modular forms for n=4 with (basic series) precision 10 sage: MFSeriesConstructor(group=5, prec=12) Power series constructor for Hecke modular forms for n=5 with (basic series) precision 12 """ return "Power series constructor for Hecke modular forms for n={} with (basic series) precision {}".\ format(self._group.n(), self._prec) def group(self): r""" Return the (Hecke triangle) group of ``self``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(group=4).group() Hecke triangle group for n = 4 """ return self._group def hecke_n(self): r""" Return the parameter ``n`` of the (Hecke triangle) group of ``self``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(group=4).hecke_n() 4 """ return self._group.n() def prec(self): r""" Return the used default precision for the PowerSeriesRing or LaurentSeriesRing. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(group=5).prec() 10 sage: MFSeriesConstructor(group=5, prec=20).prec() 20 """ return self._prec @cached_method def J_inv_ZZ(self): r""" Return the rational Fourier expansion of ``J_inv``, where the parameter ``d`` is replaced by ``1``. This is the main function used to determine all Fourier expansions! .. NOTE: The Fourier expansion of ``J_inv`` for ``d!=1`` is given by ``J_inv_ZZ(q/d)``. .. TODO: The functions that are used in this implementation are products of hypergeometric series with other, elementary, functions. Implement them and clean up this representation. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).J_inv_ZZ() q^-1 + 31/72 + 1823/27648*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3).J_inv_ZZ() q^-1 + 79/200 + 42877/640000*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3).J_inv_ZZ().parent() Laurent Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).J_inv_ZZ() q^-1 + 3/8 + 69/1024*q + O(q^2) """ F1 = lambda a,b: self._series_ring( [ ZZ(0) ] + [ rising_factorial(a,k) * rising_factorial(b,k) / (ZZ(k).factorial())**2 * sum(ZZ(1)/(a+j) + ZZ(1)/(b+j) - ZZ(2)/ZZ(1+j) for j in range(ZZ(0),ZZ(k)) ) for k in range(ZZ(1), ZZ(self._prec+1)) ], ZZ(self._prec+1) ) F = lambda a,b,c: self._series_ring( [ rising_factorial(a,k) * rising_factorial(b,k) / rising_factorial(c,k) / ZZ(k).factorial() for k in range(ZZ(0), ZZ(self._prec+1)) ], ZZ(self._prec+1) ) a = self._group.alpha() b = self._group.beta() Phi = F1(a,b) / F(a,b,ZZ(1)) q = self._series_ring.gen() # the current implementation of power series reversion is slow # J_inv_ZZ = ZZ(1) / ((q*Phi.exp()).reverse()) temp_f = (q*Phi.exp()).polynomial() new_f = temp_f.revert_series(temp_f.degree()+1) J_inv_ZZ = ZZ(1) / (new_f + O(q**(temp_f.degree()+1))) return J_inv_ZZ @cached_method def f_rho_ZZ(self): r""" Return the rational Fourier expansion of ``f_rho``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``f_rho`` for ``d!=1`` is given by ``f_rho_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).f_rho_ZZ() 1 + 5/36*q + 5/6912*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).f_rho_ZZ() 1 + 7/100*q + 21/160000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).f_rho_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).f_rho_ZZ() 1 """ q = self._series_ring.gen() n = self.hecke_n() if (n == infinity): f_rho_ZZ = self._series_ring(1) else: temp_expr = ((-q*self.J_inv_ZZ().derivative())**2/(self.J_inv_ZZ()*(self.J_inv_ZZ()-1))).power_series() f_rho_ZZ = (temp_expr.log()/(n-2)).exp() return f_rho_ZZ @cached_method def f_i_ZZ(self): r""" Return the rational Fourier expansion of ``f_i``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``f_i`` for ``d!=1`` is given by ``f_i_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).f_i_ZZ() 1 - 7/24*q - 77/13824*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).f_i_ZZ() 1 - 13/40*q - 351/64000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).f_i_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).f_i_ZZ() 1 - 3/8*q + 3/512*q^2 + O(q^3) """ q = self._series_ring.gen() n = self.hecke_n() if (n == infinity): f_i_ZZ = (-q*self.J_inv_ZZ().derivative()/self.J_inv_ZZ()).power_series() else: temp_expr = ((-q*self.J_inv_ZZ().derivative())**n/(self.J_inv_ZZ()**(n-1)*(self.J_inv_ZZ()-1))).power_series() f_i_ZZ = (temp_expr.log()/(n-2)).exp() return f_i_ZZ @cached_method def f_inf_ZZ(self): r""" Return the rational Fourier expansion of ``f_inf``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``f_inf`` for ``d!=1`` is given by ``d*f_inf_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).f_inf_ZZ() q - 1/72*q^2 + 7/82944*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3).f_inf_ZZ() q - 9/200*q^2 + 279/640000*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3).f_inf_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).f_inf_ZZ() q - 1/8*q^2 + 7/1024*q^3 + O(q^4) """ q = self._series_ring.gen() n = self.hecke_n() if (n == infinity): f_inf_ZZ = ((-q*self.J_inv_ZZ().derivative())**2/(self.J_inv_ZZ()**2*(self.J_inv_ZZ()-1))).power_series() else: temp_expr = ((-q*self.J_inv_ZZ().derivative())**(2*n)/(self.J_inv_ZZ()**(2*n-2)*(self.J_inv_ZZ()-1)**n)/q**(n-2)).power_series() f_inf_ZZ = (temp_expr.log()/(n-2)).exp()*q return f_inf_ZZ @cached_method def G_inv_ZZ(self): r""" Return the rational Fourier expansion of ``G_inv``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``G_inv`` for ``d!=1`` is given by ``d*G_inv_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(group=4, prec=3).G_inv_ZZ() q^-1 - 3/32 - 955/16384*q + O(q^2) sage: MFSeriesConstructor(group=8, prec=3).G_inv_ZZ() q^-1 - 15/128 - 15139/262144*q + O(q^2) sage: MFSeriesConstructor(group=8, prec=3).G_inv_ZZ().parent() Laurent Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).G_inv_ZZ() q^-1 - 1/8 - 59/1024*q + O(q^2) """ n = self.hecke_n() # Note that G_inv is not a weakly holomorphic form (because of the behavior at -1) if (n == infinity): q = self._series_ring.gen() temp_expr = (self.J_inv_ZZ()/self.f_inf_ZZ()*q**2).power_series() return 1/q*self.f_i_ZZ()*(temp_expr.log()/2).exp() elif (ZZ(2).divides(n)): return self.f_i_ZZ()*(self.f_rho_ZZ()**(ZZ(n/ZZ(2))))/self.f_inf_ZZ() else: #return self._qseries_ring([]) raise ValueError("G_inv doesn't exist for n={}.".format(self.hecke_n())) @cached_method def E4_ZZ(self): r""" Return the rational Fourier expansion of ``E_4``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``E4`` for ``d!=1`` is given by ``E4_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).E4_ZZ() 1 + 5/36*q + 5/6912*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E4_ZZ() 1 + 21/100*q + 483/32000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E4_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).E4_ZZ() 1 + 1/4*q + 7/256*q^2 + O(q^3) """ q = self._series_ring.gen() E4_ZZ = ((-q*self.J_inv_ZZ().derivative())**2/(self.J_inv_ZZ()*(self.J_inv_ZZ()-1))).power_series() return E4_ZZ @cached_method def E6_ZZ(self): r""" Return the rational Fourier expansion of ``E_6``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``E6`` for ``d!=1`` is given by ``E6_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).E6_ZZ() 1 - 7/24*q - 77/13824*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E6_ZZ() 1 - 37/200*q - 14663/320000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E6_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).E6_ZZ() 1 - 1/8*q - 31/512*q^2 + O(q^3) """ q = self._series_ring.gen() E6_ZZ = ((-q*self.J_inv_ZZ().derivative())**3/(self.J_inv_ZZ()**2*(self.J_inv_ZZ()-1))).power_series() return E6_ZZ @cached_method def Delta_ZZ(self): r""" Return the rational Fourier expansion of ``Delta``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``Delta`` for ``d!=1`` is given by ``d*Delta_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).Delta_ZZ() q - 1/72*q^2 + 7/82944*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3).Delta_ZZ() q + 47/200*q^2 + 11367/640000*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3).Delta_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).Delta_ZZ() q + 3/8*q^2 + 63/1024*q^3 + O(q^4) """ return (self.f_inf_ZZ()**3*self.J_inv_ZZ()**2/(self.f_rho_ZZ()**6)).power_series() @cached_method def E2_ZZ(self): r""" Return the rational Fourier expansion of ``E2``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``E2`` for ``d!=1`` is given by ``E2_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).E2_ZZ() 1 - 1/72*q - 1/41472*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E2_ZZ() 1 - 9/200*q - 369/320000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E2_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).E2_ZZ() 1 - 1/8*q - 1/512*q^2 + O(q^3) """ q = self._series_ring.gen() E2_ZZ = (q*self.f_inf_ZZ().derivative())/self.f_inf_ZZ() return E2_ZZ @cached_method def EisensteinSeries_ZZ(self, k): r""" Return the rational Fourier expansion of the normalized Eisenstein series of weight ``k``, where the parameter ``d`` is replaced by ``1``. Only arithmetic groups with ``n < infinity`` are supported! .. NOTE: THe Fourier expansion of the series is given by ``EisensteinSeries_ZZ(q/d)``. INPUT: - ``k`` -- A non-negative even integer, namely the weight. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFC = MFSeriesConstructor(prec=6) sage: MFC.EisensteinSeries_ZZ(k=0) 1 sage: MFC.EisensteinSeries_ZZ(k=2) 1 - 1/72*q - 1/41472*q^2 - 1/53747712*q^3 - 7/371504185344*q^4 - 1/106993205379072*q^5 + O(q^6) sage: MFC.EisensteinSeries_ZZ(k=6) 1 - 7/24*q - 77/13824*q^2 - 427/17915904*q^3 - 7399/123834728448*q^4 - 3647/35664401793024*q^5 + O(q^6) sage: MFC.EisensteinSeries_ZZ(k=12) 1 + 455/8292*q + 310765/4776192*q^2 + 20150585/6189944832*q^3 + 1909340615/42784898678784*q^4 + 3702799555/12322050819489792*q^5 + O(q^6) sage: MFC.EisensteinSeries_ZZ(k=12).parent() Power Series Ring in q over Rational Field sage: MFC = MFSeriesConstructor(group=4, prec=5) sage: MFC.EisensteinSeries_ZZ(k=2) 1 - 1/32*q - 5/8192*q^2 - 1/524288*q^3 - 13/536870912*q^4 + O(q^5) sage: MFC.EisensteinSeries_ZZ(k=4) 1 + 3/16*q + 39/4096*q^2 + 21/262144*q^3 + 327/268435456*q^4 + O(q^5) sage: MFC.EisensteinSeries_ZZ(k=6) 1 - 7/32*q - 287/8192*q^2 - 427/524288*q^3 - 9247/536870912*q^4 + O(q^5) sage: MFC.EisensteinSeries_ZZ(k=12) 1 + 63/11056*q + 133119/2830336*q^2 + 2790081/181141504*q^3 + 272631807/185488900096*q^4 + O(q^5) sage: MFC = MFSeriesConstructor(group=6, prec=5) sage: MFC.EisensteinSeries_ZZ(k=2) 1 - 1/18*q - 1/648*q^2 - 7/209952*q^3 - 7/22674816*q^4 + O(q^5) sage: MFC.EisensteinSeries_ZZ(k=4) 1 + 2/9*q + 1/54*q^2 + 37/52488*q^3 + 73/5668704*q^4 + O(q^5) sage: MFC.EisensteinSeries_ZZ(k=6) 1 - 1/6*q - 11/216*q^2 - 271/69984*q^3 - 1057/7558272*q^4 + O(q^5) sage: MFC.EisensteinSeries_ZZ(k=12) 1 + 182/151329*q + 62153/2723922*q^2 + 16186807/882550728*q^3 + 381868123/95315478624*q^4 + O(q^5) """ try: if k < 0: raise TypeError(None) k = 2*ZZ(k/2) except TypeError: raise TypeError("k={} has to be a non-negative even integer!".format(k)) if (not self.group().is_arithmetic() or self.group().n() == infinity): # Exceptional cases should be called manually (see in FormsRing_abstract) raise NotImplementedError("Eisenstein series are only supported in the finite arithmetic cases!") # Trivial case if k == 0: return self._series_ring(1) M = ZZ(self.group().lam()**2) lamk = M**(ZZ(k/2)) dval = self.group().dvalue() def coeff(m): m = ZZ(m) if m < 0: return ZZ(0) elif m == 0: return ZZ(1) factor = -2*k / QQ(bernoulli(k)) / lamk sum1 = sigma(m, k-1) if M.divides(m): sum2 = (lamk-1) * sigma(ZZ(m/M), k-1) else: sum2 = ZZ(0) if (M == 1): sum3 = ZZ(0) else: if (m == 1): N = ZZ(1) else: N = ZZ(m / M**ZZ(m.valuation(M))) sum3 = -sigma(ZZ(N), k-1) * ZZ(m/N)**(k-1) / (lamk + 1) return factor * (sum1 + sum2 + sum3) * dval**m q = self._series_ring.gen() return sum([coeff(m)*q**m for m in range(self.prec())]).add_bigoh(self.prec())
class MFSeriesConstructor(SageObject, UniqueRepresentation): r""" Constructor for the Fourier expansion of some (specific, basic) modular forms. The constructor is used by forms elements in case their Fourier expansion is needed or requested. """ @staticmethod def __classcall__(cls, group=HeckeTriangleGroup(3), prec=ZZ(10)): r""" Return a (cached) instance with canonical parameters. .. NOTE: For each choice of group and precision the constructor is cached (only) once. Further calculations with different base rings and possibly numerical parameters are based on the same cached instance. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor() == MFSeriesConstructor(3, 10) True sage: MFSeriesConstructor(group=4).hecke_n() 4 sage: MFSeriesConstructor(group=5, prec=12).prec() 12 """ if (group == infinity): group = HeckeTriangleGroup(infinity) else: try: group = HeckeTriangleGroup(ZZ(group)) except TypeError: group = HeckeTriangleGroup(group.n()) prec = ZZ(prec) # We don't need this assumption the precision may in principle also be negative. # if (prec<1): # raise Exception("prec must be an Integer >=1") return super(MFSeriesConstructor, cls).__classcall__(cls, group, prec) def __init__(self, group, prec): r""" Constructor for the Fourier expansion of some (specific, basic) modular forms. INPUT: - ``group`` -- A Hecke triangle group (default: HeckeTriangleGroup(3)). - ``prec`` -- An integer (default: 10), the default precision used in calculations in the LaurentSeriesRing or PowerSeriesRing. OUTPUT: The constructor for Fourier expansion with the specified settings. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFC = MFSeriesConstructor() sage: MFC Power series constructor for Hecke modular forms for n=3 with (basic series) precision 10 sage: MFC.group() Hecke triangle group for n = 3 sage: MFC.prec() 10 sage: MFC._series_ring Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=4) Power series constructor for Hecke modular forms for n=4 with (basic series) precision 10 sage: MFSeriesConstructor(group=5, prec=12) Power series constructor for Hecke modular forms for n=5 with (basic series) precision 12 sage: MFSeriesConstructor(group=infinity) Power series constructor for Hecke modular forms for n=+Infinity with (basic series) precision 10 """ self._group = group self._prec = prec self._series_ring = PowerSeriesRing(QQ, 'q', default_prec=self._prec) def _repr_(self): r""" Return the string representation of ``self``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(group=4) Power series constructor for Hecke modular forms for n=4 with (basic series) precision 10 sage: MFSeriesConstructor(group=5, prec=12) Power series constructor for Hecke modular forms for n=5 with (basic series) precision 12 """ return "Power series constructor for Hecke modular forms for n={} with (basic series) precision {}".\ format(self._group.n(), self._prec) def group(self): r""" Return the (Hecke triangle) group of ``self``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(group=4).group() Hecke triangle group for n = 4 """ return self._group def hecke_n(self): r""" Return the parameter ``n`` of the (Hecke triangle) group of ``self``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(group=4).hecke_n() 4 """ return self._group.n() def prec(self): r""" Return the used default precision for the PowerSeriesRing or LaurentSeriesRing. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(group=5).prec() 10 sage: MFSeriesConstructor(group=5, prec=20).prec() 20 """ return self._prec @cached_method def J_inv_ZZ(self): r""" Return the rational Fourier expansion of ``J_inv``, where the parameter ``d`` is replaced by ``1``. This is the main function used to determine all Fourier expansions! .. NOTE: The Fourier expansion of ``J_inv`` for ``d!=1`` is given by ``J_inv_ZZ(q/d)``. .. TODO: The functions that are used in this implementation are products of hypergeometric series with other, elementary, functions. Implement them and clean up this representation. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).J_inv_ZZ() q^-1 + 31/72 + 1823/27648*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3).J_inv_ZZ() q^-1 + 79/200 + 42877/640000*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3).J_inv_ZZ().parent() Laurent Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).J_inv_ZZ() q^-1 + 3/8 + 69/1024*q + O(q^2) """ F1 = lambda a, b: self._series_ring([ZZ(0)] + [ rising_factorial(a, k) * rising_factorial(b, k) / (ZZ(k).factorial())**2 * sum( ZZ(1) / (a + j) + ZZ(1) / (b + j) - ZZ(2) / ZZ(1 + j) for j in range(ZZ(0), ZZ(k))) for k in range(ZZ(1), ZZ(self._prec + 1)) ], ZZ(self._prec + 1)) F = lambda a, b, c: self._series_ring([ rising_factorial(a, k) * rising_factorial(b, k) / rising_factorial( c, k) / ZZ(k).factorial() for k in range(ZZ(0), ZZ(self._prec + 1)) ], ZZ(self._prec + 1)) a = self._group.alpha() b = self._group.beta() Phi = F1(a, b) / F(a, b, ZZ(1)) q = self._series_ring.gen() # the current implementation of power series reversion is slow # J_inv_ZZ = ZZ(1) / ((q*Phi.exp()).reverse()) temp_f = (q * Phi.exp()).polynomial() new_f = temp_f.revert_series(temp_f.degree() + 1) J_inv_ZZ = ZZ(1) / (new_f + O(q**(temp_f.degree() + 1))) return J_inv_ZZ @cached_method def f_rho_ZZ(self): r""" Return the rational Fourier expansion of ``f_rho``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``f_rho`` for ``d!=1`` is given by ``f_rho_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).f_rho_ZZ() 1 + 5/36*q + 5/6912*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).f_rho_ZZ() 1 + 7/100*q + 21/160000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).f_rho_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).f_rho_ZZ() 1 """ q = self._series_ring.gen() n = self.hecke_n() if (n == infinity): f_rho_ZZ = self._series_ring(1) else: temp_expr = ((-q * self.J_inv_ZZ().derivative())**2 / (self.J_inv_ZZ() * (self.J_inv_ZZ() - 1))).power_series() f_rho_ZZ = (temp_expr.log() / (n - 2)).exp() return f_rho_ZZ @cached_method def f_i_ZZ(self): r""" Return the rational Fourier expansion of ``f_i``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``f_i`` for ``d!=1`` is given by ``f_i_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).f_i_ZZ() 1 - 7/24*q - 77/13824*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).f_i_ZZ() 1 - 13/40*q - 351/64000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).f_i_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).f_i_ZZ() 1 - 3/8*q + 3/512*q^2 + O(q^3) """ q = self._series_ring.gen() n = self.hecke_n() if (n == infinity): f_i_ZZ = (-q * self.J_inv_ZZ().derivative() / self.J_inv_ZZ()).power_series() else: temp_expr = ((-q * self.J_inv_ZZ().derivative())**n / (self.J_inv_ZZ()**(n - 1) * (self.J_inv_ZZ() - 1))).power_series() f_i_ZZ = (temp_expr.log() / (n - 2)).exp() return f_i_ZZ @cached_method def f_inf_ZZ(self): r""" Return the rational Fourier expansion of ``f_inf``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``f_inf`` for ``d!=1`` is given by ``d*f_inf_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).f_inf_ZZ() q - 1/72*q^2 + 7/82944*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3).f_inf_ZZ() q - 9/200*q^2 + 279/640000*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3).f_inf_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).f_inf_ZZ() q - 1/8*q^2 + 7/1024*q^3 + O(q^4) """ q = self._series_ring.gen() n = self.hecke_n() if (n == infinity): f_inf_ZZ = ((-q * self.J_inv_ZZ().derivative())**2 / (self.J_inv_ZZ()**2 * (self.J_inv_ZZ() - 1))).power_series() else: temp_expr = ((-q * self.J_inv_ZZ().derivative())**(2 * n) / (self.J_inv_ZZ()**(2 * n - 2) * (self.J_inv_ZZ() - 1)**n) / q**(n - 2)).power_series() f_inf_ZZ = (temp_expr.log() / (n - 2)).exp() * q return f_inf_ZZ @cached_method def G_inv_ZZ(self): r""" Return the rational Fourier expansion of ``G_inv``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``G_inv`` for ``d!=1`` is given by ``d*G_inv_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(group=4, prec=3).G_inv_ZZ() q^-1 - 3/32 - 955/16384*q + O(q^2) sage: MFSeriesConstructor(group=8, prec=3).G_inv_ZZ() q^-1 - 15/128 - 15139/262144*q + O(q^2) sage: MFSeriesConstructor(group=8, prec=3).G_inv_ZZ().parent() Laurent Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).G_inv_ZZ() q^-1 - 1/8 - 59/1024*q + O(q^2) """ n = self.hecke_n() # Note that G_inv is not a weakly holomorphic form (because of the behavior at -1) if (n == infinity): q = self._series_ring.gen() temp_expr = (self.J_inv_ZZ() / self.f_inf_ZZ() * q**2).power_series() return 1 / q * self.f_i_ZZ() * (temp_expr.log() / 2).exp() elif (ZZ(2).divides(n)): return self.f_i_ZZ() * (self.f_rho_ZZ()**(ZZ( n / ZZ(2)))) / self.f_inf_ZZ() else: #return self._qseries_ring([]) raise ValueError("G_inv doesn't exist for n={}.".format( self.hecke_n())) @cached_method def E4_ZZ(self): r""" Return the rational Fourier expansion of ``E_4``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``E4`` for ``d!=1`` is given by ``E4_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).E4_ZZ() 1 + 5/36*q + 5/6912*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E4_ZZ() 1 + 21/100*q + 483/32000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E4_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).E4_ZZ() 1 + 1/4*q + 7/256*q^2 + O(q^3) """ q = self._series_ring.gen() E4_ZZ = ((-q * self.J_inv_ZZ().derivative())**2 / (self.J_inv_ZZ() * (self.J_inv_ZZ() - 1))).power_series() return E4_ZZ @cached_method def E6_ZZ(self): r""" Return the rational Fourier expansion of ``E_6``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``E6`` for ``d!=1`` is given by ``E6_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).E6_ZZ() 1 - 7/24*q - 77/13824*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E6_ZZ() 1 - 37/200*q - 14663/320000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E6_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).E6_ZZ() 1 - 1/8*q - 31/512*q^2 + O(q^3) """ q = self._series_ring.gen() E6_ZZ = ((-q * self.J_inv_ZZ().derivative())**3 / (self.J_inv_ZZ()**2 * (self.J_inv_ZZ() - 1))).power_series() return E6_ZZ @cached_method def Delta_ZZ(self): r""" Return the rational Fourier expansion of ``Delta``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``Delta`` for ``d!=1`` is given by ``d*Delta_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).Delta_ZZ() q - 1/72*q^2 + 7/82944*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3).Delta_ZZ() q + 47/200*q^2 + 11367/640000*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3).Delta_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).Delta_ZZ() q + 3/8*q^2 + 63/1024*q^3 + O(q^4) """ return (self.f_inf_ZZ()**3 * self.J_inv_ZZ()**2 / (self.f_rho_ZZ()**6)).power_series() @cached_method def E2_ZZ(self): r""" Return the rational Fourier expansion of ``E2``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``E2`` for ``d!=1`` is given by ``E2_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).E2_ZZ() 1 - 1/72*q - 1/41472*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E2_ZZ() 1 - 9/200*q - 369/320000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E2_ZZ().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).E2_ZZ() 1 - 1/8*q - 1/512*q^2 + O(q^3) """ q = self._series_ring.gen() E2_ZZ = (q * self.f_inf_ZZ().derivative()) / self.f_inf_ZZ() return E2_ZZ @cached_method def EisensteinSeries_ZZ(self, k): r""" Return the rational Fourier expansion of the normalized Eisenstein series of weight ``k``, where the parameter ``d`` is replaced by ``1``. Only arithmetic groups with ``n < infinity`` are supported! .. NOTE: THe Fourier expansion of the series is given by ``EisensteinSeries_ZZ(q/d)``. INPUT: - ``k`` -- A non-negative even integer, namely the weight. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFC = MFSeriesConstructor(prec=6) sage: MFC.EisensteinSeries_ZZ(k=0) 1 sage: MFC.EisensteinSeries_ZZ(k=2) 1 - 1/72*q - 1/41472*q^2 - 1/53747712*q^3 - 7/371504185344*q^4 - 1/106993205379072*q^5 + O(q^6) sage: MFC.EisensteinSeries_ZZ(k=6) 1 - 7/24*q - 77/13824*q^2 - 427/17915904*q^3 - 7399/123834728448*q^4 - 3647/35664401793024*q^5 + O(q^6) sage: MFC.EisensteinSeries_ZZ(k=12) 1 + 455/8292*q + 310765/4776192*q^2 + 20150585/6189944832*q^3 + 1909340615/42784898678784*q^4 + 3702799555/12322050819489792*q^5 + O(q^6) sage: MFC.EisensteinSeries_ZZ(k=12).parent() Power Series Ring in q over Rational Field sage: MFC = MFSeriesConstructor(group=4, prec=5) sage: MFC.EisensteinSeries_ZZ(k=2) 1 - 1/32*q - 5/8192*q^2 - 1/524288*q^3 - 13/536870912*q^4 + O(q^5) sage: MFC.EisensteinSeries_ZZ(k=4) 1 + 3/16*q + 39/4096*q^2 + 21/262144*q^3 + 327/268435456*q^4 + O(q^5) sage: MFC.EisensteinSeries_ZZ(k=6) 1 - 7/32*q - 287/8192*q^2 - 427/524288*q^3 - 9247/536870912*q^4 + O(q^5) sage: MFC.EisensteinSeries_ZZ(k=12) 1 + 63/11056*q + 133119/2830336*q^2 + 2790081/181141504*q^3 + 272631807/185488900096*q^4 + O(q^5) sage: MFC = MFSeriesConstructor(group=6, prec=5) sage: MFC.EisensteinSeries_ZZ(k=2) 1 - 1/18*q - 1/648*q^2 - 7/209952*q^3 - 7/22674816*q^4 + O(q^5) sage: MFC.EisensteinSeries_ZZ(k=4) 1 + 2/9*q + 1/54*q^2 + 37/52488*q^3 + 73/5668704*q^4 + O(q^5) sage: MFC.EisensteinSeries_ZZ(k=6) 1 - 1/6*q - 11/216*q^2 - 271/69984*q^3 - 1057/7558272*q^4 + O(q^5) sage: MFC.EisensteinSeries_ZZ(k=12) 1 + 182/151329*q + 62153/2723922*q^2 + 16186807/882550728*q^3 + 381868123/95315478624*q^4 + O(q^5) """ try: if k < 0: raise TypeError(None) k = 2 * ZZ(k / 2) except TypeError: raise TypeError( "k={} has to be a non-negative even integer!".format(k)) if (not self.group().is_arithmetic() or self.group().n() == infinity): # Exceptional cases should be called manually (see in FormsRing_abstract) raise NotImplementedError( "Eisenstein series are only supported in the finite arithmetic cases!" ) # Trivial case if k == 0: return self._series_ring(1) M = ZZ(self.group().lam()**2) lamk = M**(ZZ(k / 2)) dval = self.group().dvalue() def coeff(m): m = ZZ(m) if m < 0: return ZZ(0) elif m == 0: return ZZ(1) factor = -2 * k / QQ(bernoulli(k)) / lamk sum1 = sigma(m, k - 1) if M.divides(m): sum2 = (lamk - 1) * sigma(ZZ(m / M), k - 1) else: sum2 = ZZ(0) if (M == 1): sum3 = ZZ(0) else: if (m == 1): N = ZZ(1) else: N = ZZ(m / M**ZZ(m.valuation(M))) sum3 = -sigma(ZZ(N), k - 1) * ZZ(m / N)**(k - 1) / (lamk + 1) return factor * (sum1 + sum2 + sum3) * dval**m q = self._series_ring.gen() return sum([coeff(m) * q**m for m in range(self.prec())]).add_bigoh(self.prec())
def series(self, n=2, quadratic_twist=+1, prec=5): r""" Returns the `n`-th approximation to the `p`-adic L-series as a power series in `T` (corresponding to `\gamma-1` with `\gamma=1+p` as a generator of `1+p\ZZ_p`). Each coefficient is a `p`-adic number whose precision is provably correct. Here the normalization of the `p`-adic L-series is chosen such that `L_p(J,1) = (1-1/\alpha)^2 L(J,1)/\Omega_J` where `\alpha` is the unit root INPUT: - ``n`` - (default: 2) a positive integer - ``quadratic_twist`` - (default: +1) a fundamental discriminant of a quadratic field, coprime to the conductor of the curve - ``prec`` - (default: 5) maximal number of terms of the series to compute; to compute as many as possible just give a very large number for ``prec``; the result will still be correct. ALIAS: power_series is identical to series. EXAMPLES: sage: J = J0(188)[0] sage: p = 7 sage: L = J.padic_lseries(p) sage: L.is_ordinary() True sage: f = L.series(2) sage: f[0] O(7^20) sage: f[1].norm() 3 + 4*7 + 3*7^2 + 6*7^3 + 5*7^4 + 5*7^5 + 6*7^6 + 4*7^7 + 5*7^8 + 7^10 + 5*7^11 + 4*7^13 + 4*7^14 + 5*7^15 + 2*7^16 + 5*7^17 + 7^18 + 7^19 + O(7^20) """ n = ZZ(n) if n < 1: raise ValueError, "n (=%s) must be a positive integer"%n if not self.is_ordinary(): raise ValueError, "p (=%s) must be an ordinary prime"%p # check if the conditions on quadratic_twist are satisfied D = ZZ(quadratic_twist) if D != 1: if D % 4 == 0: d = D//4 if not d.is_squarefree() or d % 4 == 1: raise ValueError, "quadratic_twist (=%s) must be a fundamental discriminant of a quadratic field"%D else: if not D.is_squarefree() or D % 4 != 1: raise ValueError, "quadratic_twist (=%s) must be a fundamental discriminant of a quadratic field"%D if gcd(D,self._p) != 1: raise ValueError, "quadratic twist (=%s) must be coprime to p (=%s) "%(D,self._p) if gcd(D,self._E.conductor())!= 1: for ell in prime_divisors(D): if valuation(self._E.conductor(),ell) > valuation(D,ell) : raise ValueError, "can not twist a curve of conductor (=%s) by the quadratic twist (=%s)."%(self._E.conductor(),D) p = self._p if p == 2 and self._normalize : print 'Warning : For p=2 the normalization might not be correct !' #verbose("computing L-series for p=%s, n=%s, and prec=%s"%(p,n,prec)) # bounds = self._prec_bounds(n,prec) # padic_prec = max(bounds[1:]) + 5 padic_prec = 10 # verbose("using p-adic precision of %s"%padic_prec) res_series_prec = min(p**(n-1), prec) verbose("using series precision of %s"%res_series_prec) ans = self._get_series_from_cache(n, res_series_prec,D) if not ans is None: verbose("found series in cache") return ans K = QQ gamma = K(1 + p) R = PowerSeriesRing(K,'T',res_series_prec) T = R(R.gen(),res_series_prec ) #L = R(0) one_plus_T_factor = R(1) gamma_power = K(1) teich = self.teichmuller(padic_prec) p_power = p**(n-1) # F = Qp(p,padic_prec) verbose("Now iterating over %s summands"%((p-1)*p_power)) verbose_level = get_verbose() count_verb = 0 alphas = self.alpha() #print len(alphas) Lprod = [] self._emb = 0 if len(alphas) == 2: split = True else: split = False for alpha in alphas: L = R(0) self._emb = self._emb + 1 for j in range(p_power): s = K(0) if verbose_level >= 2 and j/p_power*100 > count_verb + 3: verbose("%.2f percent done"%(float(j)/p_power*100)) count_verb += 3 for a in range(1,p): if split: # b = ((F.teichmuller(a)).lift() % ZZ(p**n)) b = (teich[a]) % ZZ(p**n) b = b*gamma_power else: b = teich[a] * gamma_power s += self.measure(b, n, padic_prec,D,alpha) L += s * one_plus_T_factor one_plus_T_factor *= 1+T gamma_power *= gamma Lprod = Lprod + [L] if len(Lprod)==1: return Lprod[0] else: return Lprod[0]*Lprod[1]
class MFSeriesConstructor(SageObject,UniqueRepresentation): r""" Constructor for the Fourier expansion of some (specific, basic) modular forms. The constructor is used by forms elements in case their Fourier expansion is needed or requested. """ @staticmethod def __classcall__(cls, group = HeckeTriangleGroup(3), base_ring = ZZ, prec=ZZ(10), fix_d=False, set_d=None, d_num_prec=ZZ(53)): r""" Return a (cached) instance with canonical parameters. In particular in case ``fix_d = True`` or if ``set_d`` is set then the ``base_ring`` is replaced by the common parent of ``base_ring`` and the parent of ``set_d`` (resp. the numerical value of ``d`` in case ``fix_d=True``). EXAMPLES:: sage: MFSeriesConstructor() == MFSeriesConstructor(3, ZZ, 10, False, None, 53) True sage: MFSeriesConstructor(base_ring = CC, set_d=CC(1)) == MFSeriesConstructor(set_d=CC(1)) True sage: MFSeriesConstructor(group=4, fix_d=True).base_ring() == QQ True sage: MFSeriesConstructor(group=5, fix_d=True).base_ring() == RR True """ if (group==infinity): group = HeckeTriangleGroup(infinity) else: try: group = HeckeTriangleGroup(ZZ(group)) except TypeError: group = HeckeTriangleGroup(group.n()) prec=ZZ(prec) #if (prec<1): # raise Exception("prec must be an Integer >=1") fix_d = bool(fix_d) if (fix_d): n = group.n() d = group.dvalue() if (group.is_arithmetic()): d_num_prec = None set_d = 1/base_ring(1/d) else: d_num_prec = ZZ(d_num_prec) set_d = group.dvalue().n(d_num_prec) else: d_num_prec = None if (set_d is not None): base_ring=(base_ring(1)*set_d).parent() #elif (not base_ring.is_exact()): # raise NotImplementedError return super(MFSeriesConstructor,cls).__classcall__(cls, group, base_ring, prec, fix_d, set_d, d_num_prec) def __init__(self, group, base_ring, prec, fix_d, set_d, d_num_prec): r""" Constructor for the Fourier expansion of some (specific, basic) modular forms. INPUT: - ``group`` - A Hecke triangle group (default: HeckeTriangleGroup(3)). - ``base_ring`` - The base ring (default: ZZ) - ``prec`` - An integer (default: 10), the default precision used in calculations in the LaurentSeriesRing or PowerSeriesRing. - ``fix_d`` - ``True`` or ``False`` (default: ``False``). If ``fix_d == False`` the base ring of the power series is (the fraction field) of the polynomial ring over the base ring in one formal parameter ``d``. If ``fix_d == True`` the formal parameter ``d`` is replaced by its numerical value with numerical precision at least ``d_num_prec`` (or exact in case n=3, 4, 6). The base ring of the PowerSeriesRing or LaurentSeriesRing is changed to a common parent of ``base_ring`` and the parent of the mentioned value ``d``. - ``set_d`` - A number which replaces the formal parameter ``d``. The base ring of the PowerSeriesRing or LaurentSeriesRing is changed to a common parent of ``base_ring`` and the parent of the specified value for ``d``. Note that in particular ``set_d=1`` will produce rational Fourier expansions. - ``d_num_prec`` - An integer, a lower bound for the precision of the numerical value of ``d``. OUTPUT: The constructor for Fourier expansion with the specified settings. EXAMPLES:: sage: MFC = MFSeriesConstructor() sage: MFC Power series constructor for Hecke modular forms for n=3, base ring=Integer Ring with (basic series) precision 10 with formal parameter d sage: MFC.group() Hecke triangle group for n = 3 sage: MFC.prec() 10 sage: MFC.d().parent() Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFC._ZZseries_ring Power Series Ring in q over Rational Field sage: MFSeriesConstructor(set_d=CC(1)) Power series constructor for Hecke modular forms for n=3, base ring=Complex Field with 53 bits of precision with (basic series) precision 10 with parameter d=1.00000000000000 sage: MFSeriesConstructor(group=4, fix_d=True) Power series constructor for Hecke modular forms for n=4, base ring=Rational Field with (basic series) precision 10 with parameter d=1/256 sage: MFSeriesConstructor(group=5, fix_d=True) Power series constructor for Hecke modular forms for n=5, base ring=Real Field with 53 bits of precision with (basic series) precision 10 with parameter d=0.00705223418128563 """ self._group = group self._base_ring = base_ring self._prec = prec self._fix_d = fix_d self._set_d = set_d self._d_num_prec = d_num_prec if (set_d): self._coeff_ring = FractionField(base_ring) self._d = set_d else: self._coeff_ring = FractionField(PolynomialRing(base_ring,"d")) self._d = self._coeff_ring.gen() self._ZZseries_ring = PowerSeriesRing(QQ,'q',default_prec=self._prec) self._qseries_ring = PowerSeriesRing(self._coeff_ring,'q',default_prec=self._prec) def _repr_(self): r""" Return the string representation of ``self``. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True) Power series constructor for Hecke modular forms for n=4, base ring=Rational Field with (basic series) precision 10 with parameter d=1/256 sage: MFSeriesConstructor(group=5) Power series constructor for Hecke modular forms for n=5, base ring=Integer Ring with (basic series) precision 10 with formal parameter d """ if (self._set_d): return "Power series constructor for Hecke modular forms for n={}, base ring={} with (basic series) precision {} with parameter d={}".\ format(self._group.n(), self._base_ring, self._prec, self._d) else: return "Power series constructor for Hecke modular forms for n={}, base ring={} with (basic series) precision {} with formal parameter d".\ format(self._group.n(), self._base_ring, self._prec) def group(self): r""" Return the (Hecke triangle) group of ``self``. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).group() Hecke triangle group for n = 4 """ return self._group def hecke_n(self): r""" Return the parameter ``n`` of the (Hecke triangle) group of ``self``. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).hecke_n() 4 """ return self._group.n() def base_ring(self): r""" Return base ring of ``self``. EXAMPLES:: sage: MFSeriesConstructor(group=5, fix_d=True).base_ring() Real Field with 53 bits of precision sage: MFSeriesConstructor(group=5, fix_d=True, d_num_prec=100).base_ring() Real Field with 100 bits of precision """ return self._base_ring def prec(self): r""" Return the used default precision for the PowerSeriesRing or LaurentSeriesRing. EXAMPLES:: sage: MFSeriesConstructor(group=5, fix_d=True).prec() 10 sage: MFSeriesConstructor(group=5, prec=20).prec() 20 """ return self._prec def fix_d(self): r""" Return whether the numerical value for the parameter ``d`` will be substituted or not. Note: Depending on whether ``set_d`` is ``None`` or not ``d`` might still be substituted despite ``fix_d`` being ``False``. EXAMPLES:: sage: MFSeriesConstructor(group=5, fix_d=True, set_d=1).fix_d() True sage: MFSeriesConstructor(group=5, fix_d=True, set_d=1).set_d() 0.00705223418128563 sage: MFSeriesConstructor(group=5, set_d=1).fix_d() False """ return self._fix_d def set_d(self): r""" Return the numerical value which is substituted for the parameter ``d``. Default: ``None``, meaning the formal parameter ``d`` is used. EXAMPLES:: sage: MFSeriesConstructor(group=5, fix_d=True, set_d=1).set_d() 0.00705223418128563 sage: MFSeriesConstructor(group=5, set_d=1).set_d() 1 sage: MFSeriesConstructor(group=5, set_d=1).set_d().parent() Integer Ring """ return self._set_d def is_exact(self): r""" Return whether used ``base_ring`` is exact. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).is_exact() True sage: MFSeriesConstructor(group=5, fix_d=True).is_exact() False sage: MFSeriesConstructor(group=5, set_d=1).is_exact() True """ return self._base_ring.is_exact() def d(self): r""" Return the formal parameter ``d`` respectively its (possibly numerical) value in case ``set_d`` is not ``None``. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).d() 1/256 sage: MFSeriesConstructor(group=4).d() d sage: MFSeriesConstructor(group=4).d().parent() Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, fix_d=True).d() 0.00705223418128563 sage: MFSeriesConstructor(group=5, set_d=1).d() 1 """ return self._d def q(self): r""" Return the generator of the used PowerSeriesRing. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).q() q sage: MFSeriesConstructor(group=4, fix_d=True).q().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=5, fix_d=True).q().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self._qseries_ring.gen() def coeff_ring(self): r""" Return coefficient ring of ``self``. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).coeff_ring() Rational Field sage: MFSeriesConstructor(group=4).coeff_ring() Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, fix_d=True).coeff_ring() Real Field with 53 bits of precision sage: MFSeriesConstructor(group=5).coeff_ring() Fraction Field of Univariate Polynomial Ring in d over Integer Ring """ return self._coeff_ring def qseries_ring(self): r""" Return the used PowerSeriesRing. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).qseries_ring() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=4).qseries_ring() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, fix_d=True).qseries_ring() Power Series Ring in q over Real Field with 53 bits of precision sage: MFSeriesConstructor(group=5).qseries_ring() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring """ return self._qseries_ring @cached_method def J_inv_ZZ(self): r""" Return the rational Fourier expansion of ``J_inv``, where ``d`` is replaced by ``1``. This is the main function used to determine all Fourier expansions! EXAMPLES:: sage: MFSeriesConstructor(prec=3).J_inv_ZZ() q^-1 + 31/72 + 1823/27648*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).J_inv_ZZ() q^-1 + 79/200 + 42877/640000*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).J_inv_ZZ().parent() Laurent Series Ring in q over Rational Field """ F1 = lambda a,b: self._ZZseries_ring(\ [ ZZ(0) ] + [\ rising_factorial(a,k) * rising_factorial(b,k) / (ZZ(k).factorial())**2 * sum([\ ZZ(1)/(a+j)+ZZ(1)/(b+j)-ZZ(2)/ZZ(1+j) for j in range(ZZ(0),ZZ(k))\ ]) for k in range(ZZ(1),ZZ(self._prec+1)) ], ZZ(self._prec+1)\ ) F = lambda a,b,c: self._ZZseries_ring([\ rising_factorial(a,k) * rising_factorial(b,k) / rising_factorial(c,k) / (ZZ(k).factorial())\ for k in range(ZZ(0),ZZ(self._prec+1))\ ], ZZ(self._prec+1)) a = self._group.alpha() b = self._group.beta() Phi = F1(a,b) / F(a,b,ZZ(1)) q = self._ZZseries_ring.gen() J_inv_ZZ = ZZ(1) / ((q*Phi.exp()).reversion()) return J_inv_ZZ @cached_method def J_inv(self): r""" Return the Fourier expansion of ``J_inv``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).J_inv() 1/1728*q^-1 + 31/72 + 1823/16*q + O(q^2) sage: MFSeriesConstructor(prec=3).J_inv_ZZ() == MFSeriesConstructor(prec=3, set_d=1).J_inv() True sage: MFSeriesConstructor(group=5, prec=3).J_inv() d*q^-1 + 79/200 + 42877/(640000*d)*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).J_inv() 0.00705223418128563*q^-1 + 0.395000000000000 + 9.49987064777062*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3).J_inv().parent() Laurent Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).J_inv().parent() Laurent Series Ring in q over Real Field with 53 bits of precision """ return self.J_inv_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def F_rho_ZZ(self): r""" Return the rational Fourier expansion of ``F_rho``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).F_rho_ZZ() 1 + 5/36*q + 5/6912*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_rho_ZZ() 1 + 7/100*q + 21/160000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_rho_ZZ().parent() Power Series Ring in q over Rational Field """ q = self._ZZseries_ring.gen() n = self.hecke_n() temp_expr = ((-q*self.J_inv_ZZ().derivative())**2/(self.J_inv_ZZ()*(self.J_inv_ZZ()-1))).power_series() F_rho_ZZ = (temp_expr.log()/(n-2)).exp() return F_rho_ZZ @cached_method def F_rho(self): r""" Return the Fourier expansion of ``F_rho``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).F_rho() 1 + 240*q + 2160*q^2 + O(q^3) sage: MFSeriesConstructor(prec=3).F_rho_ZZ() == MFSeriesConstructor(prec=3, set_d=1).F_rho() True sage: MFSeriesConstructor(group=5, prec=3).F_rho() 1 + 7/(100*d)*q + 21/(160000*d^2)*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_rho() 1.00000000000000 + 9.92593243510795*q + 2.63903932249093*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).F_rho().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_rho().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self.F_rho_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def F_i_ZZ(self): r""" Return the rational Fourier expansion of ``F_i``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).F_i_ZZ() 1 - 7/24*q - 77/13824*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_i_ZZ() 1 - 13/40*q - 351/64000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_i_ZZ().parent() Power Series Ring in q over Rational Field """ q = self._ZZseries_ring.gen() n = self.hecke_n() temp_expr = ((-q*self.J_inv_ZZ().derivative())**n/(self.J_inv_ZZ()**(n-1)*(self.J_inv_ZZ()-1))).power_series() F_i_ZZ = (temp_expr.log()/(n-2)).exp() return F_i_ZZ @cached_method def F_i(self): r""" Return the Fourier expansion of ``F_i``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).F_i() 1 - 504*q - 16632*q^2 + O(q^3) sage: MFSeriesConstructor(prec=3).F_i_ZZ() == MFSeriesConstructor(prec=3, set_d=1).F_i() True sage: MFSeriesConstructor(group=5, prec=3).F_i() 1 - 13/(40*d)*q - 351/(64000*d^2)*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_i() 1.00000000000000 - 46.0846863058583*q - 110.274143118371*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).F_i().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_i().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self.F_i_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def F_inf_ZZ(self): r""" Return the rational Fourier expansion of ``F_inf``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).F_inf_ZZ() q - 1/72*q^2 + 7/82944*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_inf_ZZ() q - 9/200*q^2 + 279/640000*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_inf_ZZ().parent() Power Series Ring in q over Rational Field """ q = self._ZZseries_ring.gen() n = self.hecke_n() temp_expr = ((-q*self.J_inv_ZZ().derivative())**(2*n)/(self.J_inv_ZZ()**(2*n-2)*(self.J_inv_ZZ()-1)**n)/q**(n-2)).power_series() F_inf_ZZ = (temp_expr.log()/(n-2)).exp()*q return F_inf_ZZ @cached_method def F_inf(self): r""" Return the Fourier expansion of ``F_inf``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).F_inf() q - 24*q^2 + 252*q^3 + O(q^4) sage: MFSeriesConstructor(prec=3).F_inf_ZZ() == MFSeriesConstructor(prec=3, set_d=1).F_inf() True sage: MFSeriesConstructor(group=5, prec=3).F_inf() q - 9/(200*d)*q^2 + 279/(640000*d^2)*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_inf() 0.000000000000000 + 1.00000000000000*q - 6.38095656542654*q^2 + 8.76538060684488*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3).F_inf().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_inf().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self._d*self.F_inf_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def G_inv_ZZ(self): r""" Return the rational Fourier expansion of ``G_inv``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(group=4, prec=3).G_inv_ZZ() q^-1 - 3/32 - 955/16384*q + O(q^2) sage: MFSeriesConstructor(group=8, prec=3, fix_d=True).G_inv_ZZ() q^-1 - 15/128 - 15139/262144*q + O(q^2) sage: MFSeriesConstructor(group=8, prec=3, fix_d=True).G_inv_ZZ().parent() Laurent Series Ring in q over Rational Field """ n = self.hecke_n() if (ZZ(2).divides(n)): return self.F_i_ZZ()*(self.F_rho_ZZ()**(ZZ(n/ZZ(2))))/self.F_inf_ZZ() else: #return self._qseries_ring([]) raise Exception("G_inv doesn't exist for n={}.".format(self.hecke_n())) @cached_method def G_inv(self): r""" Return the Fourier expansion of ``G_inv``. EXAMPLES:: sage: MFSeriesConstructor(group=4, prec=3, fix_d=True).G_inv() 1/16777216*q^-1 - 3/2097152 - 955/4194304*q + O(q^2) sage: MFSeriesConstructor(group=4, prec=3).G_inv_ZZ() == MFSeriesConstructor(group=4, prec=3, set_d=1).G_inv() True sage: MFSeriesConstructor(group=8, prec=3).G_inv() d^3*q^-1 - 15*d^2/128 - 15139*d/262144*q + O(q^2) sage: MFSeriesConstructor(group=8, prec=3, fix_d=True).G_inv() 1.64838830030189e-6*q^-1 - 0.0000163526310530017 - 0.000682197999433738*q + O(q^2) sage: MFSeriesConstructor(group=8, prec=3).G_inv().parent() Laurent Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=8, prec=3, fix_d=True).G_inv().parent() Laurent Series Ring in q over Real Field with 53 bits of precision """ return (self._d)**2*self.G_inv_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def E4_ZZ(self): r""" Return the rational Fourier expansion of ``E_4``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).E4_ZZ() 1 + 5/36*q + 5/6912*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E4_ZZ() 1 + 21/100*q + 483/32000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E4_ZZ().parent() Power Series Ring in q over Rational Field """ q = self._ZZseries_ring.gen() E4_ZZ = ((-q*self.J_inv_ZZ().derivative())**2/(self.J_inv_ZZ()*(self.J_inv_ZZ()-1))).power_series() return E4_ZZ @cached_method def E4(self): r""" Return the Fourier expansion of ``E_4``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).E4() 1 + 240*q + 2160*q^2 + O(q^3) sage: MFSeriesConstructor(prec=3).E4_ZZ() == MFSeriesConstructor(prec=3, set_d=1).E4() True sage: MFSeriesConstructor(group=5, prec=3).E4() 1 + 21/(100*d)*q + 483/(32000*d^2)*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E4() 1.00000000000000 + 29.7777973053239*q + 303.489522086457*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E4().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E4().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self.E4_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def E6_ZZ(self): r""" Return the rational Fourier expansion of ``E_6``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).E6_ZZ() 1 - 7/24*q - 77/13824*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E6_ZZ() 1 - 37/200*q - 14663/320000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E6_ZZ().parent() Power Series Ring in q over Rational Field """ q = self._ZZseries_ring.gen() n = self.hecke_n() E6_ZZ = ((-q*self.J_inv_ZZ().derivative())**3/(self.J_inv_ZZ()**2*(self.J_inv_ZZ()-1))).power_series() return E6_ZZ @cached_method def E6(self): r""" Return the Fourier expansion of ``E_6``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).E6() 1 - 504*q - 16632*q^2 + O(q^3) sage: MFSeriesConstructor(prec=3).E6_ZZ() == MFSeriesConstructor(prec=3, set_d=1).E6() True sage: MFSeriesConstructor(group=5, prec=3).E6() 1 - 37/(200*d)*q - 14663/(320000*d^2)*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E6() 1.00000000000000 - 26.2328214356424*q - 921.338894897250*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E6().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E6().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self.E6_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def Delta_ZZ(self): r""" Return the rational Fourier expansion of ``Delta``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).Delta_ZZ() q - 1/72*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).Delta_ZZ() 71/50*q + 28267/16000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).Delta_ZZ().parent() Power Series Ring in q over Rational Field """ n = self.hecke_n() return self.E4_ZZ()**(2*n-6)*(self.E4_ZZ()**n-self.E6_ZZ()**2) @cached_method def Delta(self): r""" Return the Fourier expansion of ``Delta``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).Delta() q - 24*q^2 + O(q^3) sage: MFSeriesConstructor(prec=3).Delta_ZZ() == MFSeriesConstructor(prec=3, set_d=1).Delta() True sage: MFSeriesConstructor(group=5, prec=3).Delta() 71/50*q + 28267/(16000*d)*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).Delta() 0.000000000000000 + 1.42000000000000*q + 250.514582270711*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).Delta().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).Delta().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return (self._d)*self.Delta_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def E2_ZZ(self): r""" Return the rational Fourier expansion of ``E2``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).E2_ZZ() 1 - 1/72*q - 1/41472*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E2_ZZ() 1 - 9/200*q - 369/320000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E2_ZZ().parent() Power Series Ring in q over Rational Field """ q = self._ZZseries_ring.gen() E2_ZZ = (q*self.F_inf_ZZ().derivative())/self.F_inf_ZZ() return E2_ZZ @cached_method def E2(self): r""" Return the Fourier expansion of ``E2``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).E2() 1 - 24*q - 72*q^2 + O(q^3) sage: MFSeriesConstructor(prec=3).E2_ZZ() == MFSeriesConstructor(prec=3, set_d=1).E2() True sage: MFSeriesConstructor(group=5, prec=3).E2() 1 - 9/(200*d)*q - 369/(320000*d^2)*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E2() 1.00000000000000 - 6.38095656542654*q - 23.1858454761703*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E2().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E2().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self.E2_ZZ()(self._qseries_ring.gen()/self._d)
class JFSeriesConstructor(SageObject,UniqueRepresentation): r""" Constructor for the Fourier expansion of some (specific, basic) modular forms. The constructor is used by forms elements in case their Fourier expansion is needed or requested. """ @staticmethod def __classcall__(cls, group = HeckeTriangleGroup(3), prec=ZZ(10)): r""" Return a (cached) instance with canonical parameters. .. NOTE: For each choice of group and precision the constructor is cached (only) once. Further calculations with different base rings and possibly numerical parameters are based on the same cached instance. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor() == JFSeriesConstructor(3, 10) True sage: JFSeriesConstructor(group=4).hecke_n() 4 sage: JFSeriesConstructor(group=5, prec=12).prec() 12 """ if (group==infinity): group = HeckeTriangleGroup(infinity) else: try: group = HeckeTriangleGroup(ZZ(group)) except TypeError: group = HeckeTriangleGroup(group.n()) prec=ZZ(prec) # We don't need this assumption the precision may in principle also be negative. # if (prec<1): # raise Exception("prec must be an Integer >=1") return super(JFSeriesConstructor,cls).__classcall__(cls, group, prec) def __init__(self, group, prec): r""" Constructor for the Fourier expansion of some (specific, basic) modular forms. INPUT: - ``group`` -- A Hecke triangle group (default: HeckeTriangleGroup(3)). - ``prec`` -- An integer (default: 10), the default precision used in calculations in the LaurentSeriesRing or PowerSeriesRing. OUTPUT: The constructor for Fourier expansion with the specified settings. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFC = JFSeriesConstructor() sage: JFC Power series constructor for Hecke modular forms for n=3 with (basic series) precision 10 sage: JFC.group() Hecke triangle group for n = 3 sage: JFC.prec() 10 sage: JFC._series_ring Power Series Ring in q over Rational Field sage: JFSeriesConstructor(group=4) Power series constructor for Hecke modular forms for n=4 with (basic series) precision 10 sage: JFSeriesConstructor(group=5, prec=12) Power series constructor for Hecke modular forms for n=5 with (basic series) precision 12 sage: JFSeriesConstructor(group=infinity) Power series constructor for Hecke modular forms for n=+Infinity with (basic series) precision 10 """ self._group = group self._prec = prec FR = FractionField(PolynomialRing(ZZ,'p,d')) self._series_ring = PowerSeriesRing(FR,'q',default_prec=self._prec) #self._series_ring2 = PowerSeriesRing(QQ[['q']],'p',default_prec=self._prec) self._qseries_ring = PowerSeriesRing(QQ,'q',default_prec=self._prec) def _repr_(self): r""" Return the string representation of ``self``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor(group=4) Power series constructor for Hecke modular forms for n=4 with (basic series) precision 10 sage: JFSeriesConstructor(group=5, prec=12) Power series constructor for Hecke modular forms for n=5 with (basic series) precision 12 """ return "Power series constructor for Hecke modular forms for n={} with (basic series) precision {}".\ format(self._group.n(), self._prec) def group(self): r""" Return the (Hecke triangle) group of ``self``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor(group=4).group() Hecke triangle group for n = 4 """ return self._group def hecke_n(self): r""" Return the parameter ``n`` of the (Hecke triangle) group of ``self``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor(group=4).hecke_n() 4 """ return self._group.n() def prec(self): r""" Return the used default precision for the PowerSeriesRing or LaurentSeriesRing. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor(group=5).prec() 10 sage: JFSeriesConstructor(group=5, prec=20).prec() 20 """ return self._prec @cached_method def J_inv_ZZ(self): r""" Return the rational Fourier expansion of ``J_inv``, where the parameter ``d`` is replaced by ``1``. This is the main function used to determine all Fourier expansions! .. NOTE: The Fourier expansion of ``J_inv`` for ``d!=1`` is given by ``J_inv_ZZ(q/d)``. .. TODO: The functions that are used in this implementation are products of hypergeometric series with other, elementary, functions. Implement them and clean up this representation. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor(prec=3).J_inv_ZZ() q^-1 + 31/72 + 1823/27648*q + O(q^2) sage: JFSeriesConstructor(group=5, prec=3).J_inv_ZZ() q^-1 + 79/200 + 42877/640000*q + O(q^2) sage: JFSeriesConstructor(group=5, prec=3).J_inv_ZZ().parent() Laurent Series Ring in q over Rational Field sage: JFSeriesConstructor(group=infinity, prec=3).J_inv_ZZ() q^-1 + 3/8 + 69/1024*q + O(q^2) """ F1 = lambda a,b: self._qseries_ring( [ ZZ(0) ] + [ rising_factorial(a,k) * rising_factorial(b,k) / (ZZ(k).factorial())**2 * sum(ZZ(1)/(a+j) + ZZ(1)/(b+j) - ZZ(2)/ZZ(1+j) for j in range(ZZ(0),ZZ(k)) ) for k in range(ZZ(1), ZZ(self._prec+1)) ], ZZ(self._prec+1) ) F = lambda a,b,c: self._qseries_ring( [ rising_factorial(a,k) * rising_factorial(b,k) / rising_factorial(c,k) / ZZ(k).factorial() for k in range(ZZ(0), ZZ(self._prec+1)) ], ZZ(self._prec+1) ) a = self._group.alpha() b = self._group.beta() Phi = F1(a,b) / F(a,b,ZZ(1)) q = self._qseries_ring.gen() # the current implementation of power series reversion is slow # J_inv_ZZ = ZZ(1) / ((q*Phi.exp()).reversion()) temp_f = (q*Phi.exp()).polynomial() new_f = temp_f.revert_series(temp_f.degree()+1) J_inv_ZZ = ZZ(1) / (new_f + O(q**(temp_f.degree()+1))) q = self._series_ring.gen() J_inv_ZZ = sum([J_inv_ZZ.coefficients()[m] * q**J_inv_ZZ.exponents()[m] for m in range(len(J_inv_ZZ.coefficients()))]) + O(q**J_inv_ZZ.prec()) return J_inv_ZZ @cached_method def f_rho_ZZ(self): r""" Return the rational Fourier expansion of ``f_rho``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``f_rho`` for ``d!=1`` is given by ``f_rho_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor(prec=3).f_rho_ZZ() 1 + 5/36*q + 5/6912*q^2 + O(q^3) sage: JFSeriesConstructor(group=5, prec=3).f_rho_ZZ() 1 + 7/100*q + 21/160000*q^2 + O(q^3) sage: JFSeriesConstructor(group=5, prec=3).f_rho_ZZ().parent() Power Series Ring in q over Rational Field sage: JFSeriesConstructor(group=infinity, prec=3).f_rho_ZZ() 1 """ q = self._series_ring.gen(0) n = self.hecke_n() if (n == infinity): f_rho_ZZ = self._series_ring(1) else: temp_expr = ((-q*self.J_inv_ZZ().derivative())**2/(self.J_inv_ZZ()*(self.J_inv_ZZ()-1))).power_series() f_rho_ZZ = (temp_expr.log()/(n-2)).exp() return f_rho_ZZ @cached_method def f_i_ZZ(self): r""" Return the rational Fourier expansion of ``f_i``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``f_i`` for ``d!=1`` is given by ``f_i_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor(prec=3).f_i_ZZ() 1 - 7/24*q - 77/13824*q^2 + O(q^3) sage: JFSeriesConstructor(group=5, prec=3).f_i_ZZ() 1 - 13/40*q - 351/64000*q^2 + O(q^3) sage: JFSeriesConstructor(group=5, prec=3).f_i_ZZ().parent() Power Series Ring in q over Rational Field sage: JFSeriesConstructor(group=infinity, prec=3).f_i_ZZ() 1 - 3/8*q + 3/512*q^2 + O(q^3) """ q = self._series_ring.gen(0) n = self.hecke_n() if (n == infinity): f_i_ZZ = (-q*self.J_inv_ZZ().derivative()/self.J_inv_ZZ()).power_series() else: temp_expr = ((-q*self.J_inv_ZZ().derivative())**n/(self.J_inv_ZZ()**(n-1)*(self.J_inv_ZZ()-1))).power_series() f_i_ZZ = (temp_expr.log()/(n-2)).exp() return f_i_ZZ @cached_method def f_inf_ZZ(self): r""" Return the rational Fourier expansion of ``f_inf``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``f_inf`` for ``d!=1`` is given by ``d*f_inf_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor(prec=3).f_inf_ZZ() q - 1/72*q^2 + 7/82944*q^3 + O(q^4) sage: JFSeriesConstructor(group=5, prec=3).f_inf_ZZ() q - 9/200*q^2 + 279/640000*q^3 + O(q^4) sage: JFSeriesConstructor(group=5, prec=3).f_inf_ZZ().parent() Power Series Ring in q over Rational Field sage: JFSeriesConstructor(group=infinity, prec=3).f_inf_ZZ() q - 1/8*q^2 + 7/1024*q^3 + O(q^4) """ q = self._series_ring.gen(0) n = self.hecke_n() if (n == infinity): f_inf_ZZ = ((-q*self.J_inv_ZZ().derivative())**2/(self.J_inv_ZZ()**2*(self.J_inv_ZZ()-1))).power_series() else: temp_expr = ((-q*self.J_inv_ZZ().derivative())**(2*n)/(self.J_inv_ZZ()**(2*n-2)*(self.J_inv_ZZ()-1)**n)/q**(n-2)).power_series() f_inf_ZZ = (temp_expr.log()/(n-2)).exp()*q return f_inf_ZZ @cached_method def G_inv_ZZ(self): r""" Return the rational Fourier expansion of ``G_inv``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``G_inv`` for ``d!=1`` is given by ``d*G_inv_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor(group=4, prec=3).G_inv_ZZ() q^-1 - 3/32 - 955/16384*q + O(q^2) sage: JFSeriesConstructor(group=8, prec=3).G_inv_ZZ() q^-1 - 15/128 - 15139/262144*q + O(q^2) sage: JFSeriesConstructor(group=8, prec=3).G_inv_ZZ().parent() Laurent Series Ring in q over Rational Field sage: JFSeriesConstructor(group=infinity, prec=3).G_inv_ZZ() q^-1 - 1/8 - 59/1024*q + O(q^2) """ n = self.hecke_n() # Note that G_inv is not a weakly holomorphic form (because of the behavior at -1) if (n == infinity): q = self._series_ring.gen(0) temp_expr = (self.J_inv_ZZ()/self.f_inf_ZZ()*q**2).power_series() return 1/q*self.f_i_ZZ()*(temp_expr.log()/2).exp() elif (ZZ(2).divides(n)): return self.f_i_ZZ()*(self.f_rho_ZZ()**(ZZ(n/ZZ(2))))/self.f_inf_ZZ() else: #return self._qseries_ring([]) raise ValueError("G_inv doesn't exist for n={}.".format(self.hecke_n())) @cached_method def E4_ZZ(self): r""" Return the rational Fourier expansion of ``E_4``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``E4`` for ``d!=1`` is given by ``E4_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor(prec=3).E4_ZZ() 1 + 5/36*q + 5/6912*q^2 + O(q^3) sage: JFSeriesConstructor(group=5, prec=3).E4_ZZ() 1 + 21/100*q + 483/32000*q^2 + O(q^3) sage: JFSeriesConstructor(group=5, prec=3).E4_ZZ().parent() Power Series Ring in q over Rational Field sage: JFSeriesConstructor(group=infinity, prec=3).E4_ZZ() 1 + 1/4*q + 7/256*q^2 + O(q^3) """ q = self._series_ring.gen(0) E4_ZZ = ((-q*self.J_inv_ZZ().derivative())**2/(self.J_inv_ZZ()*(self.J_inv_ZZ()-1))).power_series() return E4_ZZ @cached_method def E6_ZZ(self): r""" Return the rational Fourier expansion of ``E_6``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``E6`` for ``d!=1`` is given by ``E6_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor(prec=3).E6_ZZ() 1 - 7/24*q - 77/13824*q^2 + O(q^3) sage: JFSeriesConstructor(group=5, prec=3).E6_ZZ() 1 - 37/200*q - 14663/320000*q^2 + O(q^3) sage: JFSeriesConstructor(group=5, prec=3).E6_ZZ().parent() Power Series Ring in q over Rational Field sage: JFSeriesConstructor(group=infinity, prec=3).E6_ZZ() 1 - 1/8*q - 31/512*q^2 + O(q^3) """ q = self._series_ring.gen(0) E6_ZZ = ((-q*self.J_inv_ZZ().derivative())**3/(self.J_inv_ZZ()**2*(self.J_inv_ZZ()-1))).power_series() return E6_ZZ @cached_method def Delta_ZZ(self): r""" Return the rational Fourier expansion of ``Delta``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``Delta`` for ``d!=1`` is given by ``d*Delta_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor(prec=3).Delta_ZZ() q - 1/72*q^2 + 7/82944*q^3 + O(q^4) sage: JFSeriesConstructor(group=5, prec=3).Delta_ZZ() q + 47/200*q^2 + 11367/640000*q^3 + O(q^4) sage: JFSeriesConstructor(group=5, prec=3).Delta_ZZ().parent() Power Series Ring in q over Rational Field sage: JFSeriesConstructor(group=infinity, prec=3).Delta_ZZ() q + 3/8*q^2 + 63/1024*q^3 + O(q^4) """ return (self.f_inf_ZZ()**3*self.J_inv_ZZ()**2/(self.f_rho_ZZ()**6)).power_series() @cached_method def E2_ZZ(self): r""" Return the rational Fourier expansion of ``E2``, where the parameter ``d`` is replaced by ``1``. .. NOTE: The Fourier expansion of ``E2`` for ``d!=1`` is given by ``E2_ZZ(q/d)``. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFSeriesConstructor(prec=3).E2_ZZ() 1 - 1/72*q - 1/41472*q^2 + O(q^3) sage: JFSeriesConstructor(group=5, prec=3).E2_ZZ() 1 - 9/200*q - 369/320000*q^2 + O(q^3) sage: JFSeriesConstructor(group=5, prec=3).E2_ZZ().parent() Power Series Ring in q over Rational Field sage: JFSeriesConstructor(group=infinity, prec=3).E2_ZZ() 1 - 1/8*q - 1/512*q^2 + O(q^3) """ q = self._series_ring.gen(0) E2_ZZ = (q*self.f_inf_ZZ().derivative())/self.f_inf_ZZ() return E2_ZZ @cached_method def EisensteinSeries_ZZ(self, k): r""" Return the rational Fourier expansion of the normalized Eisenstein series of weight ``k``, where the parameter ``d`` is replaced by ``1``. Only arithmetic groups with ``n < infinity`` are supported! .. NOTE: THe Fourier expansion of the series is given by ``EisensteinSeries_ZZ(q/d)``. INPUT: - ``k`` -- A non-negative even integer, namely the weight. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import JFSeriesConstructor sage: JFC = JFSeriesConstructor(prec=6) sage: JFC.EisensteinSeries_ZZ(k=0) 1 sage: JFC.EisensteinSeries_ZZ(k=2) 1 - 1/72*q - 1/41472*q^2 - 1/53747712*q^3 - 7/371504185344*q^4 - 1/106993205379072*q^5 + O(q^6) sage: JFC.EisensteinSeries_ZZ(k=6) 1 - 7/24*q - 77/13824*q^2 - 427/17915904*q^3 - 7399/123834728448*q^4 - 3647/35664401793024*q^5 + O(q^6) sage: JFC.EisensteinSeries_ZZ(k=12) 1 + 455/8292*q + 310765/4776192*q^2 + 20150585/6189944832*q^3 + 1909340615/42784898678784*q^4 + 3702799555/12322050819489792*q^5 + O(q^6) sage: JFC.EisensteinSeries_ZZ(k=12).parent() Power Series Ring in q over Rational Field sage: JFC = JFSeriesConstructor(group=4, prec=5) sage: JFC.EisensteinSeries_ZZ(k=2) 1 - 1/32*q - 5/8192*q^2 - 1/524288*q^3 - 13/536870912*q^4 + O(q^5) sage: JFC.EisensteinSeries_ZZ(k=4) 1 + 3/16*q + 39/4096*q^2 + 21/262144*q^3 + 327/268435456*q^4 + O(q^5) sage: JFC.EisensteinSeries_ZZ(k=6) 1 - 7/32*q - 287/8192*q^2 - 427/524288*q^3 - 9247/536870912*q^4 + O(q^5) sage: JFC.EisensteinSeries_ZZ(k=12) 1 + 63/11056*q + 133119/2830336*q^2 + 2790081/181141504*q^3 + 272631807/185488900096*q^4 + O(q^5) sage: JFC = JFSeriesConstructor(group=6, prec=5) sage: JFC.EisensteinSeries_ZZ(k=2) 1 - 1/18*q - 1/648*q^2 - 7/209952*q^3 - 7/22674816*q^4 + O(q^5) sage: JFC.EisensteinSeries_ZZ(k=4) 1 + 2/9*q + 1/54*q^2 + 37/52488*q^3 + 73/5668704*q^4 + O(q^5) sage: JFC.EisensteinSeries_ZZ(k=6) 1 - 1/6*q - 11/216*q^2 - 271/69984*q^3 - 1057/7558272*q^4 + O(q^5) sage: JFC.EisensteinSeries_ZZ(k=12) 1 + 182/151329*q + 62153/2723922*q^2 + 16186807/882550728*q^3 + 381868123/95315478624*q^4 + O(q^5) """ try: if k < 0: raise TypeError(None) k = 2*ZZ(k/2) except TypeError: raise TypeError("k={} has to be a non-negative even integer!".format(k)) if (not self.group().is_arithmetic() or self.group().n() == infinity): # Exceptional cases should be called manually (see in FormsRing_abstract) raise NotImplementedError("Eisenstein series are only supported in the finite arithmetic cases!") # Trivial case if k == 0: return self._series_ring(1) M = ZZ(self.group().lam()**2) lamk = M**(ZZ(k/2)) dval = self.group().dvalue() def coeff(m): m = ZZ(m) if m < 0: return ZZ(0) elif m == 0: return ZZ(1) factor = -2*k / QQ(bernoulli(k)) / lamk sum1 = sigma(m, k-1) if M.divides(m): sum2 = (lamk-1) * sigma(ZZ(m/M), k-1) else: sum2 = ZZ(0) if (M == 1): sum3 = ZZ(0) else: if (m == 1): N = ZZ(1) else: N = ZZ(m / M**ZZ(m.valuation(M))) sum3 = -sigma(ZZ(N), k-1) * ZZ(m/N)**(k-1) / (lamk + 1) return factor * (sum1 + sum2 + sum3) * dval**m q = self._series_ring.gen(0) return sum([coeff(m)*q**m for m in range(self.prec())]).add_bigoh(self.prec()) #TODO: We only need this for the classical case where the coefficients of the eisenstein series # are known explicitely (no HeckeTriangleGroup necessary) #TODO: Rename all methods and remove everything unnecessary #TODO2: use a very clear convention what is meant by q,s,p,etc... def _cstheta(self, d, r): #returns coefficient c(d,r) p^r q^d of i q^(-1/8) theta1; s = shift = i q^{-1/8} k = r - QQ(1/2) if k in ZZ and 2*d == (k**2+k): return (-1)**k else: return 0 @cached_method def _cseta(self, m): #returns coefficient q^m of q^{1/24} eta^{-1} if m < 0: return 0 return Partitions(m).cardinality() @cached_method def _cseta3(self, m): #returns coeffcient q^m of q^{1/8} eta^{-3} if m < 0: return 0 return PartitionTuples(3,m).cardinality() @cached_method def _cK(self, d, r): #K = i theta_1 / \eta^3 = stheta*seta3 #return coefficient c(d,r) p^r q^d ## Since Jacobi form coffs satisfy r^2 < 4mn. theta1 coffs satisfy r^2 < 2 n. Here n = d + 1/8 so zero except for r^2 <= 2d + 1/4. if d < 0: return 0 return sum( self._cseta3(d - a)*self._cstheta(a,r) for a in range(0,d+1) ) @cached_method def _cK2(self, d, r): ## theta1^2 satisfy 4^2 < 4 n. n = d + 1/4, we get c(d,r) non-zero for r^2 <= 4d + 1. if d < 0: return 0 coff = 0 for a in range(0,d+1): L = sqrt(2*a + QQ(1/4)).round() #print "a,L", a, L coff += sum( self._cK(d - a,r-QQ(b/2))*self._cK(a,QQ(b/2)) for b in range(-2*L,2*L+1) if is_odd(b) ) return coff @cached_method def _cWP(self, d, r): #\wp(z) & = \frac{1}{12} + \frac{p}{(1-p)^2} + \sum_{k,r \geq 1} k (p^k - 2 + p^{-k}) q^{kr} if d < 0: return 0 if d == 0: if r < 0: return 0 elif r == 0: return QQ(1/12) else: return r if d > 0: if r == 0: return -2*sigma(d,1) elif d % r == 0: return abs(r) else: return 0 @cached_method def _cZ(self, d, r): #elliptic genus 24*K**2*wp if d < 0: return 0 coff = 0 for a in range(0,d + 1): L = sqrt(4*a + 1).round() coff += sum( 24*self._cWP(d - a,r-b)*self._cK2(a,b) for b in range(-L,L+1) ) return coff @cached_method def K(self): q = self._series_ring.gen() p = self._series_ring.base_ring().gen() def min_rcoeff(d): #TODO return -10 def max_rcoeff(d): #TODO return 10 return sum([sum([self._cK(d,r)*p**r for r in range(min_rcoeff(d), max_rcoeff(d) + 1)])*q**d for d in range(self.prec())]) @cached_method def wp(self): q = self._series_ring.gen() p = self._series_ring.base_ring().gen() def min_rcoeff(d): #TODO return -10 def max_rcoeff(d): #TODO return 10 return sum([sum([self._cWP(d,r)*p**r for r in range(min_rcoeff(d), max_rcoeff(d) + 1)])*q**d for d in range(self.prec())]) #TODO @cached_method def J1(self): q = self._series_ring.gen() p = self._series_ring.base_ring().gen() def min_rcoeff(d): #TODO return -10 def max_rcoeff(d): #TODO return 10 return sum([sum([self._cK(d,r)*p**r for r in range(min_rcoeff(d), max_rcoeff(d) + 1)])*q**d for d in range(self.prec())])
def series(self, n=2, quadratic_twist=+1, prec=5): r""" Returns the `n`-th approximation to the `p`-adic L-series as a power series in `T` (corresponding to `\gamma-1` with `\gamma=1+p` as a generator of `1+p\ZZ_p`). Each coefficient is a `p`-adic number whose precision is provably correct. Here the normalization of the `p`-adic L-series is chosen such that `L_p(J,1) = (1-1/\alpha)^2 L(J,1)/\Omega_J` where `\alpha` is the unit root INPUT: - ``n`` - (default: 2) a positive integer - ``quadratic_twist`` - (default: +1) a fundamental discriminant of a quadratic field, coprime to the conductor of the curve - ``prec`` - (default: 5) maximal number of terms of the series to compute; to compute as many as possible just give a very large number for ``prec``; the result will still be correct. ALIAS: power_series is identical to series. EXAMPLES:: sage: J = J0(188)[0] sage: p = 7 sage: L = J.padic_lseries(p) sage: L.is_ordinary() True sage: f = L.series(2) sage: f[0] O(7^20) sage: f[1].norm() 3 + 4*7 + 3*7^2 + 6*7^3 + 5*7^4 + 5*7^5 + 6*7^6 + 4*7^7 + 5*7^8 + 7^10 + 5*7^11 + 4*7^13 + 4*7^14 + 5*7^15 + 2*7^16 + 5*7^17 + 7^18 + 7^19 + O(7^20) """ n = ZZ(n) if n < 1: raise ValueError("n (={0}) must be a positive integer".format(n)) if not self.is_ordinary(): raise ValueError("p (={0}) must be an ordinary prime".format( self._p)) # check if the conditions on quadratic_twist are satisfied D = ZZ(quadratic_twist) if D != 1: if D % 4 == 0: d = D // 4 if not d.is_squarefree() or d % 4 == 1: raise ValueError( "quadratic_twist (={0}) must be a fundamental discriminant of a quadratic field" .format(D)) else: if not D.is_squarefree() or D % 4 != 1: raise ValueError( "quadratic_twist (={0}) must be a fundamental discriminant of a quadratic field" .format(D)) if gcd(D, self._p) != 1: raise ValueError( "quadratic twist (={0}) must be coprime to p (={1}) ". format(D, self._p)) if gcd(D, self._E.conductor()) != 1: for ell in prime_divisors(D): if valuation(self._E.conductor(), ell) > valuation(D, ell): raise ValueError( "can not twist a curve of conductor (={0}) by the quadratic twist (={1})." .format(self._E.conductor(), D)) p = self._p if p == 2 and self._normalize: print('Warning : For p=2 the normalization might not be correct !') #verbose("computing L-series for p=%s, n=%s, and prec=%s"%(p,n,prec)) # bounds = self._prec_bounds(n,prec) # padic_prec = max(bounds[1:]) + 5 padic_prec = 10 # verbose("using p-adic precision of %s"%padic_prec) res_series_prec = min(p**(n - 1), prec) verbose("using series precision of %s" % res_series_prec) ans = self._get_series_from_cache(n, res_series_prec, D) if not ans is None: verbose("found series in cache") return ans K = QQ gamma = K(1 + p) R = PowerSeriesRing(K, 'T', res_series_prec) T = R(R.gen(), res_series_prec) #L = R(0) one_plus_T_factor = R(1) gamma_power = K(1) teich = self.teichmuller(padic_prec) p_power = p**(n - 1) # F = Qp(p,padic_prec) verbose("Now iterating over %s summands" % ((p - 1) * p_power)) verbose_level = get_verbose() count_verb = 0 alphas = self.alpha() #print len(alphas) Lprod = [] self._emb = 0 if len(alphas) == 2: split = True else: split = False for alpha in alphas: L = R(0) self._emb = self._emb + 1 for j in range(p_power): s = K(0) if verbose_level >= 2 and j / p_power * 100 > count_verb + 3: verbose("%.2f percent done" % (float(j) / p_power * 100)) count_verb += 3 for a in range(1, p): if split: b = (teich[a]) % ZZ(p**n) b = b * gamma_power else: b = teich[a] * gamma_power s += self.measure(b, n, padic_prec, D, alpha) L += s * one_plus_T_factor one_plus_T_factor *= 1 + T gamma_power *= gamma Lprod = Lprod + [L] if len(Lprod) == 1: return Lprod[0] else: return Lprod[0] * Lprod[1]
def double_integral_zero_infty(Phi, tau1, tau2): p = Phi.parent().prime() K = tau1.parent() R = PolynomialRing(K, 'x') x = R.gen() R1 = PowerSeriesRing(K, 'r1') r1 = R1.gen() try: R1.set_default_prec(Phi.precision_absolute()) except AttributeError: R1.set_default_prec(Phi.precision_relative()) level = Phi._map._manin.level() E0inf = [M2Z([0, -1, level, 0])] E0Zp = [M2Z([p, a, 0, 1]) for a in range(p)] predicted_evals = num_evals(tau1, tau2) a, b, c, d = find_center(p, level, tau1, tau2).list() h = M2Z([a, b, c, d]) E = [h * e0 for e0 in E0Zp + E0inf] resadd = 0 resmul = 1 total_evals = 0 percentage = QQ(0) ii = 0 f = (x - tau2) / (x - tau1) while len(E) > 0: ii += 1 increment = QQ((100 - percentage) / len(E)) verbose( 'remaining %s percent (and done %s of %s evaluations)' % (RealField(10)(100 - percentage), total_evals, predicted_evals)) newE = [] for e in E: a, b, c, d = e.list() assert ZZ(c) % level == 0 try: y0 = f((a * r1 + b) / (c * r1 + d)) val = y0(y0.parent().base_ring()(0)) if all([xx.valuation(p) > 0 for xx in (y0 / val - 1).list()]): if total_evals % 100 == 0: Phi._map._codomain.clear_cache() pol = val.log(p_branch=0) + ( (y0.derivative() / y0).integral()) V = [0] * pol.valuation() + pol.shift( -pol.valuation()).list() try: phimap = Phi._map(M2Z([b, d, a, c])) except OverflowError: print(a, b, c, d) raise OverflowError, 'Matrix too large?' # mu_e0 = ZZ(phimap.moment(0).rational_reconstruction()) mu_e0 = ZZ(Phi._liftee._map(M2Z([b, d, a, c])).moment(0)) mu_e = [mu_e0] + [ phimap.moment(o).lift() for o in range(1, len(V)) ] resadd += sum(starmap(mul, izip(V, mu_e))) resmul *= val**mu_e0 percentage += increment total_evals += 1 else: newE.extend([e * e0 for e0 in E0Zp]) except ZeroDivisionError: #raise RuntimeError,'Probably not enough working precision...' newE.extend([e * e0 for e0 in E0Zp]) E = newE verbose('total evaluations = %s' % total_evals) val = resmul.valuation() return p**val * K.teichmuller(p**(-val) * resmul) * resadd.exp()