Path: blob/master/src/sage/functions/transcendental.py
8815 views
"""1Transcendental Functions2"""34#*****************************************************************************5# Copyright (C) 2005 William Stein <[email protected]>6#7# Distributed under the terms of the GNU General Public License (GPL)8#9# This code is distributed in the hope that it will be useful,10# but WITHOUT ANY WARRANTY; without even the implied warranty of11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12# General Public License for more details.13#14# The full text of the GPL is available at:15#16# http://www.gnu.org/licenses/17#*****************************************************************************1819import sys20import sage.libs.pari.all21from sage.libs.pari.all import pari22import sage.rings.complex_field as complex_field23from sage.structure.coerce import parent24from sage.structure.element import get_coercion_model25from sage.symbolic.expression import Expression26from sage.functions.other import factorial, psi2728from sage.rings.all import (ComplexField, ZZ, RR, RDF)29from sage.rings.complex_number import is_ComplexNumber30from sage.rings.real_mpfr import (RealField, is_RealNumber)3132from sage.symbolic.function import GinacFunction, BuiltinFunction, is_inexact3334import sage.libs.mpmath.utils as mpmath_utils35from sage.misc.superseded import deprecation36from sage.combinat.combinat import bernoulli_polynomial3738CC = complex_field.ComplexField()39I = CC.gen(0)404142class Function_zeta(GinacFunction):43def __init__(self):44r"""45Riemann zeta function at s with s a real or complex number.4647INPUT:4849- ``s`` - real or complex number5051If s is a real number the computation is done using the MPFR52library. When the input is not real, the computation is done using53the PARI C library.5455EXAMPLES::5657sage: zeta(x)58zeta(x)59sage: zeta(2)601/6*pi^261sage: zeta(2.)621.6449340668482363sage: RR = RealField(200)64sage: zeta(RR(2))651.644934066848226436472415166646025189218949901206798437735666sage: zeta(I)67zeta(I)68sage: zeta(I).n()690.00330022368532410 - 0.418155449141322*I7071It is possible to use the ``hold`` argument to prevent72automatic evaluation::7374sage: zeta(2,hold=True)75zeta(2)7677To then evaluate again, we currently must use Maxima via78:meth:`sage.symbolic.expression.Expression.simplify`::7980sage: a = zeta(2,hold=True); a.simplify()811/6*pi^28283TESTS::8485sage: latex(zeta(x))86\zeta(x)87sage: a = loads(dumps(zeta(x)))88sage: a.operator() == zeta89True9091sage: zeta(1)92Infinity93sage: zeta(x).subs(x=1)94Infinity95"""96GinacFunction.__init__(self, "zeta")9798zeta = Function_zeta()99100101class Function_HurwitzZeta(BuiltinFunction):102def __init__(self):103r"""104TESTS::105106sage: latex(hurwitz_zeta(x, 2))107\zeta\left(x, 2\right)108sage: hurwitz_zeta(x, 2)._sympy_()109zeta(x, 2)110"""111BuiltinFunction.__init__(self, 'hurwitz_zeta', nargs=2,112conversions=dict(mathematica='HurwitzZeta',113sympy='zeta'),114latex_name='\zeta')115116def _eval_(self, s, x):117r"""118TESTS::119120sage: hurwitz_zeta(x, 1)121zeta(x)122sage: hurwitz_zeta(4, 3)1231/90*pi^4 - 17/16124sage: hurwitz_zeta(-4, x)125-1/5*x^5 + 1/2*x^4 - 1/3*x^3 + 1/30*x126sage: hurwitz_zeta(3, 0.5)1278.41439832211716128"""129co = get_coercion_model().canonical_coercion(s, x)[0]130if is_inexact(co) and not isinstance(co, Expression):131return self._evalf_(s, x, parent=parent(co))132if x == 1:133return zeta(s)134if s in ZZ and s > 1:135return ((-1) ** s) * psi(s - 1, x) / factorial(s - 1)136elif s in ZZ and s < 0:137return -bernoulli_polynomial(x, -s + 1) / (-s + 1)138else:139return140141def _evalf_(self, s, x, parent):142r"""143TESTS::144145sage: hurwitz_zeta(11/10, 1/2).n()14612.1038134956837147sage: hurwitz_zeta(11/10, 1/2).n(100)14812.103813495683755105709077413149sage: hurwitz_zeta(11/10, 1 + 1j).n()1509.85014164287853 - 1.06139499403981*I151"""152from mpmath import zeta153return mpmath_utils.call(zeta, s, x, parent=parent)154155def _derivative_(self, s, x, diff_param):156r"""157TESTS::158159sage: y = var('y')160sage: diff(hurwitz_zeta(x, y), y)161-x*hurwitz_zeta(x + 1, y)162"""163if diff_param == 1:164return -s * hurwitz_zeta(s + 1, x)165else:166raise NotImplementedError('derivative with respect to first '167'argument')168169hurwitz_zeta_func = Function_HurwitzZeta()170171172def hurwitz_zeta(s, x, prec=None, **kwargs):173r"""174The Hurwitz zeta function `\zeta(s, x)`, where `s` and `x` are complex.175176The Hurwitz zeta function is one of the many zeta functions. It177defined as178179.. math::180181\zeta(s, x) = \sum_{k=0}^{\infty} (k + x)^{-s}.182183184When `x = 1`, this coincides with Riemann's zeta function.185The Dirichlet L-functions may be expressed as a linear combination186of Hurwitz zeta functions.187188EXAMPLES:189190Symbolic evaluations::191192sage: hurwitz_zeta(x, 1)193zeta(x)194sage: hurwitz_zeta(4, 3)1951/90*pi^4 - 17/16196sage: hurwitz_zeta(-4, x)197-1/5*x^5 + 1/2*x^4 - 1/3*x^3 + 1/30*x198sage: hurwitz_zeta(7, -1/2)199127*zeta(7) - 128200sage: hurwitz_zeta(-3, 1)2011/120202203Numerical evaluations::204205sage: hurwitz_zeta(3, 1/2).n()2068.41439832211716207sage: hurwitz_zeta(11/10, 1/2).n()20812.1038134956837209sage: hurwitz_zeta(3, x).series(x, 60).subs(x=0.5).n()2108.41439832211716211sage: hurwitz_zeta(3, 0.5)2128.41439832211716213214REFERENCES:215216- :wikipedia:`Hurwitz_zeta_function`217"""218if prec:219deprecation(15095, 'the syntax hurwitz_zeta(s, x, prec) has been '220'deprecated. Use hurwitz_zeta(s, x).n(digits=prec) '221'instead.')222return hurwitz_zeta_func(s, x).n(digits=prec)223return hurwitz_zeta_func(s, x, **kwargs)224225226class Function_zetaderiv(GinacFunction):227def __init__(self):228r"""229Derivatives of the Riemann zeta function.230231EXAMPLES::232233sage: zetaderiv(1, x)234zetaderiv(1, x)235sage: zetaderiv(1, x).diff(x)236zetaderiv(2, x)237sage: var('n')238n239sage: zetaderiv(n,x)240zetaderiv(n, x)241sage: zetaderiv(1, 4).n()242-0.0689112658961254243sage: import mpmath; mpmath.diff(lambda x: mpmath.zeta(x), 4)244mpf('-0.068911265896125382')245246TESTS::247248sage: latex(zetaderiv(2,x))249\zeta^\prime\left(2, x\right)250sage: a = loads(dumps(zetaderiv(2,x)))251sage: a.operator() == zetaderiv252True253"""254GinacFunction.__init__(self, "zetaderiv", nargs=2)255256def _evalf_(self, n, x, parent):257from mpmath import zeta258return mpmath_utils.call(zeta, x, 1, n, parent=parent)259260zetaderiv = Function_zetaderiv()261262def zeta_symmetric(s):263r"""264Completed function `\xi(s)` that satisfies265`\xi(s) = \xi(1-s)` and has zeros at the same points as the266Riemann zeta function.267268INPUT:269270271- ``s`` - real or complex number272273274If s is a real number the computation is done using the MPFR275library. When the input is not real, the computation is done using276the PARI C library.277278More precisely,279280.. math::281282xi(s) = \gamma(s/2 + 1) * (s-1) * \pi^{-s/2} * \zeta(s).283284285286EXAMPLES::287288sage: zeta_symmetric(0.7)2890.497580414651127290sage: zeta_symmetric(1-0.7)2910.497580414651127292sage: RR = RealField(200)293sage: zeta_symmetric(RR(0.7))2940.49758041465112690357779107525638385212657443284080589766062295sage: C.<i> = ComplexField()296sage: zeta_symmetric(0.5 + i*14.0)2970.000201294444235258 + 1.49077798716757e-19*I298sage: zeta_symmetric(0.5 + i*14.1)2990.0000489893483255687 + 4.40457132572236e-20*I300sage: zeta_symmetric(0.5 + i*14.2)301-0.0000868931282620101 + 7.11507675693612e-20*I302303REFERENCE:304305- I copied the definition of xi from306http://web.viu.ca/pughg/RiemannZeta/RiemannZetaLong.html307"""308if not (is_ComplexNumber(s) or is_RealNumber(s)):309s = ComplexField()(s)310311R = s.parent()312if s == 1: # deal with poles, hopefully313return R(0.5)314315return (s/2 + 1).gamma() * (s-1) * (R.pi()**(-s/2)) * s.zeta()316317import math318from sage.rings.polynomial.polynomial_real_mpfr_dense import PolynomialRealDense319320class DickmanRho(BuiltinFunction):321r"""322Dickman's function is the continuous function satisfying the323differential equation324325.. math::326327x \rho'(x) + \rho(x-1) = 0328329with initial conditions `\rho(x)=1` for330`0 \le x \le 1`. It is useful in estimating the frequency331of smooth numbers as asymptotically332333.. math::334335\Psi(a, a^{1/s}) \sim a \rho(s)336337where `\Psi(a,b)` is the number of `b`-smooth338numbers less than `a`.339340ALGORITHM:341342Dickmans's function is analytic on the interval343`[n,n+1]` for each integer `n`. To evaluate at344`n+t, 0 \le t < 1`, a power series is recursively computed345about `n+1/2` using the differential equation stated above.346As high precision arithmetic may be needed for intermediate results347the computed series are cached for later use.348349Simple explicit formulas are used for the intervals [0,1] and350[1,2].351352EXAMPLES::353354sage: dickman_rho(2)3550.306852819440055356sage: dickman_rho(10)3572.77017183772596e-11358sage: dickman_rho(10.00000000000000000000000000000000000000)3592.77017183772595898875812120063434232634e-11360sage: plot(log(dickman_rho(x)), (x, 0, 15))361362AUTHORS:363364- Robert Bradshaw (2008-09)365366REFERENCES:367368- G. Marsaglia, A. Zaman, J. Marsaglia. "Numerical369Solutions to some Classical Differential-Difference Equations."370Mathematics of Computation, Vol. 53, No. 187 (1989).371"""372def __init__(self):373"""374Constructs an object to represent Dickman's rho function.375376TESTS::377378sage: dickman_rho(x)379dickman_rho(x)380sage: dickman_rho(3)3810.0486083882911316382sage: dickman_rho(pi)3830.0359690758968463384"""385self._cur_prec = 0386BuiltinFunction.__init__(self, "dickman_rho", 1)387388def _eval_(self, x):389"""390EXAMPLES::391392sage: [dickman_rho(n) for n in [1..10]]393[1.00000000000000, 0.306852819440055, 0.0486083882911316, 0.00491092564776083, 0.000354724700456040, 0.0000196496963539553, 8.74566995329392e-7, 3.23206930422610e-8, 1.01624828273784e-9, 2.77017183772596e-11]394sage: dickman_rho(0)3951.00000000000000396"""397if not is_RealNumber(x):398try:399x = RR(x)400except (TypeError, ValueError):401return None #PrimitiveFunction.__call__(self, SR(x))402if x < 0:403return x.parent()(0)404elif x <= 1:405return x.parent()(1)406elif x <= 2:407return 1 - x.log()408n = x.floor()409if self._cur_prec < x.parent().prec() or not self._f.has_key(n):410self._cur_prec = rel_prec = x.parent().prec()411# Go a bit beyond so we're not constantly re-computing.412max = x.parent()(1.1)*x + 10413abs_prec = (-self.approximate(max).log2() + rel_prec + 2*max.log2()).ceil()414self._f = {}415if sys.getrecursionlimit() < max + 10:416sys.setrecursionlimit(int(max) + 10)417self._compute_power_series(max.floor(), abs_prec, cache_ring=x.parent())418return self._f[n](2*(x-n-x.parent()(0.5)))419420def power_series(self, n, abs_prec):421"""422This function returns the power series about `n+1/2` used423to evaluate Dickman's function. It is scaled such that the interval424`[n,n+1]` corresponds to x in `[-1,1]`.425426INPUT:427428- ``n`` - the lower endpoint of the interval for which429this power series holds430431- ``abs_prec`` - the absolute precision of the432resulting power series433434EXAMPLES::435436sage: f = dickman_rho.power_series(2, 20); f437-9.9376e-8*x^11 + 3.7722e-7*x^10 - 1.4684e-6*x^9 + 5.8783e-6*x^8 - 0.000024259*x^7 + 0.00010341*x^6 - 0.00045583*x^5 + 0.0020773*x^4 - 0.0097336*x^3 + 0.045224*x^2 - 0.11891*x + 0.13032438sage: f(-1), f(0), f(1)439(0.30685, 0.13032, 0.048608)440sage: dickman_rho(2), dickman_rho(2.5), dickman_rho(3)441(0.306852819440055, 0.130319561832251, 0.0486083882911316)442"""443return self._compute_power_series(n, abs_prec, cache_ring=None)444445def _compute_power_series(self, n, abs_prec, cache_ring=None):446"""447Compute the power series giving Dickman's function on [n, n+1], by448recursion in n. For internal use; self.power_series() is a wrapper449around this intended for the user.450451INPUT:452453- ``n`` - the lower endpoint of the interval for which454this power series holds455456- ``abs_prec`` - the absolute precision of the457resulting power series458459- ``cache_ring`` - for internal use, caches the power460series at this precision.461462EXAMPLES::463464sage: f = dickman_rho.power_series(2, 20); f465-9.9376e-8*x^11 + 3.7722e-7*x^10 - 1.4684e-6*x^9 + 5.8783e-6*x^8 - 0.000024259*x^7 + 0.00010341*x^6 - 0.00045583*x^5 + 0.0020773*x^4 - 0.0097336*x^3 + 0.045224*x^2 - 0.11891*x + 0.13032466"""467if n <= 1:468if n <= -1:469return PolynomialRealDense(RealField(abs_prec)['x'])470if n == 0:471return PolynomialRealDense(RealField(abs_prec)['x'], [1])472elif n == 1:473nterms = (RDF(abs_prec) * RDF(2).log()/RDF(3).log()).ceil()474R = RealField(abs_prec)475neg_three = ZZ(-3)476coeffs = [1 - R(1.5).log()] + [neg_three**-k/k for k in range(1, nterms)]477f = PolynomialRealDense(R['x'], coeffs)478if cache_ring is not None:479self._f[n] = f.truncate_abs(f[0] >> (cache_ring.prec()+1)).change_ring(cache_ring)480return f481else:482f = self._compute_power_series(n-1, abs_prec, cache_ring)483# integrand = f / (2n+1 + x)484# We calculate this way because the most significant term is the constant term,485# and so we want to push the error accumulation and remainder out to the least486# significant terms.487integrand = f.reverse().quo_rem(PolynomialRealDense(f.parent(), [1, 2*n+1]))[0].reverse()488integrand = integrand.truncate_abs(RR(2)**-abs_prec)489iintegrand = integrand.integral()490ff = PolynomialRealDense(f.parent(), [f(1) + iintegrand(-1)]) - iintegrand491i = 0492while abs(f[i]) < abs(f[i+1]):493i += 1494rel_prec = int(abs_prec + abs(RR(f[i])).log2())495if cache_ring is not None:496self._f[n] = ff.truncate_abs(ff[0] >> (cache_ring.prec()+1)).change_ring(cache_ring)497return ff.change_ring(RealField(rel_prec))498499def approximate(self, x, parent=None):500r"""501Approximate using de Bruijn's formula502503.. math::504505\rho(x) \sim \frac{exp(-x \xi + Ei(\xi))}{\sqrt{2\pi x}\xi}506507which is asymptotically equal to Dickman's function, and is much508faster to compute.509510REFERENCES:511512- N. De Bruijn, "The Asymptotic behavior of a function513occurring in the theory of primes." J. Indian Math Soc. v 15.514(1951)515516EXAMPLES::517518sage: dickman_rho.approximate(10)5192.41739196365564e-11520sage: dickman_rho(10)5212.77017183772596e-11522sage: dickman_rho.approximate(1000)5234.32938809066403e-3464524"""525log, exp, sqrt, pi = math.log, math.exp, math.sqrt, math.pi526x = float(x)527xi = log(x)528y = (exp(xi)-1.0)/xi - x529while abs(y) > 1e-12:530dydxi = (exp(xi)*(xi-1.0) + 1.0)/(xi*xi)531xi -= y/dydxi532y = (exp(xi)-1.0)/xi - x533return (-x*xi + RR(xi).eint()).exp() / (sqrt(2*pi*x)*xi)534535dickman_rho = DickmanRho()536537538