Пример #1
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))
Пример #2
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))
Пример #3
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
Пример #4
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))]
Пример #5
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
Пример #6
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()]
Пример #7
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))
Пример #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 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))
Пример #9
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)
Пример #10
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)
Пример #11
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)
Пример #12
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))
Пример #13
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))
Пример #14
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
Пример #15
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)
Пример #16
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.")
Пример #17
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]
    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)
Пример #19
0
 def __init__(self, precision, p):
     self.__precision = precision
     self.__power_series_ring = PowerSeriesRing(GF(p), 'q')
     self.__p = int(p)
Пример #20
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)
Пример #21
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)
Пример #22
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)
Пример #23
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)
Пример #24
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()
    def __init__(self, precision, p):
        JacobiFormD1NNFactory_class.__init__(self, precision)

        self.__power_series_ring_modular = PowerSeriesRing(GF(p), 'q')
        self.__p = int(p)
Пример #26
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