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
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)
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)
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
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)