Exemplo n.º 1
0
def anlist_over_nf(E, bound):
    """
    Caution: This method is slow, especially for curves of high
    conductor, or defined over number fields of high degree. 
    The method is to take the Euler product form, and retrieve 
    the coefficients by expanding each product factor as a power 
    series. The bottleneck is counting points over good reductions.

    TODO: Cache this method: it is computed when initializing the 
    class dokchitser, if cached would have .num_coeffs() of a_i stored.

    EXAMPLE::

        sage: K.<i> = NumberField(x^2+1) 
        sage: E = EllipticCurve(K,[0,-1,1,0,0])
        sage: from psage.ellcurve.lseries.lseries_nf import anlist_over_nf
        sage: anlist_over_nf(E, 20)
        [0, 1, -2, 0, 2, 2, 0, 0, 0, -5, -4, 0, 0, 8, 0, 0, -4, -4, 10, 0, 4]
    """
    conductor = E.conductor()
    coefficients = [0, 1] + [0] * (bound - 1)
    for p in prime_range(bound + 1):
        accuracy_p = int(math.floor(old_div(math.log(bound), math.log(p)))) + 1
        series_p = get_coeffs_p_over_nf(E, p, accuracy_p, conductor)
        for i in range(1, accuracy_p):
            coefficients[p**i] = series_p[i]
    extend_multiplicatively_generic(coefficients)
    return coefficients
Exemplo n.º 2
0
def anlist_over_nf(E, bound):
    """
    Caution: This method is slow, especially for curves of high
    conductor, or defined over number fields of high degree. 
    The method is to take the Euler product form, and retrieve 
    the coefficients by expanding each product factor as a power 
    series. The bottleneck is counting points over good reductions.

    TODO: Cache this method: it is computed when initializing the 
    class dokchitser, if cached would have .num_coeffs() of a_i stored.

    EXAMPLE::

        sage: K.<i> = NumberField(x^2+1) 
        sage: E = EllipticCurve(K,[0,-1,1,0,0])
        sage: from psage.ellcurve.lseries.lseries_nf import anlist_over_nf
        sage: anlist_over_nf(E, 20)
        [0, 1, -2, 0, 2, 2, 0, 0, 0, -5, -4, 0, 0, 8, 0, 0, -4, -4, 10, 0, 4]
    """    
    conductor = E.conductor()
    coefficients = [0,1] + [0]*(bound-1)
    for p in prime_range(bound+1):
        accuracy_p = int(math.floor(math.log(bound)/math.log(p))) + 1
        series_p = get_coeffs_p_over_nf(E, p, accuracy_p, conductor)
        for i in range(1, accuracy_p):
            coefficients[p**i] = series_p[i]
    extend_multiplicatively_generic(coefficients)
    return coefficients
Exemplo n.º 3
0
def anlist_over_sqrt5(E, bound):
    """
    Compute the Dirichlet L-series coefficients, up to and including
    a_bound.  The i-th element of the return list is a[i].

    INPUT:
        - E -- elliptic curve over Q(sqrt(5)), which must have
          defining polynomial `x^2-x-1`.
        - ``bound`` -- integer

    OUTPUT:
        - list of integers of length bound + 1

    EXAMPLES::

        sage: from psage.ellcurve.lseries.lseries_nf import anlist_over_sqrt5
        sage: K.<a> = NumberField(x^2-x-1); E = EllipticCurve([0,-a,a,0,0])
        sage: v = anlist_over_sqrt5(E, 50); v
        [0, 1, 0, 0, -2, -1, 0, 0, 0, -4, 0, 3, 0, 0, 0, 0, 0, 0, 0, 5, 2, 0, 0, 0, 0, -4, 0, 0, 0, 11, 0, -6, 0, 0, 0, 0, 8, 0, 0, 0, 0, -1, 0, 0, -6, 4, 0, 0, 0, -6, 0]
        sage: len(v)
        51

    This function isn't super fast, but at least it will work in a few
    seconds up to `10^4`::

        sage: t = cputime()
        sage: v = anlist_over_sqrt5(E, 10^4)
        sage: assert cputime(t) < 5
    """
    from . import aplist_sqrt5
    from psage.number_fields.sqrt5.prime import primes_of_bounded_norm, Prime

    # Compute all of the prime ideals of the ring of integers up to the given bound
    primes = primes_of_bounded_norm(bound + 1)

    # Compute the traces of Frobenius: this is supposed to be the hard part
    v = aplist_sqrt5.aplist(E, bound + 1)

    # Compute information about the primes of bad reduction, in
    # particular the integers i such that primes[i] is a prime of bad
    # reduction.
    bad_primes = set([Prime(a.prime()) for a in E.local_data()])

    # We compute the local factors of the L-series as power series in ZZ[T].
    P = PowerSeriesRing(ZZ, 'T')
    T = P.gen()
    # Table of powers of T, so we don't have to compute T^4 (say) thousands of times.
    Tp = [T**i for i in range(5)]

    # For each prime, we write down the local factor.
    L_P = []
    for i, P in enumerate(primes):
        inertial_deg = 2 if P.is_inert() else 1
        a_p = v[i]
        if P in bad_primes:
            # bad reduction
            f = 1 - a_p * Tp[inertial_deg]
        else:
            # good reduction
            q = P.norm()
            f = 1 - a_p * Tp[inertial_deg] + q * Tp[2 * inertial_deg]
        L_P.append(f)

    # Use the local factors of the L-series to compute the Dirichlet
    # series coefficients of prime-power index.
    coefficients = [0, 1] + [0] * (bound - 1)
    i = 0
    while i < len(primes):
        P = primes[i]
        if P.is_split():
            s = L_P[i] * L_P[i + 1]
            i += 2
        else:
            s = L_P[i]
            i += 1
        p = P.p
        # We need enough terms t so that p^t > bound
        accuracy_p = int(math.floor(old_div(math.log(bound), math.log(p)))) + 1
        series_p = s.add_bigoh(accuracy_p)**(-1)
        for j in range(1, accuracy_p):
            coefficients[p**j] = series_p[j]

    # Using multiplicativity, fill in the non-prime power Dirichlet
    # series coefficients.
    extend_multiplicatively_generic(coefficients)
    return coefficients
Exemplo n.º 4
0
def elliptic_cm_form(E, n, prec, aplist_only=False, anlist_only=False):
    """
    Return q-expansion of the CM modular form associated to the n-th
    power of the Grossencharacter associated to the elliptic curve E.

    INPUT:
        - E -- CM elliptic curve
        - n -- positive integer
        - prec -- positive integer
        - aplist_only -- return list only of ap for p prime
        - anlist_only -- return list only of an

    OUTPUT:
        - power series with integer coefficients

    EXAMPLES::

        sage: from psage.modform.rational.special import elliptic_cm_form
        sage: f = CuspForms(121,4).newforms(names='a')[0]; f
        q + 8*q^3 - 8*q^4 + 18*q^5 + O(q^6)
        sage: E = EllipticCurve('121b')
        sage: elliptic_cm_form(E, 3, 7)
        q + 8*q^3 - 8*q^4 + 18*q^5 + O(q^7)
        sage: g = elliptic_cm_form(E, 3, 100)
        sage: g == f.q_expansion(100)
        True
    """
    if not E.has_cm():
        raise ValueError, "E must have CM"
    n = ZZ(n)
    if n <= 0:
        raise ValueError, "n must be positive"

    prec = ZZ(prec)
    if prec <= 0:
        return []
    elif prec <= 1:
        return [ZZ(0)]
    elif prec <= 2:
        return [ZZ(0), ZZ(1)]
    
    # Derive formula for sum of n-th powers of roots
    a,p,T = SR.var('a,p,T')
    roots = (T**2 - a*T + p).roots(multiplicities=False)
    s = sum(alpha**n for alpha in roots).simplify_full()
    
    # Create fast callable expression from formula
    g = fast_callable(s.polynomial(ZZ))

    # Compute aplist for the curve
    v = E.aplist(prec)

    # Use aplist to compute ap values for the CM form attached to n-th
    # power of Grossencharacter.
    P = prime_range(prec)

    if aplist_only:
        # case when we only want the a_p (maybe for computing an
        # L-series via Euler product)
        return [g(ap,p) for ap,p in zip(v,P)]

    # Default cause where we want all a_n
    anlist = [ZZ(0),ZZ(1)] + [None]*(prec-2)
    for ap,p in zip(v,P):
        anlist[p] = g(ap,p)

    # Fill in the prime power a_{p^r} for r >= 2.
    N = E.conductor()
    for p in P:
        prm2 = 1
        prm1 = p
        pr = p*p
        pn = p**n
        e = 1 if N%p else 0
        while pr < prec:
            anlist[pr] = anlist[prm1] * anlist[p]
            if e:
                anlist[pr] -= pn * anlist[prm2]
            prm2 = prm1
            prm1 = pr
            pr *= p

    # fill in a_n with n divisible by at least 2 primes
    extend_multiplicatively_generic(anlist)

    if anlist_only:
        return anlist

    f = Integer_list_to_polynomial(anlist, 'q')
    return ZZ[['q']](f, prec=prec)

    
    
                    
Exemplo n.º 5
0
def elliptic_cm_form(E, n, prec, aplist_only=False, anlist_only=False):
    """
    Return q-expansion of the CM modular form associated to the n-th
    power of the Grossencharacter associated to the elliptic curve E.

    INPUT:
        - E -- CM elliptic curve
        - n -- positive integer
        - prec -- positive integer
        - aplist_only -- return list only of ap for p prime
        - anlist_only -- return list only of an

    OUTPUT:
        - power series with integer coefficients

    EXAMPLES::

        sage: from psage.modform.rational.special import elliptic_cm_form
        sage: f = CuspForms(121,4).newforms(names='a')[0]; f
        q + 8*q^3 - 8*q^4 + 18*q^5 + O(q^6)
        sage: E = EllipticCurve('121b')
        sage: elliptic_cm_form(E, 3, 7)
        q + 8*q^3 - 8*q^4 + 18*q^5 + O(q^7)
        sage: g = elliptic_cm_form(E, 3, 100)
        sage: g == f.q_expansion(100)
        True
    """
    if not E.has_cm():
        raise ValueError, "E must have CM"
    n = ZZ(n)
    if n <= 0:
        raise ValueError, "n must be positive"

    prec = ZZ(prec)
    if prec <= 0:
        return []
    elif prec <= 1:
        return [ZZ(0)]
    elif prec <= 2:
        return [ZZ(0), ZZ(1)]
    
    # Derive formula for sum of n-th powers of roots
    a,p,T = SR.var('a,p,T')
    roots = (T**2 - a*T + p).roots(multiplicities=False)
    s = sum(alpha**n for alpha in roots).simplify_full()
    
    # Create fast callable expression from formula
    g = fast_callable(s.polynomial(ZZ))

    # Compute aplist for the curve
    v = E.aplist(prec)

    # Use aplist to compute ap values for the CM form attached to n-th
    # power of Grossencharacter.
    P = prime_range(prec)

    if aplist_only:
        # case when we only want the a_p (maybe for computing an
        # L-series via Euler product)
        return [g(ap,p) for ap,p in zip(v,P)]

    # Default cause where we want all a_n
    anlist = [ZZ(0),ZZ(1)] + [None]*(prec-2)
    for ap,p in zip(v,P):
        anlist[p] = g(ap,p)

    # Fill in the prime power a_{p^r} for r >= 2.
    N = E.conductor()
    for p in P:
        prm2 = 1
        prm1 = p
        pr = p*p
        pn = p**n
        e = 1 if N%p else 0
        while pr < prec:
            anlist[pr] = anlist[prm1] * anlist[p]
            if e:
                anlist[pr] -= pn * anlist[prm2]
            prm2 = prm1
            prm1 = pr
            pr *= p

    # fill in a_n with n divisible by at least 2 primes
    extend_multiplicatively_generic(anlist)

    if anlist_only:
        return anlist

    f = Integer_list_to_polynomial(anlist, 'q')
    return ZZ[['q']](f, prec=prec)
Exemplo n.º 6
0
def anlist_over_sqrt5(E, bound):
    """
    Compute the Dirichlet L-series coefficients, up to and including
    a_bound.  The i-th element of the return list is a[i].

    INPUT:
        - E -- elliptic curve over Q(sqrt(5)), which must have
          defining polynomial `x^2-x-1`.
        - ``bound`` -- integer

    OUTPUT:
        - list of integers of length bound + 1

    EXAMPLES::

        sage: from psage.ellcurve.lseries.lseries_nf import anlist_over_sqrt5
        sage: K.<a> = NumberField(x^2-x-1); E = EllipticCurve([0,-a,a,0,0])
        sage: v = anlist_over_sqrt5(E, 50); v
        [0, 1, 0, 0, -2, -1, 0, 0, 0, -4, 0, 3, 0, 0, 0, 0, 0, 0, 0, 5, 2, 0, 0, 0, 0, -4, 0, 0, 0, 11, 0, -6, 0, 0, 0, 0, 8, 0, 0, 0, 0, -1, 0, 0, -6, 4, 0, 0, 0, -6, 0]
        sage: len(v)
        51

    This function isn't super fast, but at least it will work in a few
    seconds up to `10^4`::

        sage: t = cputime()
        sage: v = anlist_over_sqrt5(E, 10^4)
        sage: assert cputime(t) < 5
    """
    import aplist_sqrt5
    from psage.number_fields.sqrt5.prime import primes_of_bounded_norm, Prime

    # Compute all of the prime ideals of the ring of integers up to the given bound
    primes = primes_of_bounded_norm(bound+1)

    # Compute the traces of Frobenius: this is supposed to be the hard part
    v      = aplist_sqrt5.aplist(E, bound+1)

    # Compute information about the primes of bad reduction, in
    # particular the integers i such that primes[i] is a prime of bad
    # reduction.
    bad_primes = set([Prime(a.prime()) for a in E.local_data()])


    # We compute the local factors of the L-series as power series in ZZ[T].
    P = PowerSeriesRing(ZZ, 'T')
    T = P.gen()
    # Table of powers of T, so we don't have to compute T^4 (say) thousands of times.
    Tp = [T**i for i in range(5)]

    # For each prime, we write down the local factor.
    L_P = []
    for i, P in enumerate(primes):
        inertial_deg = 2 if P.is_inert() else 1
        a_p = v[i]
        if P in bad_primes:
            # bad reduction
            f = 1 - a_p*Tp[inertial_deg]
        else:
            # good reduction
            q = P.norm()
            f = 1 - a_p*Tp[inertial_deg] + q*Tp[2*inertial_deg]
        L_P.append(f)

    # Use the local factors of the L-series to compute the Dirichlet
    # series coefficients of prime-power index.
    coefficients = [0,1] + [0]*(bound-1)
    i = 0
    while i < len(primes):
        P = primes[i]
        if P.is_split():
            s = L_P[i] * L_P[i+1]
            i += 2
        else:
            s = L_P[i]
            i += 1
        p = P.p
        # We need enough terms t so that p^t > bound
        accuracy_p = int(math.floor(math.log(bound)/math.log(p))) + 1
        series_p = s.add_bigoh(accuracy_p)**(-1)
        for j in range(1, accuracy_p):
            coefficients[p**j] = series_p[j]

    # Using multiplicativity, fill in the non-prime power Dirichlet
    # series coefficients.
    extend_multiplicatively_generic(coefficients)
    return coefficients