def lseries(self, num_prec=None, max_imaginary_part=0, max_asymp_coeffs=40): r""" Return the L-series of ``self`` if ``self`` is modular and holomorphic. Note: This relies on the (pari) based function ``Dokchitser``. INPUT: - ``num_prec`` -- An integer denoting the to-be-used numerical precision. If integer ``num_prec=None`` (default) the default numerical precision of the parent of ``self`` is used. - ``max_imaginary_part`` -- A real number (default: 0), indicating up to which imaginary part the L-series is going to be studied. - ``max_asymp_coeffs`` -- An integer (default: 40). OUTPUT: An interface to Tim Dokchitser's program for computing L-series, namely the series given by the Fourier coefficients of ``self``. EXAMPLES:: sage: from sage.modular.modform.eis_series import eisenstein_series_lseries sage: from sage.modular.modform_hecketriangle.space import ModularForms sage: f = ModularForms(n=3, k=4).E4()/240 sage: L = f.lseries() sage: L L-series associated to the modular form 1/240 + q + 9*q^2 + 28*q^3 + 73*q^4 + O(q^5) sage: L.conductor 1 sage: L(1).prec() 53 sage: L.check_functional_equation() < 2^(-50) True sage: L(1) -0.0304484570583... sage: abs(L(1) - eisenstein_series_lseries(4)(1)) < 2^(-53) True sage: L.derivative(1, 1) -0.0504570844798... sage: L.derivative(1, 2)/2 -0.0350657360354... sage: L.taylor_series(1, 3) -0.0304484570583... - 0.0504570844798...*z - 0.0350657360354...*z^2 + O(z^3) sage: coeffs = f.q_expansion_vector(min_exp=0, max_exp=20, fix_d=True) sage: sum([coeffs[k]*k^(-10) for k in range(1,len(coeffs))]).n(53) 1.00935215408... sage: L(10) 1.00935215649... sage: f = ModularForms(n=6, k=4).E4() sage: L = f.lseries(num_prec=200) sage: L.conductor 3 sage: L.check_functional_equation() < 2^(-180) True sage: L(1) -2.92305187760575399490414692523085855811204642031749788... sage: L(1).prec() 200 sage: coeffs = f.q_expansion_vector(min_exp=0, max_exp=20, fix_d=True) sage: sum([coeffs[k]*k^(-10) for k in range(1,len(coeffs))]).n(53) 24.2281438789... sage: L(10).n(53) 24.2281439447... sage: f = ModularForms(n=8, k=6, ep=-1).E6() sage: L = f.lseries() sage: L.check_functional_equation() < 2^(-45) True sage: L.taylor_series(3, 3) 0.000000000000... + 0.867197036668...*z + 0.261129628199...*z^2 + O(z^3) sage: coeffs = f.q_expansion_vector(min_exp=0, max_exp=20, fix_d=True) sage: sum([coeffs[k]*k^(-10) for k in range(1,len(coeffs))]).n(53) -13.0290002560... sage: L(10).n(53) -13.0290184579... sage: f = (ModularForms(n=17, k=24).Delta()^2) # long time sage: L = f.lseries() # long time sage: L.check_functional_equation() < 2^(-50) # long time True sage: L.taylor_series(12, 3) # long time 0.000683924755280... - 0.000875942285963...*z + 0.000647618966023...*z^2 + O(z^3) sage: coeffs = f.q_expansion_vector(min_exp=0, max_exp=20, fix_d=True) # long time sage: sum([coeffs[k]*k^(-30) for k in range(1,len(coeffs))]).n(53) # long time 9.31562890589...e-10 sage: L(30).n(53) # long time 9.31562890589...e-10 sage: f = ModularForms(n=infinity, k=2, ep=-1).f_i() sage: L = f.lseries() sage: L.check_functional_equation() < 2^(-50) True sage: L.taylor_series(1, 3) 0.000000000000... + 5.76543616701...*z + 9.92776715593...*z^2 + O(z^3) sage: coeffs = f.q_expansion_vector(min_exp=0, max_exp=20, fix_d=True) sage: sum([coeffs[k]*k^(-10) for k in range(1,len(coeffs))]).n(53) -23.9781792831... sage: L(10).n(53) -23.9781792831... """ from sage.rings.all import ZZ from sage.symbolic.all import pi from sage.functions.other import sqrt from sage.lfunctions.dokchitser import Dokchitser if (not (self.is_modular() and self.is_holomorphic()) or self.weight() == 0): raise NotImplementedError( "L-series are only implemented for non-trivial holomorphic modular forms." ) if (num_prec is None): num_prec = self.parent().default_num_prec() conductor = self.group().lam()**2 if (self.group().is_arithmetic()): conductor = ZZ(conductor) else: conductor = conductor.n(num_prec) gammaV = [0, 1] weight = self.weight() eps = self.ep() # L^*(s) = cor_factor * (2*pi)^(-s)gamma(s)*L(f,s), cor_factor = (2 * sqrt(pi)).n(num_prec) if (self.is_cuspidal()): poles = [] residues = [] else: poles = [weight] val_inf = self.q_expansion_fixed_d(prec=1, d_num_prec=num_prec)[0] residue = eps * val_inf * cor_factor # (pari) BUG? # The residue of the above L^*(s) differs by a factor -1 from # the residue pari expects (?!?). residue *= -1 residues = [residue] L = Dokchitser(conductor=conductor, gammaV=gammaV, weight=weight, eps=eps, poles=poles, residues=residues, prec=num_prec) # TODO for later: Figure out the correct coefficient growth and do L.set_coeff_growth(...) # num_coeffs = L.num_coeffs() num_coeffs = L.num_coeffs(1.2) coeff_vector = [ coeff for coeff in self.q_expansion_vector( min_exp=0, max_exp=num_coeffs + 1, fix_d=True) ] pari_precode = "coeff = {};".format(coeff_vector) L.init_coeffs(v="coeff[k+1]", pari_precode=pari_precode, max_imaginary_part=max_imaginary_part, max_asymp_coeffs=max_asymp_coeffs) L.check_functional_equation() L.rename("L-series associated to the {} form {}".format( "cusp" if self.is_cuspidal() else "modular", self)) return L
def lseries(self, num_prec=None, max_imaginary_part=0, max_asymp_coeffs=40): r""" Return the L-series of ``self`` if ``self`` is modular and holomorphic. Note: This relies on the (pari) based function ``Dokchitser``. INPUT: - ``num_prec`` -- An integer denoting the to-be-used numerical precision. If integer ``num_prec=None`` (default) the default numerical precision of the parent of ``self`` is used. - ``max_imaginary_part`` -- A real number (default: 0), indicating up to which imaginary part the L-series is going to be studied. - ``max_asymp_coeffs`` -- An integer (default: 40). OUTPUT: An interface to Tim Dokchitser's program for computing L-series, namely the series given by the Fourier coefficients of ``self``. EXAMPLES:: sage: from sage.modular.modform.eis_series import eisenstein_series_lseries sage: from sage.modular.modform_hecketriangle.space import ModularForms sage: f = ModularForms(n=3, k=4).E4()/240 sage: L = f.lseries() sage: L L-series associated to the modular form 1/240 + q + 9*q^2 + 28*q^3 + 73*q^4 + O(q^5) sage: L.conductor 1 sage: L(1).prec() 53 sage: L.check_functional_equation() < 2^(-50) True sage: L(1) -0.0304484570583... sage: abs(L(1) - eisenstein_series_lseries(4)(1)) < 2^(-53) True sage: L.derivative(1, 1) -0.0504570844798... sage: L.derivative(1, 2)/2 -0.0350657360354... sage: L.taylor_series(1, 3) -0.0304484570583... - 0.0504570844798...*z - 0.0350657360354...*z^2 + O(z^3) sage: coeffs = f.q_expansion_vector(min_exp=0, max_exp=20, fix_d=True) sage: sum([coeffs[k]*k^(-10) for k in range(1,len(coeffs))]).n(53) 1.00935215408... sage: L(10) 1.00935215649... sage: f = ModularForms(n=6, k=4).E4() sage: L = f.lseries(num_prec=200) sage: L.conductor 3 sage: L.check_functional_equation() < 2^(-180) True sage: L(1) -2.92305187760575399490414692523085855811204642031749788... sage: L(1).prec() 200 sage: coeffs = f.q_expansion_vector(min_exp=0, max_exp=20, fix_d=True) sage: sum([coeffs[k]*k^(-10) for k in range(1,len(coeffs))]).n(53) 24.2281438789... sage: L(10).n(53) 24.2281439447... sage: f = ModularForms(n=8, k=6, ep=-1).E6() sage: L = f.lseries() sage: L.check_functional_equation() < 2^(-45) True sage: L.taylor_series(3, 3) 0.000000000000... + 0.867197036668...*z + 0.261129628199...*z^2 + O(z^3) sage: coeffs = f.q_expansion_vector(min_exp=0, max_exp=20, fix_d=True) sage: sum([coeffs[k]*k^(-10) for k in range(1,len(coeffs))]).n(53) -13.0290002560... sage: L(10).n(53) -13.0290184579... sage: f = (ModularForms(n=17, k=24).Delta()^2) # long time sage: L = f.lseries() # long time sage: L.check_functional_equation() < 2^(-50) # long time True sage: L.taylor_series(12, 3) # long time 0.000683924755280... - 0.000875942285963...*z + 0.000647618966023...*z^2 + O(z^3) sage: coeffs = f.q_expansion_vector(min_exp=0, max_exp=20, fix_d=True) # long time sage: sum([coeffs[k]*k^(-30) for k in range(1,len(coeffs))]).n(53) # long time 9.31562890589...e-10 sage: L(30).n(53) # long time 9.31562890589...e-10 sage: f = ModularForms(n=infinity, k=2, ep=-1).f_i() sage: L = f.lseries() sage: L.check_functional_equation() < 2^(-50) True sage: L.taylor_series(1, 3) 0.000000000000... + 5.76543616701...*z + 9.92776715593...*z^2 + O(z^3) sage: coeffs = f.q_expansion_vector(min_exp=0, max_exp=20, fix_d=True) sage: sum([coeffs[k]*k^(-10) for k in range(1,len(coeffs))]).n(53) -23.9781792831... sage: L(10).n(53) -23.9781792831... """ from sage.rings.all import ZZ from sage.symbolic.all import pi from sage.functions.other import sqrt from sage.lfunctions.dokchitser import Dokchitser if (not (self.is_modular() and self.is_holomorphic()) or self.weight() == 0): raise NotImplementedError("L-series are only implemented for non-trivial holomorphic modular forms.") if (num_prec is None): num_prec = self.parent().default_num_prec() conductor = self.group().lam()**2 if (self.group().is_arithmetic()): conductor = ZZ(conductor) else: conductor = conductor.n(num_prec) gammaV = [0, 1] weight = self.weight() eps = self.ep() # L^*(s) = cor_factor * (2*pi)^(-s)gamma(s)*L(f,s), cor_factor = (2*sqrt(pi)).n(num_prec) if (self.is_cuspidal()): poles = [] residues = [] else: poles = [ weight ] val_inf = self.q_expansion_fixed_d(prec=1, d_num_prec=num_prec)[0] residue = eps * val_inf * cor_factor # (pari) BUG? # The residue of the above L^*(s) differs by a factor -1 from # the residue pari expects (?!?). residue *= -1 residues = [ residue ] L = Dokchitser(conductor = conductor, gammaV = gammaV, weight = weight, eps = eps, poles = poles, residues = residues, prec = num_prec) # TODO for later: Figure out the correct coefficient growth and do L.set_coeff_growth(...) # num_coeffs = L.num_coeffs() num_coeffs = L.num_coeffs(1.2) coeff_vector = [coeff for coeff in self.q_expansion_vector(min_exp=0, max_exp=num_coeffs + 1, fix_d=True)] pari_precode = "coeff = {};".format(coeff_vector) L.init_coeffs(v = "coeff[k+1]", pari_precode = pari_precode, max_imaginary_part = max_imaginary_part, max_asymp_coeffs = max_asymp_coeffs) L.check_functional_equation() L.rename("L-series associated to the {} form {}".format("cusp" if self.is_cuspidal() else "modular", self)) return L