Exemplo n.º 1
0
def eisenstein_series_lseries(weight, prec=53,
               max_imaginary_part=0,
               max_asymp_coeffs=40):
    r"""
    Return the L-series of the weight `2k` Eisenstein series
    on `\mathrm{SL}_2(\ZZ)`.

    This actually returns an interface to Tim Dokchitser's program
    for computing with the L-series of the Eisenstein series

    INPUT:

    - ``weight`` - even integer

    - ``prec`` - integer (bits precision)

    - ``max_imaginary_part`` - real number

    - ``max_asymp_coeffs`` - integer

    OUTPUT:

    The L-series of the Eisenstein series.

    EXAMPLES:

    We compute with the L-series of `E_{16}` and then `E_{20}`::

       sage: L = eisenstein_series_lseries(16)
       sage: L(1)
       -0.291657724743874
       sage: L = eisenstein_series_lseries(20)
       sage: L(2)
       -5.02355351645998

    Now with higher precision::

        sage: L = eisenstein_series_lseries(20, prec=200)
        sage: L(2)
        -5.0235535164599797471968418348135050804419155747868718371029
    """
    f = eisenstein_series_qexp(weight,prec)
    from sage.lfunctions.all import Dokchitser
    from sage.symbolic.constants import pi
    key = (prec, max_imaginary_part, max_asymp_coeffs)
    j = weight
    L = Dokchitser(conductor = 1,
                   gammaV = [0,1],
                   weight = j,
                   eps = (-1)**Integer(j/2),
                   poles = [j],
                   # Using a string for residues is a hack but it works well
                   # since this will make PARI/GP compute sqrt(pi) with the
                   # right precision.
                   residues = '[sqrt(Pi)*(%s)]'%((-1)**Integer(j/2)*bernoulli(j)/j),
                   prec = prec)

    s = 'coeff = %s;'%f.list()
    L.init_coeffs('coeff[k+1]',pari_precode = s,
                  max_imaginary_part=max_imaginary_part,
                  max_asymp_coeffs=max_asymp_coeffs)
    L.check_functional_equation()
    L.rename('L-series associated to the weight %s Eisenstein series %s on SL_2(Z)'%(j,f))
    return L
Exemplo n.º 2
0
def eisenstein_series_qexp(k, prec = 10, K=QQ, var='q', normalization='linear'):
    r"""
    Return the `q`-expansion of the normalized weight `k` Eisenstein series on
    `{\rm SL}_2(\ZZ)` to precision prec in the ring `K`. Three normalizations
    are available, depending on the parameter ``normalization``; the default
    normalization is the one for which the linear coefficient is 1.

    INPUT:

    - ``k`` - an even positive integer

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

    - ``K`` - (default: `\QQ`) a ring

    - ``var`` - (default: ``'q'``) variable name to use for q-expansion

    - ``normalization`` - (default: ``'linear'``) normalization to use. If this
      is ``'linear'``, then the series will be normalized so that the linear
      term is 1. If it is ``'constant'``, the series will be normalized to have
      constant term 1. If it is ``'integral'``, then the series will be
      normalized to have integer coefficients and no common factor, and linear
      term that is positive. Note that ``'integral'`` will work over arbitrary
      base rings, while ``'linear'`` or ``'constant'`` will fail if the
      denominator (resp. numerator) of `B_k / 2k` is invertible.

    ALGORITHM:

        We know `E_k = \text{constant} + \sum_n \sigma_{k-1}(n) q^n`. So we
        compute all the `\sigma_{k-1}(n)` simultaneously, using the fact that
        `\sigma` is multiplicative.

    EXAMPLES::

        sage: eisenstein_series_qexp(2,5)
        -1/24 + q + 3*q^2 + 4*q^3 + 7*q^4 + O(q^5)
        sage: eisenstein_series_qexp(2,0)
        O(q^0)
        sage: eisenstein_series_qexp(2,5,GF(7))
        2 + q + 3*q^2 + 4*q^3 + O(q^5)
        sage: eisenstein_series_qexp(2,5,GF(7),var='T')
        2 + T + 3*T^2 + 4*T^3 + O(T^5)

    We illustrate the use of the ``normalization`` parameter::

        sage: eisenstein_series_qexp(12, 5, normalization='integral')
        691 + 65520*q + 134250480*q^2 + 11606736960*q^3 + 274945048560*q^4 + O(q^5)
        sage: eisenstein_series_qexp(12, 5, normalization='constant')
        1 + 65520/691*q + 134250480/691*q^2 + 11606736960/691*q^3 + 274945048560/691*q^4 + O(q^5)
        sage: eisenstein_series_qexp(12, 5, normalization='linear')
        691/65520 + q + 2049*q^2 + 177148*q^3 + 4196353*q^4 + O(q^5)
        sage: eisenstein_series_qexp(12, 50, K=GF(13), normalization="constant")
        1 + O(q^50)

    TESTS:

    Test that :trac:`5102` is fixed::

        sage: eisenstein_series_qexp(10, 30, GF(17))
        15 + q + 3*q^2 + 15*q^3 + 7*q^4 + 13*q^5 + 11*q^6 + 11*q^7 + 15*q^8 + 7*q^9 + 5*q^10 + 7*q^11 + 3*q^12 + 14*q^13 + 16*q^14 + 8*q^15 + 14*q^16 + q^17 + 4*q^18 + 3*q^19 + 6*q^20 + 12*q^21 + 4*q^22 + 12*q^23 + 4*q^24 + 4*q^25 + 8*q^26 + 14*q^27 + 9*q^28 + 6*q^29 + O(q^30)

    This shows that the bug reported at :trac:`8291` is fixed::

        sage: eisenstein_series_qexp(26, 10, GF(13))
        7 + q + 3*q^2 + 4*q^3 + 7*q^4 + 6*q^5 + 12*q^6 + 8*q^7 + 2*q^8 + O(q^10)

    We check that the function behaves properly over finite-characteristic base rings::

        sage: eisenstein_series_qexp(12, 5, K = Zmod(691), normalization="integral")
        566*q + 236*q^2 + 286*q^3 + 194*q^4 + O(q^5)
        sage: eisenstein_series_qexp(12, 5, K = Zmod(691), normalization="constant")
        Traceback (most recent call last):
        ...
        ValueError: The numerator of -B_k/(2*k) (=691) must be invertible in the ring Ring of integers modulo 691
        sage: eisenstein_series_qexp(12, 5, K = Zmod(691), normalization="linear")
        q + 667*q^2 + 252*q^3 + 601*q^4 + O(q^5)

        sage: eisenstein_series_qexp(12, 5, K = Zmod(2), normalization="integral")
        1 + O(q^5)
        sage: eisenstein_series_qexp(12, 5, K = Zmod(2), normalization="constant")
        1 + O(q^5)
        sage: eisenstein_series_qexp(12, 5, K = Zmod(2), normalization="linear")
        Traceback (most recent call last):
        ...
        ValueError: The denominator of -B_k/(2*k) (=65520) must be invertible in the ring Ring of integers modulo 2

    AUTHORS:

    - William Stein: original implementation

    - Craig Citro (2007-06-01): rewrote for massive speedup

    - Martin Raum (2009-08-02): port to cython for speedup

    - David Loeffler (2010-04-07): work around an integer overflow when `k` is large

    - David Loeffler (2012-03-15): add options for alternative normalizations
      (motivated by :trac:`12043`)
    """
    ## we use this to prevent computation if it would fail anyway.
    if k <= 0 or k % 2 == 1 :
        raise ValueError("k must be positive and even")

    a0 = - bernoulli(k) / (2*k)

    if normalization == 'linear':
        a0den = a0.denominator()
        try:
            a0fac = K(1/a0den)
        except ZeroDivisionError:
            raise ValueError("The denominator of -B_k/(2*k) (=%s) must be invertible in the ring %s"%(a0den, K))
    elif normalization == 'constant':
        a0num = a0.numerator()
        try:
            a0fac = K(1/a0num)
        except ZeroDivisionError:
            raise ValueError("The numerator of -B_k/(2*k) (=%s) must be invertible in the ring %s"%(a0num, K))
    elif normalization == 'integral':
        a0fac = None
    else:
        raise ValueError("Normalization (=%s) must be one of 'linear', 'constant', 'integral'" % normalization)

    R = PowerSeriesRing(K, var)
    if K == QQ and normalization == 'linear':
        ls = Ek_ZZ(k, prec)
        # The following is *dramatically* faster than doing the more natural
        # "R(ls)" would be:
        E = ZZ[var](ls, prec=prec, check=False).change_ring(QQ)
        if len(ls)>0:
            E._unsafe_mutate(0, a0)
        return R(E, prec)
        # The following is an older slower alternative to the above three lines:
        #return a0fac*R(eisenstein_series_poly(k, prec).list(), prec=prec, check=False)
    else:
        # This used to work with check=False, but that can only be regarded as
        # an improbable lucky miracle. Enabling checking is a noticeable speed
        # regression; the morally right fix would be to expose FLINT's
        # fmpz_poly_to_nmod_poly command (at least for word-sized N).
        if a0fac is not None:
            return a0fac*R(eisenstein_series_poly(k, prec).list(), prec=prec, check=True)
        else:
            return R(eisenstein_series_poly(k, prec).list(), prec=prec, check=True)
Exemplo n.º 3
0
def eisenstein_series_qexp(k, prec=10, K=QQ, var='q', normalization='linear'):
    r"""
    Return the `q`-expansion of the normalized weight `k` Eisenstein series on
    `{\rm SL}_2(\ZZ)` to precision prec in the ring `K`. Three normalizations
    are available, depending on the parameter ``normalization``; the default
    normalization is the one for which the linear coefficient is 1.

    INPUT:

    - ``k`` - an even positive integer

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

    - ``K`` - (default: `\QQ`) a ring

    - ``var`` - (default: ``'q'``) variable name to use for q-expansion

    - ``normalization`` - (default: ``'linear'``) normalization to use. If this
      is ``'linear'``, then the series will be normalized so that the linear
      term is 1. If it is ``'constant'``, the series will be normalized to have
      constant term 1. If it is ``'integral'``, then the series will be
      normalized to have integer coefficients and no common factor, and linear
      term that is positive. Note that ``'integral'`` will work over arbitrary
      base rings, while ``'linear'`` or ``'constant'`` will fail if the
      denominator (resp. numerator) of `B_k / 2k` is invertible.

    ALGORITHM:

        We know `E_k = \text{constant} + \sum_n \sigma_{k-1}(n) q^n`. So we
        compute all the `\sigma_{k-1}(n)` simultaneously, using the fact that
        `\sigma` is multiplicative.

    EXAMPLES::

        sage: eisenstein_series_qexp(2,5)
        -1/24 + q + 3*q^2 + 4*q^3 + 7*q^4 + O(q^5)
        sage: eisenstein_series_qexp(2,0)
        O(q^0)
        sage: eisenstein_series_qexp(2,5,GF(7))
        2 + q + 3*q^2 + 4*q^3 + O(q^5)
        sage: eisenstein_series_qexp(2,5,GF(7),var='T')
        2 + T + 3*T^2 + 4*T^3 + O(T^5)

    We illustrate the use of the ``normalization`` parameter::

        sage: eisenstein_series_qexp(12, 5, normalization='integral')
        691 + 65520*q + 134250480*q^2 + 11606736960*q^3 + 274945048560*q^4 + O(q^5)
        sage: eisenstein_series_qexp(12, 5, normalization='constant')
        1 + 65520/691*q + 134250480/691*q^2 + 11606736960/691*q^3 + 274945048560/691*q^4 + O(q^5)
        sage: eisenstein_series_qexp(12, 5, normalization='linear')
        691/65520 + q + 2049*q^2 + 177148*q^3 + 4196353*q^4 + O(q^5)
        sage: eisenstein_series_qexp(12, 50, K=GF(13), normalization="constant")
        1 + O(q^50)

    TESTS:

    Test that :trac:`5102` is fixed::

        sage: eisenstein_series_qexp(10, 30, GF(17))
        15 + q + 3*q^2 + 15*q^3 + 7*q^4 + 13*q^5 + 11*q^6 + 11*q^7 + 15*q^8 + 7*q^9 + 5*q^10 + 7*q^11 + 3*q^12 + 14*q^13 + 16*q^14 + 8*q^15 + 14*q^16 + q^17 + 4*q^18 + 3*q^19 + 6*q^20 + 12*q^21 + 4*q^22 + 12*q^23 + 4*q^24 + 4*q^25 + 8*q^26 + 14*q^27 + 9*q^28 + 6*q^29 + O(q^30)

    This shows that the bug reported at :trac:`8291` is fixed::

        sage: eisenstein_series_qexp(26, 10, GF(13))
        7 + q + 3*q^2 + 4*q^3 + 7*q^4 + 6*q^5 + 12*q^6 + 8*q^7 + 2*q^8 + O(q^10)

    We check that the function behaves properly over finite-characteristic base rings::

        sage: eisenstein_series_qexp(12, 5, K = Zmod(691), normalization="integral")
        566*q + 236*q^2 + 286*q^3 + 194*q^4 + O(q^5)
        sage: eisenstein_series_qexp(12, 5, K = Zmod(691), normalization="constant")
        Traceback (most recent call last):
        ...
        ValueError: The numerator of -B_k/(2*k) (=691) must be invertible in the ring Ring of integers modulo 691
        sage: eisenstein_series_qexp(12, 5, K = Zmod(691), normalization="linear")
        q + 667*q^2 + 252*q^3 + 601*q^4 + O(q^5)

        sage: eisenstein_series_qexp(12, 5, K = Zmod(2), normalization="integral")
        1 + O(q^5)
        sage: eisenstein_series_qexp(12, 5, K = Zmod(2), normalization="constant")
        1 + O(q^5)
        sage: eisenstein_series_qexp(12, 5, K = Zmod(2), normalization="linear")
        Traceback (most recent call last):
        ...
        ValueError: The denominator of -B_k/(2*k) (=65520) must be invertible in the ring Ring of integers modulo 2

    AUTHORS:

    - William Stein: original implementation

    - Craig Citro (2007-06-01): rewrote for massive speedup

    - Martin Raum (2009-08-02): port to cython for speedup

    - David Loeffler (2010-04-07): work around an integer overflow when `k` is large

    - David Loeffler (2012-03-15): add options for alternative normalizations
      (motivated by :trac:`12043`)
    """
    ## we use this to prevent computation if it would fail anyway.
    if k <= 0 or k % 2 == 1:
        raise ValueError, "k must be positive and even"

    a0 = -bernoulli(k) / (2 * k)

    if normalization == 'linear':
        a0den = a0.denominator()
        try:
            a0fac = K(1 / a0den)
        except ZeroDivisionError:
            raise ValueError, "The denominator of -B_k/(2*k) (=%s) must be invertible in the ring %s" % (
                a0den, K)
    elif normalization == 'constant':
        a0num = a0.numerator()
        try:
            a0fac = K(1 / a0num)
        except ZeroDivisionError:
            raise ValueError, "The numerator of -B_k/(2*k) (=%s) must be invertible in the ring %s" % (
                a0num, K)
    elif normalization == 'integral':
        a0fac = None
    else:
        raise ValueError, "Normalization (=%s) must be one of 'linear', 'constant', 'integral'" % normalization

    R = PowerSeriesRing(K, var)
    if K == QQ and normalization == 'linear':
        ls = Ek_ZZ(k, prec)
        # The following is *dramatically* faster than doing the more natural
        # "R(ls)" would be:
        E = ZZ[var](ls, prec=prec, check=False).change_ring(QQ)
        if len(ls) > 0:
            E._unsafe_mutate(0, a0)
        return R(E, prec)
        # The following is an older slower alternative to the above three lines:
        #return a0fac*R(eisenstein_series_poly(k, prec).list(), prec=prec, check=False)
    else:
        # This used to work with check=False, but that can only be regarded as
        # an improbable lucky miracle. Enabling checking is a noticeable speed
        # regression; the morally right fix would be to expose FLINT's
        # fmpz_poly_to_nmod_poly command (at least for word-sized N).
        if a0fac is not None:
            return a0fac * R(
                eisenstein_series_poly(k, prec).list(), prec=prec, check=True)
        else:
            return R(eisenstein_series_poly(k, prec).list(),
                     prec=prec,
                     check=True)
Exemplo n.º 4
0
def eisenstein_series_lseries(weight,
                              prec=53,
                              max_imaginary_part=0,
                              max_asymp_coeffs=40):
    r"""
    Return the L-series of the weight `2k` Eisenstein series
    on `\mathrm{SL}_2(\ZZ)`.

    This actually returns an interface to Tim Dokchitser's program
    for computing with the L-series of the Eisenstein series

    INPUT:

    - ``weight`` - even integer

    - ``prec`` - integer (bits precision)

    - ``max_imaginary_part`` - real number

    - ``max_asymp_coeffs`` - integer

    OUTPUT:

    The L-series of the Eisenstein series.

    EXAMPLES:

    We compute with the L-series of `E_{16}` and then `E_{20}`::

       sage: L = eisenstein_series_lseries(16)
       sage: L(1)
       -0.291657724743874
       sage: L = eisenstein_series_lseries(20)
       sage: L(2)
       -5.02355351645998

    Now with higher precision::

        sage: L = eisenstein_series_lseries(20, prec=200)
        sage: L(2)
        -5.0235535164599797471968418348135050804419155747868718371029
    """
    f = eisenstein_series_qexp(weight, prec)
    from sage.lfunctions.all import Dokchitser
    from sage.symbolic.constants import pi
    key = (prec, max_imaginary_part, max_asymp_coeffs)
    j = weight
    L = Dokchitser(
        conductor=1,
        gammaV=[0, 1],
        weight=j,
        eps=(-1)**Integer(j / 2),
        poles=[j],
        # Using a string for residues is a hack but it works well
        # since this will make PARI/GP compute sqrt(pi) with the
        # right precision.
        residues='[sqrt(Pi)*(%s)]' % ((-1)**Integer(j / 2) * bernoulli(j) / j),
        prec=prec)

    s = 'coeff = %s;' % f.list()
    L.init_coeffs('coeff[k+1]',
                  pari_precode=s,
                  max_imaginary_part=max_imaginary_part,
                  max_asymp_coeffs=max_asymp_coeffs)
    L.check_functional_equation()
    L.rename(
        'L-series associated to the weight %s Eisenstein series %s on SL_2(Z)'
        % (j, f))
    return L
Exemplo n.º 5
0
def eisenstein_series_qexp(k, prec = 10, K=QQ, var='q') :
    r"""
    Return the `q`-expansion of the normalized weight `k` Eisenstein series on
    `{\rm SL}_2(\ZZ)` to precision prec in the ring `K`.  (The normalization
    chosen here is the one that forces the coefficient of `q` to be 1.)

    INPUT:
    
    - ``k`` - an even positive integer
    
    - ``prec`` - (default: 10) a nonnegative integer
    
    - ``K`` - (default: `\QQ`) a ring in which the denominator of `B_k / 2k` is invertible

    - ``var`` - (default: 'q') variable name to use for q-expansion

    ALGORITHM:
    
        We know `E_k = \text{constant} + \sum_n \sigma_{k-1}(n) q^n`. So we
        compute all the `\sigma_{k-1}(n)` simultaneously, using the fact that
        `\sigma` is multiplicative.

    EXAMPLES::
    
        sage: eisenstein_series_qexp(2,5)
        -1/24 + q + 3*q^2 + 4*q^3 + 7*q^4 + O(q^5)
        sage: eisenstein_series_qexp(2,0)
        O(q^0)
        sage: eisenstein_series_qexp(2,5,GF(7))
        2 + q + 3*q^2 + 4*q^3 + O(q^5)
        sage: eisenstein_series_qexp(2,5,GF(7),var='T')
        2 + T + 3*T^2 + 4*T^3 + O(T^5)

        sage: eisenstein_series_qexp(10, 30, GF(17))
        15 + q + 3*q^2 + 15*q^3 + 7*q^4 + 13*q^5 + 11*q^6 + 11*q^7 + 15*q^8 + 7*q^9 + 5*q^10 + 7*q^11 + 3*q^12 + 14*q^13 + 16*q^14 + 8*q^15 + 14*q^16 + q^17 + 4*q^18 + 3*q^19 + 6*q^20 + 12*q^21 + 4*q^22 + 12*q^23 + 4*q^24 + 4*q^25 + 8*q^26 + 14*q^27 + 9*q^28 + 6*q^29 + O(q^30)

    TESTS:

    This shows that the bug reported at trac 8291 is fixed::

        sage: eisenstein_series_qexp(26, 10, GF(13))
        7 + q + 3*q^2 + 4*q^3 + 7*q^4 + 6*q^5 + 12*q^6 + 8*q^7 + 2*q^8 + O(q^10)

    AUTHORS:
    
    - William Stein: original implementation

    - Craig Citro (2007-06-01): rewrote for massive speedup
    
    - Martin Raum (2009-08-02): port to cython for speedup
    
    - David Loeffler (2010-04-07): work around an integer overflow when k is large
    """
    ## we use this to prevent computation if it would fail anyway.
    if k <= 0 or k % 2 == 1 :
        raise ValueError, "k must be positive and even"    
    
    a0 = - bernoulli(k) / (2*k)
    a0den = a0.denominator()
    try:
        a0fac = K(1/a0den)
    except ZeroDivisionError:
        raise ValueError, "The denominator of -B_k/(2*k) (=%s) must be invertible in the ring %s"%(a0den, K)
    

    R = PowerSeriesRing(K, var)
    if K == QQ:
        ls = Ek_ZZ(k, prec)
        # The following is *dramatically* faster than doing the more natural
        # "R(ls)" would be:
        E = ZZ[var](ls, prec=prec, check=False).change_ring(QQ)
        if len(ls)>0:
            E._unsafe_mutate(0, a0)
        return R(E, prec)
        # The following is an older slower alternative to the above three lines:
        #return a0fac*R(eisenstein_series_poly(k, prec).list(), prec=prec, check=False)
    else:
        # this is a temporary fix due to a change in the
        # polynomial constructor over finite fields; this
        # is a notable speed regression, to be fixed soon.
        return a0fac*R(eisenstein_series_poly(k, prec).list(), prec=prec, check=True)