Beispiel #1
0
 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))]
Beispiel #2
0
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
Beispiel #3
0
    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))
Beispiel #4
0
    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))
Beispiel #6
0
    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))
Beispiel #7
0
    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)
Beispiel #8
0
    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))
Beispiel #9
0
def an_list(euler_factor_polynomial_fn,
            upperbound=100000,
            base_field=sage.rings.all.RationalField()):
    """ Takes a fn that gives for each prime the polynomial of the associated with the prime,
        given as a list, with independent coefficient first. This list is of length the degree+1.
    """
    from sage.rings.fast_arith import prime_range
    from sage.rings.all import PowerSeriesRing
    from math import ceil, log
    PP = PowerSeriesRing(base_field, 'x', 1 + ceil(log(upperbound) / log(2.)))

    x = PP('x')
    prime_l = prime_range(upperbound + 1)
    result = [1 for i in range(upperbound)]
    for p in prime_l:
        euler_factor = (1 / (PP(euler_factor_polynomial_fn(p)))).padded_list()
        if len(euler_factor) == 1:
            for j in range(1, 1 + upperbound // p):
                result[j * p - 1] = 0
            continue

        k = 1
        while True:
            if p**k > upperbound:
                break
            for j in range(1, 1 + upperbound // (p**k)):
                if j % p == 0:
                    continue
                result[j * p**k - 1] *= euler_factor[k]
            k += 1
    return result
    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))
Beispiel #11
0
def modular_ratio_space(chi):
    r"""
    Compute the space of 'modular ratios', i.e. meromorphic modular forms f
    level N and character chi such that f * E is a holomorphic cusp form for
    every Eisenstein series E of weight 1 and character 1/chi.

    Elements are returned as q-expansions up to precision R, where R is one
    greater than the weight 3 Sturm bound.

    EXAMPLES::

        sage: chi = DirichletGroup(31,QQ).0
        sage: sage.modular.modform.weight1.modular_ratio_space(chi)
        [q - 8/3*q^3 + 13/9*q^4 + 43/27*q^5 - 620/81*q^6 + 1615/243*q^7 + 3481/729*q^8 + O(q^9),
         q^2 - 8/3*q^3 + 13/9*q^4 + 70/27*q^5 - 620/81*q^6 + 1858/243*q^7 + 2752/729*q^8 + O(q^9)]
    """
    from sage.modular.modform.constructor import EisensteinForms, CuspForms

    if chi(-1) == 1:
        return []
    N = chi.modulus()
    chi = chi.minimize_base_ring()
    K = chi.base_ring()
    R = Gamma0(N).sturm_bound(3) + 1
    verbose("Working precision is %s" % R, level=1)
    verbose("Coeff field is %s" % K, level=1)

    V = K**R
    I = V
    d = I.rank()

    t = verbose("Calculating Eisenstein forms in weight 1...", level=1)
    B0 = EisensteinForms(~chi, 1).q_echelon_basis(prec=R)
    B = [b + B0[0] for b in B0]
    verbose("Done (dimension %s)" % len(B), level=1, t=t)

    t = verbose("Calculating in weight 2...", level=1)
    C = CuspForms(Gamma0(N), 2).q_echelon_basis(prec=R)
    verbose("Done (dimension %s)" % len(C), t=t, level=1)

    t = verbose("Computing candidate space", level=1)
    for b in B:
        quots = (c / b for c in C)
        W = V.span(V(x.padded_list(R)) for x in quots)
        I = I.intersection(W)
        if I.rank() < d:
            verbose(" Cut down to dimension %s" % I.rank(), level=1)
            d = I.rank()
        if I.rank() == 0:
            break

    verbose("Done: intersection is %s-dimensional" % I.dimension(),
            t=t,
            level=1)

    A = PowerSeriesRing(K, 'q')
    return [A(x.list()).add_bigoh(R) for x in I.gens()]
    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)
Beispiel #13
0
    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))
Beispiel #14
0
    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)
Beispiel #15
0
    def approximate_series(self, prec, name=None):
        """
        Return the Laurent series with absolute precision ``prec`` approximated
        from this series.

        INPUT:

        - ``prec`` -- an integer

        - ``name`` -- name of the variable; if it is ``None``, the name of the variable
          of the series is used

        OUTPUT: a Laurent series with absolute precision ``prec``

        EXAMPLES::

            sage: L = LazyLaurentSeriesRing(ZZ, 'z')
            sage: z = L.gen()
            sage: f = (z - 2*z^3)^5/(1 - 2*z)
            sage: f
            z^5 + 2*z^6 - 6*z^7 - 12*z^8 + 16*z^9 + 32*z^10 - 16*z^11 + ...
            sage: g = f.approximate_series(10)
            sage: g
            z^5 + 2*z^6 - 6*z^7 - 12*z^8 + 16*z^9 + O(z^10)
            sage: g.parent()
            Power Series Ring in z over Integer Ring

        ::

            sage: h = (f^-1).approximate_series(3)
            sage: h
            z^-5 - 2*z^-4 + 10*z^-3 - 20*z^-2 + 60*z^-1 - 120 + 280*z - 560*z^2 + O(z^3)
            sage: h.parent()
            Laurent Series Ring in z over Integer Ring
        """
        S = self.parent()

        if name is None:
            name = S.variable_name()

        if self.valuation() < 0:
            from sage.rings.all import LaurentSeriesRing
            R = LaurentSeriesRing(S.base_ring(), name=name)
            n = self.valuation()
            return R([self.coefficient(i) for i in range(n, prec)],
                     n).add_bigoh(prec)
        else:
            from sage.rings.all import PowerSeriesRing
            R = PowerSeriesRing(S.base_ring(), name=name)
            return R([self.coefficient(i)
                      for i in range(prec)]).add_bigoh(prec)
Beispiel #16
0
def theta_qexp(prec=10, var='q', K=ZZ, sparse=False):
    r"""
    Return the `q`-expansion of the standard `\theta` series
    ` \theta = 1 + 2\sum_{n=1}{^\infty} q^{n^2}. `

    INPUT:

    - prec -- integer; the absolute precision of the output
    - var -- (default: 'q') variable name
    - K -- (default: ZZ) base ring of answer

    OUTPUT:

    a power series over K

    EXAMPLES::

        sage: theta_qexp(25)
        1 + 2*q + 2*q^4 + 2*q^9 + 2*q^16 + O(q^25)
        sage: theta_qexp(10)
        1 + 2*q + 2*q^4 + 2*q^9 + O(q^10)
        sage: theta_qexp(100)
        1 + 2*q + 2*q^4 + 2*q^9 + 2*q^16 + 2*q^25 + 2*q^36 + 2*q^49 + 2*q^64 + 2*q^81 + O(q^100)
        sage: theta_qexp(100, 't')
        1 + 2*t + 2*t^4 + 2*t^9 + 2*t^16 + 2*t^25 + 2*t^36 + 2*t^49 + 2*t^64 + 2*t^81 + O(t^100)
        sage: theta_qexp(100, 't', GF(2))
        1 + O(t^100)
        sage: f = theta_qexp(20,sparse=True); f
        1 + 2*q + 2*q^4 + 2*q^9 + 2*q^16 + O(q^20)
        sage: parent(f)
        Sparse Power Series Ring in q over Integer Ring

    """
    prec = Integer(prec)
    if prec <= 0:
        raise ValueError("prec must be positive")
    if sparse:
        v = {}
    else:
        v = [Integer(0)] * prec
    v[0] = Integer(1)
    two = Integer(2)
    n = int(sqrt(prec))
    if n*n != prec:
        n += 1
    for m in xrange(1, n):
        v[m*m] = two

    R = PowerSeriesRing(K, sparse=sparse, names=var)
    return R(v, prec=prec)
Beispiel #17
0
def theta2_qexp(prec=10, var='q', K=ZZ, sparse=False):
    r"""
    Return the `q`-expansion of the series
    ` \theta_2 = \sum_{n odd} q^{n^2}. `

    INPUT:

    - prec -- integer; the absolute precision of the output
    - var -- (default: 'q') variable name
    - K -- (default: ZZ) base ring of answer

    OUTPUT:

    a power series over K

    EXAMPLES::

        sage: theta2_qexp(18)
        q + q^9 + O(q^18)
        sage: theta2_qexp(49)
        q + q^9 + q^25 + O(q^49)
        sage: theta2_qexp(100, 'q', QQ)
        q + q^9 + q^25 + q^49 + q^81 + O(q^100)
        sage: f = theta2_qexp(100, 't', GF(3)); f
        t + t^9 + t^25 + t^49 + t^81 + O(t^100)
        sage: parent(f)
        Power Series Ring in t over Finite Field of size 3
        sage: theta2_qexp(200)
        q + q^9 + q^25 + q^49 + q^81 + q^121 + q^169 + O(q^200)
        sage: f = theta2_qexp(20,sparse=True); f
        q + q^9 + O(q^20)
        sage: parent(f)
        Sparse Power Series Ring in q over Integer Ring
    """
    prec = Integer(prec)
    if prec <= 0:
        raise ValueError("prec must be positive")
    if sparse:
        v = {}
    else:
        v = [Integer(0)] * prec
    one = Integer(1)
    n = int(sqrt(prec))
    if n*n < prec:
        n += 1
    for m in xrange(1, n, 2):
        v[m*m] = one
    R = PowerSeriesRing(K, sparse=sparse, names=var)
    return R(v, prec=prec)
Beispiel #18
0
    def taylor_series(self, s, k=6, var='z'):
        r"""
        Return the first `k` terms of the Taylor series expansion
        of the `L`-series about `s`.

        This is returned as a formal power series in ``var``.

        INPUT:

        -  ``s`` -- complex number; point about which to expand

        -  ``k`` -- optional integer (default: 6), series is
           `O(``var``^k)`

        -  ``var`` -- optional string (default: 'z'), variable of power
           series

        EXAMPLES::

            sage: from sage.lfunctions.pari import lfun_number_field, LFunction
            sage: lf = lfun_number_field(QQ)
            sage: L = LFunction(lf)
            sage: L.taylor_series(2, 3)
            1.64493406684823 - 0.937548254315844*z + 0.994640117149451*z^2 + O(z^3)
            sage: E = EllipticCurve('37a')
            sage: L = E.lseries().dokchitser(algorithm="pari")
            sage: L.taylor_series(1)
            0.000000000000000 + 0.305999773834052*z + 0.186547797268162*z^2 - 0.136791463097188*z^3 + 0.0161066468496401*z^4 + 0.0185955175398802*z^5 + O(z^6)

        We compute a Taylor series where each coefficient is to high
        precision::

            sage: E = EllipticCurve('389a')
            sage: L = E.lseries().dokchitser(200,algorithm="pari")
            sage: L.taylor_series(1,3)
            2...e-63 + (...e-63)*z + 0.75931650028842677023019260789472201907809751649492435158581*z^2 + O(z^3)

        Check that :trac:`25402` is fixed::

            sage: L = EllipticCurve("24a1").modular_form().lseries()
            sage: L.taylor_series(-1, 3)
            0.000000000000000 - 0.702565506265199*z + 0.638929001045535*z^2 + O(z^3)
        """
        pt = pari.Ser([s, 1], d=k)  # s + x + O(x^k)
        B = PowerSeriesRing(self._CC, var)
        return B(pari.lfun(self._L, pt, precision=self.prec))
Beispiel #19
0
    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))
Beispiel #20
0
    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))
Beispiel #21
0
def an_list(euler_factor_polynomial_fn,
            upperbound=100000,
            base_field=sage.rings.all.RationalField()):
    """
    Takes a fn that gives for each prime the Euler polynomial of the associated
    with the prime, given as a list, with independent coefficient first. This
    list is of length the degree+1.
    Output the first `upperbound` coefficients built from the Euler polys.

    Example:
    The `euler_factor_polynomial_fn` should in practice come from an L-function
    or data. For a simple example, we construct just the 2 and 3 factors of the
    Riemann zeta function, which have Euler factors (1 - 1*2^(-s))^(-1) and
    (1 - 1*3^(-s))^(-1).
    >>> euler = lambda p: [1, -1] if p <= 3 else [1, 0]
    >>> an_list(euler)[:20]
    [1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0]
    """
    from sage.rings.fast_arith import prime_range
    from sage.rings.all import PowerSeriesRing
    from math import ceil, log
    PP = PowerSeriesRing(base_field, 'x', 1 + ceil(log(upperbound) / log(2.)))

    prime_l = prime_range(upperbound + 1)
    result = [1 for i in range(upperbound)]
    for p in prime_l:
        euler_factor = (1 / (PP(euler_factor_polynomial_fn(p)))).padded_list()
        if len(euler_factor) == 1:
            for j in range(1, 1 + upperbound // p):
                result[j * p - 1] = 0
            continue

        k = 1
        while True:
            if p**k > upperbound:
                break
            for j in range(1, 1 + upperbound // (p**k)):
                if j % p == 0:
                    continue
                result[j * p**k - 1] *= euler_factor[k]
            k += 1
    return result
Beispiel #22
0
    def _l_action_(self, c):
        """
        Multivariate power series support multiplication by any ring for
        which there is a supported action on the base ring.

        EXAMPLES::
        
            sage: R.<s,t> = PowerSeriesRing(ZZ); R
            Multivariate Power Series Ring in s, t over Integer Ring
            sage: f = 1 + t + s + s*t + R.O(3)
            sage: g = f._l_action_(1/2); g
            1/2 + 1/2*s + 1/2*t + 1/2*s*t + O(s, t)^3
            sage: g.parent()
            Multivariate Power Series Ring in s, t over Rational Field
            sage: g = (1/2)*f; g
            1/2 + 1/2*s + 1/2*t + 1/2*s*t + O(s, t)^3
            sage: g.parent()
            Multivariate Power Series Ring in s, t over Rational Field

            sage: K = NumberField(x-3,'a')
            sage: g = K.random_element()*f
            sage: g.parent()
            Multivariate Power Series Ring in s, t over Number Field in a with defining polynomial x - 3

        """
        try:
            f = c * self._bg_value
            if f.parent() == self.parent()._bg_ps_ring():
                return MPowerSeries(self.parent(), f, prec=f.prec())
            else:
                from sage.rings.all import PowerSeriesRing
                new_parent = PowerSeriesRing(f.base_ring().base_ring(),
                                             num_gens=f.base_ring().ngens(),
                                             names=f.base_ring().gens())
                return MPowerSeries(new_parent, f, prec=f.prec())
        except (TypeError, AttributeError):
            raise TypeError("Action not defined.")
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())
Beispiel #24
0
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 local_analytic_interpolation(self, P, Q):
        """
        For points `P`, `Q` in the same residue disc,
        this constructs an interpolation from `P` to `Q`
        (in homogeneous coordinates) in a power series in
        the local parameter `t`, with precision equal to
        the `p`-adic precision of the underlying ring.

        INPUT:

        - P and Q points on self in the same residue disc

        OUTPUT:

        Returns a point `X(t) = ( x(t) : y(t) : z(t) )` such that:

        (1) `X(0) = P` and `X(1) = Q` if `P, Q` are not in the infinite disc
        (2) `X(P[0]^g/P[1]) = P` and `X(Q[0]^g/Q[1]) = Q` if `P, Q` are in the infinite disc

        EXAMPLES::

            sage: R.<x> = QQ['x']
            sage: H = HyperellipticCurve(x^3-10*x+9)
            sage: K = Qp(5,8)
            sage: HK = H.change_ring(K)

        A non-Weierstrass disc::

            sage: P = HK(0,3)
            sage: Q = HK(5, 3 + 3*5^2 + 2*5^3 + 3*5^4 + 2*5^5 + 2*5^6 + 3*5^7 + O(5^8))
            sage: x,y,z, = HK.local_analytic_interpolation(P,Q)
            sage: x(0) == P[0], x(1) == Q[0], y(0) == P[1], y.polynomial()(1) == Q[1]
            (True, True, True, True)

        A finite Weierstrass disc::

            sage: P = HK.lift_x(1 + 2*5^2)
            sage: Q = HK.lift_x(1 + 3*5^2)
            sage: x,y,z = HK.local_analytic_interpolation(P,Q)
            sage: x(0) == P[0], x.polynomial()(1) == Q[0], y(0) == P[1], y(1) == Q[1]
            (True, True, True, True)

        The infinite disc::

            sage: P = HK.lift_x(5^-2)
            sage: Q = HK.lift_x(4*5^-2)
            sage: x,y,z = HK.local_analytic_interpolation(P,Q)
            sage: x = x/z
            sage: y = y/z
            sage: x(P[0]/P[1]) == P[0]
            True
            sage: x(Q[0]/Q[1]) == Q[0]
            True
            sage: y(P[0]/P[1]) == P[1]
            True
            sage: y(Q[0]/Q[1]) == Q[1]
            True

        An error if points are not in the same disc::

            sage: x,y,z = HK.local_analytic_interpolation(P,HK(1,0))
            Traceback (most recent call last):
            ...
            ValueError: (5^-2 + O(5^6) : 5^-3 + 4*5^2 + 5^3 + 3*5^4 + O(5^5) : 1 + O(5^8)) and (1 + O(5^8) : 0 : 1 + O(5^8)) are not in the same residue disc

        AUTHORS:

        - Robert Bradshaw (2007-03)
        - Jennifer Balakrishnan (2010-02)
        """
        prec = self.base_ring().precision_cap()
        if not self.is_same_disc(P, Q):
            raise ValueError("%s and %s are not in the same residue disc" %
                             (P, Q))
        disc = self.residue_disc(P)
        t = PowerSeriesRing(self.base_ring(), 't', prec).gen(0)
        if disc == self.change_ring(self.base_ring().residue_field())(0, 1, 0):
            x, y = self.local_coordinates_at_infinity(2 * prec)
            g = self.genus()
            return (x * t**(2 * g + 1), y * t**(2 * g + 1), t**(2 * g + 1))
        if disc[1] != 0:
            x = P[0] + t * (Q[0] - P[0])
            pts = self.lift_x(x, all=True)
            if pts[0][1][0] == P[1]:
                return pts[0]
            else:
                return pts[1]
        else:
            S = self.find_char_zero_weier_point(P)
            x, y = self.local_coord(S)
            a = P[1]
            b = Q[1] - P[1]
            y = a + b * t
            x = x.polynomial()(y).add_bigoh(x.prec())
            return (x, y, 1)
Beispiel #26
0
 def __init__(self, precision, p):
     self.__precision = precision
     self.__power_series_ring = PowerSeriesRing(GF(p), 'q')
     self.__p = int(p)
Beispiel #27
0
    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)
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 __init__(self, precision, p):
        JacobiFormD1NNFactory_class.__init__(self, precision)

        self.__power_series_ring_modular = PowerSeriesRing(GF(p), 'q')
        self.__p = int(p)
Beispiel #30
0
def victor_miller_basis(k, prec=10, cusp_only=False, var='q'):
    r"""
    Compute and return the Victor Miller basis for modular forms of
    weight `k` and level 1 to precision `O(q^{prec})`.  If
    ``cusp_only`` is True, return only a basis for the cuspidal
    subspace.

    INPUT:

    - ``k`` -- an integer

    - ``prec`` -- (default: 10) a positive integer

    - ``cusp_only`` -- bool (default: False)

    - ``var`` -- string (default: 'q')

    OUTPUT:

        A sequence whose entries are power series in ``ZZ[[var]]``.

    EXAMPLES::

        sage: victor_miller_basis(1, 6)
        []
        sage: victor_miller_basis(0, 6)
        [
        1 + O(q^6)
        ]
        sage: victor_miller_basis(2, 6)
        []
        sage: victor_miller_basis(4, 6)
        [
        1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
        ]

        sage: victor_miller_basis(6, 6, var='w')
        [
        1 - 504*w - 16632*w^2 - 122976*w^3 - 532728*w^4 - 1575504*w^5 + O(w^6)
        ]

        sage: victor_miller_basis(6, 6)
        [
        1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)
        ]
        sage: victor_miller_basis(12, 6)
        [
        1 + 196560*q^2 + 16773120*q^3 + 398034000*q^4 + 4629381120*q^5 + O(q^6),
        q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 + O(q^6)
        ]

        sage: victor_miller_basis(12, 6, cusp_only=True)
        [
        q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 + O(q^6)
        ]
        sage: victor_miller_basis(24, 6, cusp_only=True)
        [
        q + 195660*q^3 + 12080128*q^4 + 44656110*q^5 + O(q^6),
        q^2 - 48*q^3 + 1080*q^4 - 15040*q^5 + O(q^6)
        ]
        sage: victor_miller_basis(24, 6)
        [
        1 + 52416000*q^3 + 39007332000*q^4 + 6609020221440*q^5 + O(q^6),
        q + 195660*q^3 + 12080128*q^4 + 44656110*q^5 + O(q^6),
        q^2 - 48*q^3 + 1080*q^4 - 15040*q^5 + O(q^6)
        ]
        sage: victor_miller_basis(32, 6)
        [
        1 + 2611200*q^3 + 19524758400*q^4 + 19715347537920*q^5 + O(q^6),
        q + 50220*q^3 + 87866368*q^4 + 18647219790*q^5 + O(q^6),
        q^2 + 432*q^3 + 39960*q^4 - 1418560*q^5 + O(q^6)
        ]

        sage: victor_miller_basis(40,200)[1:] == victor_miller_basis(40,200,cusp_only=True)
        True
        sage: victor_miller_basis(200,40)[1:] == victor_miller_basis(200,40,cusp_only=True)
        True

    AUTHORS:

    - William Stein, Craig Citro: original code

    - Martin Raum (2009-08-02): use FLINT for polynomial arithmetic (instead of NTL)
    """
    k = Integer(k)
    if k % 2 == 1 or k == 2:
        return Sequence([])
    elif k < 0:
        raise ValueError("k must be non-negative")
    elif k == 0:
        return Sequence([PowerSeriesRing(ZZ, var)(1).add_bigoh(prec)], cr=True)
    e = k.mod(12)
    if e == 2: e += 12
    n = (k - e) // 12

    if n == 0 and cusp_only:
        return Sequence([])

    # If prec is less than or equal to the dimension of the space of
    # cusp forms, which is just n, then we know the answer, and we
    # simply return it.
    if prec <= n:
        q = PowerSeriesRing(ZZ, var).gen(0)
        err = bigO(q**prec)
        ls = [0] * (n + 1)
        if not cusp_only:
            ls[0] = 1 + err
        for i in range(1, prec):
            ls[i] = q**i + err
        for i in range(prec, n + 1):
            ls[i] = err
        return Sequence(ls, cr=True)

    F6 = eisenstein_series_poly(6, prec)

    if e == 0:
        A = Fmpz_poly(1)
    elif e == 4:
        A = eisenstein_series_poly(4, prec)
    elif e == 6:
        A = F6
    elif e == 8:
        A = eisenstein_series_poly(8, prec)
    elif e == 10:
        A = eisenstein_series_poly(10, prec)
    else:  # e == 14
        A = eisenstein_series_poly(14, prec)

    if A[0] == -1:
        A = -A

    if n == 0:
        return Sequence([PowerSeriesRing(ZZ, var)(A.list()).add_bigoh(prec)],
                        cr=True)

    F6_squared = F6**2
    F6_squared._unsafe_mutate_truncate(prec)
    D = _delta_poly(prec)
    Fprod = F6_squared
    Dprod = D

    if cusp_only:
        ls = [Fmpz_poly(0)] + [A] * n
    else:
        ls = [A] * (n + 1)

    for i in xrange(1, n + 1):
        ls[n - i] *= Fprod
        ls[i] *= Dprod
        ls[n - i]._unsafe_mutate_truncate(prec)
        ls[i]._unsafe_mutate_truncate(prec)

        Fprod *= F6_squared
        Dprod *= D
        Fprod._unsafe_mutate_truncate(prec)
        Dprod._unsafe_mutate_truncate(prec)

    P = PowerSeriesRing(ZZ, var)
    if cusp_only:
        for i in xrange(1, n + 1):
            for j in xrange(1, i):
                ls[j] = ls[j] - ls[j][i] * ls[i]

        return Sequence([P(l.list()).add_bigoh(prec) for l in ls[1:]], cr=True)
    else:
        for i in xrange(1, n + 1):
            for j in xrange(i):
                ls[j] = ls[j] - ls[j][i] * ls[i]

        return Sequence([P(l.list()).add_bigoh(prec) for l in ls], cr=True)
Beispiel #31
0
    def frobenius_polynomial(self):
        r"""
        Return the characteristic polynomial of Frobenius.

        EXAMPLES:

        Hyperelliptic curves::

            sage: p = 11
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: f = x^7 + 4*x^2 + 10*x + 4
            sage: CyclicCover(2, f).frobenius_polynomial() == \
            ....: HyperellipticCurve(f).frobenius_polynomial()
            True
            sage: f = 2*x^5 + 4*x^3 + x^2 + 2*x + 1
            sage: CyclicCover(2, f).frobenius_polynomial() == \
            ....: HyperellipticCurve(f).frobenius_polynomial()
            True
            sage: f = 2*x^6 + 4*x^4 + x^3 + 2*x^2 + x
            sage: CyclicCover(2, f).frobenius_polynomial() == \
            ....: HyperellipticCurve(f).frobenius_polynomial()
            True
            sage: p = 1117
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: f = x^9 + 4*x^2 + 10*x + 4
            sage: CyclicCover(2, f).frobenius_polynomial() == \
            ....: HyperellipticCurve(f).frobenius_polynomial() # long time
            True
            sage: f = 2*x^5 + 4*x^3 + x^2 + 2*x + 1
            sage: CyclicCover(2, f).frobenius_polynomial() == \
            ....: HyperellipticCurve(f).frobenius_polynomial()
            True

        Superelliptic curves::

            sage: p = 11
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1).frobenius_polynomial()
            x^6 + 21*x^4 + 231*x^2 + 1331
            sage: CyclicCover(4, x^3 + x + 1).frobenius_polynomial()
            x^6 + 2*x^5 + 11*x^4 + 121*x^2 + 242*x + 1331
            sage: p = 4999
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: CyclicCover(4, x^3  - 1).frobenius_polynomial() == \
            ....: CyclicCover(3, x^4  + 1).frobenius_polynomial()
            True
            sage: CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1).frobenius_polynomial()
            x^6 + 180*x^5 + 20988*x^4 + 1854349*x^3 + 104919012*x^2 + 4498200180*x + 124925014999
            sage: CyclicCover(4,x^5 + x + 1).frobenius_polynomial()
            x^12 - 64*x^11 + 5018*x^10 - 488640*x^9 + 28119583*x^8 - 641791616*x^7 + 124245485932*x^6 - 3208316288384*x^5 + 702708407289583*x^4 - 61043359329111360*x^3 + 3133741752599645018*x^2 - 199800079984001599936*x + 15606259372500374970001

            sage: CyclicCover(11, PolynomialRing(GF(1129), 'x')([-1] + [0]*(5-1) + [1])).frobenius_polynomial() # long time
            x^40 + 7337188909826596*x^30 + 20187877911930897108199045855206*x^20 + 24687045654725446027864774006541463602997309796*x^10 + 11320844849639649951608809973589776933203136765026963553258401

            sage: CyclicCover(3, PolynomialRing(GF(1009^2), 'x')([-1] + [0]*(5-1) + [1])).frobenius_polynomial() # long time
            x^8 + 532*x^7 - 2877542*x^6 - 242628176*x^5 + 4390163797795*x^4 - 247015136050256*x^3 - 2982540407204025062*x^2 + 561382189105547134612*x + 1074309286591662654798721


        A non-monic example checking that :trac:`29015` is fixed::

            sage: a = 3
            sage: K.<s>=GF(83^3);
            sage: R.<x>= PolynomialRing(K)
            sage: h = s*x^4 +x*3+ 8;
            sage: C = CyclicCover(a,h)
            sage: C.frobenius_polynomial()
            x^6 + 1563486*x^4 + 893980969482*x^2 + 186940255267540403

        Non-superelliptic curves::

            sage: p = 13
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: C = CyclicCover(4, x^4 + 1)
            sage: C.frobenius_polynomial()
            x^6 - 6*x^5 + 3*x^4 + 60*x^3 + 39*x^2 - 1014*x + 2197
            sage: R.<t> = PowerSeriesRing(Integers())
            sage: C.projective_closure().zeta_series(2,t)
            1 + 8*t + 102*t^2 + O(t^3)
            sage: C.frobenius_polynomial().reverse()(t)/((1-t)*(1-p*t)) + O(t^5)
            1 + 8*t + 102*t^2 + 1384*t^3 + 18089*t^4 + O(t^5)

            sage: x = PolynomialRing(GF(11),"x").gen()
            sage: CyclicCover(4, x^6 - 11*x^3 + 70*x^2 - x + 961).frobenius_polynomial() # long time
            x^14 + 14*x^12 + 287*x^10 + 3025*x^8 + 33275*x^6 + 381997*x^4 + 2254714*x^2 + 19487171
            sage: x = PolynomialRing(GF(4999),"x").gen()
            sage: CyclicCover(4, x^6 - 11*x^3 + 70*x^2 - x + 961).frobenius_polynomial() # long time
            x^14 - 4*x^13 - 2822*x^12 - 30032*x^11 + 37164411*x^10 - 152369520*x^9 + 54217349361*x^8 - 1021791160888*x^7 + 271032529455639*x^6 - 3807714457169520*x^5 + 4642764601604000589*x^4 - 18754988504199390032*x^3 - 8809934776794570547178*x^2 - 62425037490001499880004*x + 78015690603129374475034999

            sage: p = 11
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: CyclicCover(3, 5*x^3 - 5*x + 13).frobenius_polynomial()
            x^2 + 11
            sage: CyclicCover(3, x^6 + x^4 - x^3 + 2*x^2 - x - 1).frobenius_polynomial()
            x^8 + 32*x^6 + 462*x^4 + 3872*x^2 + 14641
            sage: p = 4999
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: CyclicCover(3, 5*x^3 - 5*x + 13).frobenius_polynomial()
            x^2 - 47*x + 4999
            sage: CyclicCover(3, x^6 + x^4 - x^3 + 2*x^2 - x - 1).frobenius_polynomial()
            x^8 + 122*x^7 + 4594*x^6 - 639110*x^5 - 82959649*x^4 - 3194910890*x^3 + 114804064594*x^2 + 15240851829878*x + 624500149980001

            sage: p = 11
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: CyclicCover(5, x^5 + x).frobenius_polynomial() # long time
            x^12 + 4*x^11 + 22*x^10 + 108*x^9 + 503*x^8 + 1848*x^7 + 5588*x^6 + 20328*x^5 + 60863*x^4 + 143748*x^3 + 322102*x^2 + 644204*x + 1771561
            sage: CyclicCover(5, 2*x^5 + x).frobenius_polynomial() # long time
            x^12 - 9*x^11 + 42*x^10 - 108*x^9 - 47*x^8 + 1782*x^7 - 8327*x^6 + 19602*x^5 - 5687*x^4 - 143748*x^3 + 614922*x^2 - 1449459*x + 1771561
            sage: p = 49999
            sage: x = PolynomialRing(GF(p),"x").gen()
            sage: CyclicCover(5, x^5 + x ).frobenius_polynomial() # long time
            x^12 + 299994*x^10 + 37498500015*x^8 + 2499850002999980*x^6 + 93742500224997000015*x^4 + 1874812507499850001499994*x^2 + 15623125093747500037499700001
            sage: CyclicCover(5, 2*x^5 + x).frobenius_polynomial() # long time
            x^12 + 299994*x^10 + 37498500015*x^8 + 2499850002999980*x^6 + 93742500224997000015*x^4 + 1874812507499850001499994*x^2 + 15623125093747500037499700001


        TESTS::

            sage: for _ in range(5): # long time
            ....:     fail = False
            ....:     p = random_prime(500, lbound=5)
            ....:     for i in range(1, 4):
            ....:         F = GF(p**i)
            ....:         Fx = PolynomialRing(F, 'x')
            ....:         b = F.random_element()
            ....:         while b == 0:
            ....:            b = F.random_element()
            ....:         E = EllipticCurve(F, [0, b])
            ....:         C1 = CyclicCover(3, Fx([-b, 0, 1]))
            ....:         C2 = CyclicCover(2, Fx([b, 0, 0, 1]))
            ....:         frob = [elt.frobenius_polynomial() for elt in [E, C1, C2]]
            ....:         if len(set(frob)) != 1:
            ....:             E
            ....:             C1
            ....:             C2
            ....:             frob
            ....:             fail = True
            ....:             break
            ....:     if fail:
            ....:       break
            ....: else:
            ....:     True
            True


        """
        self._init_frob()
        F = self.frobenius_matrix(self._N0)

        def _denominator():
            R = PolynomialRing(ZZ, "T")
            T = R.gen()
            denom = R(1)
            lc = self._f.list()[-1]
            if lc == 1:  # MONIC
                for i in range(2, self._delta + 1):
                    if self._delta % i == 0:
                        phi = euler_phi(i)
                        G = IntegerModRing(i)
                        ki = G(self._q).multiplicative_order()
                        denom = denom * (T**ki - 1)**(phi // ki)
                return denom
            else:  # Non-monic
                x = PolynomialRing(self._Fq, "x").gen()
                f = x**self._delta - lc
                L = f.splitting_field("a")
                roots = [r for r, _ in f.change_ring(L).roots()]
                roots_dict = dict([(r, i) for i, r in enumerate(roots)])
                rootsfrob = [
                    L.frobenius_endomorphism(self._Fq.degree())(r)
                    for r in roots
                ]
                m = zero_matrix(len(roots))
                for i, r in enumerate(roots):
                    m[i, roots_dict[rootsfrob[i]]] = 1
            return R(R(m.characteristic_polynomial()) // (T - 1))

        denom = _denominator()
        R = PolynomialRing(ZZ, "x")

        if self._nodenominators:
            min_val = 0
        else:
            # are there any denominators in F?
            min_val = min(
                self._Qq(elt).valuation() for row in F.rows() for elt in row)

        if min_val >= 0:
            prec = _N0_nodenominators(self._p, self._genus, self._n)
            charpoly_prec = [
                prec + i for i in reversed(range(1, self._genus + 1))
            ] + [prec] * (self._genus + 1)
            cp = charpoly_frobenius(F, charpoly_prec, self._p, 1, self._n,
                                    denom.list())
            return R(cp)
        else:
            cp = F.charpoly().reverse()
            denom = denom.reverse()
            PS = PowerSeriesRing(self._Zp, "T")
            cp = PS(cp) / PS(denom)
            cp = cp.padded_list(self._genus + 1)
            cpZZ = [None for _ in range(2 * self._genus + 1)]
            cpZZ[0] = 1
            cpZZ[-1] = self._p**self._genus
            for i in range(1, self._genus + 1):
                cmod = cp[i]
                bound = binomial(2 * self._genus,
                                 i) * self._p**(i * self._n * 0.5)
                localmod = self._p**(ceil(log(bound, self._p)))
                c = cmod.lift() % localmod
                if c > bound:
                    c = -(-cmod.lift() % localmod)
                cpZZ[i] = c
                if i != self._genus + 1:
                    cpZZ[2 * self._genus - i] = c * self._p**(self._genus - i)
            cpZZ.reverse()
            return R(cpZZ)
Beispiel #32
0
def delta_qexp(prec=10, var='q', K=ZZ):
    """
    Return the `q`-expansion of the weight 12 cusp form `\Delta` as a power
    series with coefficients in the ring K (`= \ZZ` by default).

    INPUT:

    - ``prec`` -- integer (default 10), the absolute precision of the output
      (must be positive)

    - ``var`` -- string (default: 'q'), variable name

    - ``K`` -- ring (default: `\ZZ`), base ring of answer

    OUTPUT:

    a power series over K in the variable ``var``

    ALGORITHM:

    Compute the theta series

    .. math::

        \sum_{n \ge 0} (-1)^n (2n+1) q^{n(n+1)/2},

    a very simple explicit modular form whose 8th power is `\Delta`. Then
    compute the 8th power. All computations are done over `\ZZ` or `\ZZ`
    modulo `N` depending on the characteristic of the given coefficient
    ring `K`, and coerced into `K` afterwards.

    EXAMPLES::

        sage: delta_qexp(7)
        q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 - 6048*q^6 + O(q^7)
        sage: delta_qexp(7,'z')
        z - 24*z^2 + 252*z^3 - 1472*z^4 + 4830*z^5 - 6048*z^6 + O(z^7)
        sage: delta_qexp(-3)
        Traceback (most recent call last):
        ...
        ValueError: prec must be positive
        sage: delta_qexp(20, K = GF(3))
        q + q^4 + 2*q^7 + 2*q^13 + q^16 + 2*q^19 + O(q^20)
        sage: delta_qexp(20, K = GF(3^5, 'a'))
        q + q^4 + 2*q^7 + 2*q^13 + q^16 + 2*q^19 + O(q^20)
        sage: delta_qexp(10, K = IntegerModRing(60))
        q + 36*q^2 + 12*q^3 + 28*q^4 + 30*q^5 + 12*q^6 + 56*q^7 + 57*q^9 + O(q^10)

    TESTS:

    Test algorithm with modular arithmetic (see also #11804)::

        sage: delta_qexp(10^4).change_ring(GF(13)) == delta_qexp(10^4, K=GF(13))
        True
        sage: delta_qexp(1000).change_ring(IntegerModRing(5^100)) == delta_qexp(1000, K=IntegerModRing(5^100))
        True

    AUTHORS:

    - William Stein: original code

    - David Harvey (2007-05): sped up first squaring step

    - Martin Raum (2009-08-02): use FLINT for polynomial arithmetic (instead of NTL)
    """
    R = PowerSeriesRing(K, var)
    if K in (ZZ, QQ):
        return R(_delta_poly(prec).list(), prec, check=False)
    ch = K.characteristic()
    if ch > 0 and prec > 150:
        return R(_delta_poly_modulo(ch, prec), prec, check=False)
    else:
        # compute over ZZ and coerce
        return R(_delta_poly(prec).list(), prec, check=True)
Beispiel #33
0
    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]
Beispiel #34
0
def coeff_to_power_series(c, var='q', prec=None):
    """
    Convert a list or dictionary giving coefficients to a sage power series.
    """
    from sage.all import PowerSeriesRing, QQ
    return PowerSeriesRing(QQ, var)(c, 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]
Beispiel #36
0
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)
Beispiel #37
0
def hecke_stable_subspace(chi, aux_prime=ZZ(2)):
    r"""
    Compute a q-expansion basis for S_1(chi).

    Results are returned as q-expansions to a certain fixed (and fairly high)
    precision. If more precision is required this can be obtained with
    :func:`modular_ratio_to_prec`.

    EXAMPLES::

        sage: from sage.modular.modform.weight1 import hecke_stable_subspace
        sage: hecke_stable_subspace(DirichletGroup(59, QQ).0)
        [q - q^3 + q^4 - q^5 - q^7 - q^12 + q^15 + q^16 + 2*q^17 - q^19 - q^20 + q^21 + q^27 - q^28 - q^29 + q^35 + O(q^40)]
    """
    # Deal quickly with the easy cases.
    if chi(-1) == 1: return []
    N = chi.modulus()
    H = chi.kernel()
    G = GammaH(N, H)
    try:
        if ArithmeticSubgroup.dimension_cusp_forms(G, 1) == 0:
            verbose("no wt 1 cusp forms for N=%s, chi=%s by Riemann-Roch" %
                    (N, chi._repr_short_()),
                    level=1)
            return []
    except NotImplementedError:
        pass

    from sage.modular.modform.constructor import EisensteinForms
    chi = chi.minimize_base_ring()
    K = chi.base_ring()

    # Auxiliary prime for Hecke stability method
    l = aux_prime
    while l.divides(N):
        l = l.next_prime()
    verbose("Auxiliary prime: %s" % l, level=1)

    # Compute working precision
    R = l * Gamma0(N).sturm_bound(l + 2)

    t = verbose("Computing modular ratio space", level=1)
    mrs = modular_ratio_space(chi)

    t = verbose("Computing modular ratios to precision %s" % R, level=1)
    qexps = [modular_ratio_to_prec(chi, f, R) for f in mrs]
    verbose("Done", t=t, level=1)

    # We want to compute the largest subspace of I stable under T_l. To do
    # this, we compute I intersect T_l(I) modulo q^(R/l), and take its preimage
    # under T_l, which is then well-defined modulo q^R.

    from sage.modular.modform.hecke_operator_on_qexp import hecke_operator_on_qexp

    t = verbose("Computing Hecke-stable subspace", level=1)
    A = PowerSeriesRing(K, 'q')
    r = R // l
    V = K**R
    W = K**r
    Tl_images = [hecke_operator_on_qexp(f, l, 1, chi) for f in qexps]
    qvecs = [V(x.padded_list(R)) for x in qexps]
    qvecs_trunc = [W(x.padded_list(r)) for x in qexps]
    Tvecs = [W(x.padded_list(r)) for x in Tl_images]

    I = V.submodule(qvecs)
    Iimage = W.span(qvecs_trunc)
    TlI = W.span(Tvecs)
    Jimage = Iimage.intersection(TlI)
    J = I.Hom(W)(Tvecs).inverse_image(Jimage)

    verbose("Hecke-stable subspace is %s-dimensional" % J.dimension(),
            t=t,
            level=1)

    if J.rank() == 0: return []

    # The theory does not guarantee that J is exactly S_1(chi), just that it is
    # intermediate between S_1(chi) and M_1(chi). In every example I know of,
    # it is equal to S_1(chi), but just for honesty, we check this anyway.
    t = verbose("Checking cuspidality", level=1)
    JEis = V.span(
        V(x.padded_list(R))
        for x in EisensteinForms(chi, 1).q_echelon_basis(prec=R))
    D = JEis.intersection(J)
    if D.dimension() != 0:
        raise ArithmeticError("Got non-cuspidal form!")
    verbose("Done", t=t, level=1)
    qexps = Sequence(A(x.list()).add_bigoh(R) for x in J.gens())
    return qexps
Beispiel #38
0
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()