123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787 |
- """ Riemann zeta and related function. """
- from sympy.core.add import Add
- from sympy.core.cache import cacheit
- from sympy.core.function import ArgumentIndexError, expand_mul, Function
- from sympy.core.numbers import pi, I, Integer
- from sympy.core.relational import Eq
- from sympy.core.singleton import S
- from sympy.core.symbol import Dummy
- from sympy.core.sympify import sympify
- from sympy.functions.combinatorial.numbers import bernoulli, factorial, genocchi, harmonic
- from sympy.functions.elementary.complexes import re, unpolarify, Abs, polar_lift
- from sympy.functions.elementary.exponential import log, exp_polar, exp
- from sympy.functions.elementary.integers import ceiling, floor
- from sympy.functions.elementary.miscellaneous import sqrt
- from sympy.functions.elementary.piecewise import Piecewise
- from sympy.polys.polytools import Poly
- ###############################################################################
- ###################### LERCH TRANSCENDENT #####################################
- ###############################################################################
- class lerchphi(Function):
- r"""
- Lerch transcendent (Lerch phi function).
- Explanation
- ===========
- For $\operatorname{Re}(a) > 0$, $|z| < 1$ and $s \in \mathbb{C}$, the
- Lerch transcendent is defined as
- .. math :: \Phi(z, s, a) = \sum_{n=0}^\infty \frac{z^n}{(n + a)^s},
- where the standard branch of the argument is used for $n + a$,
- and by analytic continuation for other values of the parameters.
- A commonly used related function is the Lerch zeta function, defined by
- .. math:: L(q, s, a) = \Phi(e^{2\pi i q}, s, a).
- **Analytic Continuation and Branching Behavior**
- It can be shown that
- .. math:: \Phi(z, s, a) = z\Phi(z, s, a+1) + a^{-s}.
- This provides the analytic continuation to $\operatorname{Re}(a) \le 0$.
- Assume now $\operatorname{Re}(a) > 0$. The integral representation
- .. math:: \Phi_0(z, s, a) = \int_0^\infty \frac{t^{s-1} e^{-at}}{1 - ze^{-t}}
- \frac{\mathrm{d}t}{\Gamma(s)}
- provides an analytic continuation to $\mathbb{C} - [1, \infty)$.
- Finally, for $x \in (1, \infty)$ we find
- .. math:: \lim_{\epsilon \to 0^+} \Phi_0(x + i\epsilon, s, a)
- -\lim_{\epsilon \to 0^+} \Phi_0(x - i\epsilon, s, a)
- = \frac{2\pi i \log^{s-1}{x}}{x^a \Gamma(s)},
- using the standard branch for both $\log{x}$ and
- $\log{\log{x}}$ (a branch of $\log{\log{x}}$ is needed to
- evaluate $\log{x}^{s-1}$).
- This concludes the analytic continuation. The Lerch transcendent is thus
- branched at $z \in \{0, 1, \infty\}$ and
- $a \in \mathbb{Z}_{\le 0}$. For fixed $z, a$ outside these
- branch points, it is an entire function of $s$.
- Examples
- ========
- The Lerch transcendent is a fairly general function, for this reason it does
- not automatically evaluate to simpler functions. Use ``expand_func()`` to
- achieve this.
- If $z=1$, the Lerch transcendent reduces to the Hurwitz zeta function:
- >>> from sympy import lerchphi, expand_func
- >>> from sympy.abc import z, s, a
- >>> expand_func(lerchphi(1, s, a))
- zeta(s, a)
- More generally, if $z$ is a root of unity, the Lerch transcendent
- reduces to a sum of Hurwitz zeta functions:
- >>> expand_func(lerchphi(-1, s, a))
- zeta(s, a/2)/2**s - zeta(s, a/2 + 1/2)/2**s
- If $a=1$, the Lerch transcendent reduces to the polylogarithm:
- >>> expand_func(lerchphi(z, s, 1))
- polylog(s, z)/z
- More generally, if $a$ is rational, the Lerch transcendent reduces
- to a sum of polylogarithms:
- >>> from sympy import S
- >>> expand_func(lerchphi(z, s, S(1)/2))
- 2**(s - 1)*(polylog(s, sqrt(z))/sqrt(z) -
- polylog(s, sqrt(z)*exp_polar(I*pi))/sqrt(z))
- >>> expand_func(lerchphi(z, s, S(3)/2))
- -2**s/z + 2**(s - 1)*(polylog(s, sqrt(z))/sqrt(z) -
- polylog(s, sqrt(z)*exp_polar(I*pi))/sqrt(z))/z
- The derivatives with respect to $z$ and $a$ can be computed in
- closed form:
- >>> lerchphi(z, s, a).diff(z)
- (-a*lerchphi(z, s, a) + lerchphi(z, s - 1, a))/z
- >>> lerchphi(z, s, a).diff(a)
- -s*lerchphi(z, s + 1, a)
- See Also
- ========
- polylog, zeta
- References
- ==========
- .. [1] Bateman, H.; Erdelyi, A. (1953), Higher Transcendental Functions,
- Vol. I, New York: McGraw-Hill. Section 1.11.
- .. [2] https://dlmf.nist.gov/25.14
- .. [3] https://en.wikipedia.org/wiki/Lerch_transcendent
- """
- def _eval_expand_func(self, **hints):
- z, s, a = self.args
- if z == 1:
- return zeta(s, a)
- if s.is_Integer and s <= 0:
- t = Dummy('t')
- p = Poly((t + a)**(-s), t)
- start = 1/(1 - t)
- res = S.Zero
- for c in reversed(p.all_coeffs()):
- res += c*start
- start = t*start.diff(t)
- return res.subs(t, z)
- if a.is_Rational:
- # See section 18 of
- # Kelly B. Roach. Hypergeometric Function Representations.
- # In: Proceedings of the 1997 International Symposium on Symbolic and
- # Algebraic Computation, pages 205-211, New York, 1997. ACM.
- # TODO should something be polarified here?
- add = S.Zero
- mul = S.One
- # First reduce a to the interaval (0, 1]
- if a > 1:
- n = floor(a)
- if n == a:
- n -= 1
- a -= n
- mul = z**(-n)
- add = Add(*[-z**(k - n)/(a + k)**s for k in range(n)])
- elif a <= 0:
- n = floor(-a) + 1
- a += n
- mul = z**n
- add = Add(*[z**(n - 1 - k)/(a - k - 1)**s for k in range(n)])
- m, n = S([a.p, a.q])
- zet = exp_polar(2*pi*I/n)
- root = z**(1/n)
- up_zet = unpolarify(zet)
- addargs = []
- for k in range(n):
- p = polylog(s, zet**k*root)
- if isinstance(p, polylog):
- p = p._eval_expand_func(**hints)
- addargs.append(p/(up_zet**k*root)**m)
- return add + mul*n**(s - 1)*Add(*addargs)
- # TODO use minpoly instead of ad-hoc methods when issue 5888 is fixed
- if isinstance(z, exp) and (z.args[0]/(pi*I)).is_Rational or z in [-1, I, -I]:
- # TODO reference?
- if z == -1:
- p, q = S([1, 2])
- elif z == I:
- p, q = S([1, 4])
- elif z == -I:
- p, q = S([-1, 4])
- else:
- arg = z.args[0]/(2*pi*I)
- p, q = S([arg.p, arg.q])
- return Add(*[exp(2*pi*I*k*p/q)/q**s*zeta(s, (k + a)/q)
- for k in range(q)])
- return lerchphi(z, s, a)
- def fdiff(self, argindex=1):
- z, s, a = self.args
- if argindex == 3:
- return -s*lerchphi(z, s + 1, a)
- elif argindex == 1:
- return (lerchphi(z, s - 1, a) - a*lerchphi(z, s, a))/z
- else:
- raise ArgumentIndexError
- def _eval_rewrite_helper(self, target):
- res = self._eval_expand_func()
- if res.has(target):
- return res
- else:
- return self
- def _eval_rewrite_as_zeta(self, z, s, a, **kwargs):
- return self._eval_rewrite_helper(zeta)
- def _eval_rewrite_as_polylog(self, z, s, a, **kwargs):
- return self._eval_rewrite_helper(polylog)
- ###############################################################################
- ###################### POLYLOGARITHM ##########################################
- ###############################################################################
- class polylog(Function):
- r"""
- Polylogarithm function.
- Explanation
- ===========
- For $|z| < 1$ and $s \in \mathbb{C}$, the polylogarithm is
- defined by
- .. math:: \operatorname{Li}_s(z) = \sum_{n=1}^\infty \frac{z^n}{n^s},
- where the standard branch of the argument is used for $n$. It admits
- an analytic continuation which is branched at $z=1$ (notably not on the
- sheet of initial definition), $z=0$ and $z=\infty$.
- The name polylogarithm comes from the fact that for $s=1$, the
- polylogarithm is related to the ordinary logarithm (see examples), and that
- .. math:: \operatorname{Li}_{s+1}(z) =
- \int_0^z \frac{\operatorname{Li}_s(t)}{t} \mathrm{d}t.
- The polylogarithm is a special case of the Lerch transcendent:
- .. math:: \operatorname{Li}_{s}(z) = z \Phi(z, s, 1).
- Examples
- ========
- For $z \in \{0, 1, -1\}$, the polylogarithm is automatically expressed
- using other functions:
- >>> from sympy import polylog
- >>> from sympy.abc import s
- >>> polylog(s, 0)
- 0
- >>> polylog(s, 1)
- zeta(s)
- >>> polylog(s, -1)
- -dirichlet_eta(s)
- If $s$ is a negative integer, $0$ or $1$, the polylogarithm can be
- expressed using elementary functions. This can be done using
- ``expand_func()``:
- >>> from sympy import expand_func
- >>> from sympy.abc import z
- >>> expand_func(polylog(1, z))
- -log(1 - z)
- >>> expand_func(polylog(0, z))
- z/(1 - z)
- The derivative with respect to $z$ can be computed in closed form:
- >>> polylog(s, z).diff(z)
- polylog(s - 1, z)/z
- The polylogarithm can be expressed in terms of the lerch transcendent:
- >>> from sympy import lerchphi
- >>> polylog(s, z).rewrite(lerchphi)
- z*lerchphi(z, s, 1)
- See Also
- ========
- zeta, lerchphi
- """
- @classmethod
- def eval(cls, s, z):
- if z.is_number:
- if z is S.One:
- return zeta(s)
- elif z is S.NegativeOne:
- return -dirichlet_eta(s)
- elif z is S.Zero:
- return S.Zero
- elif s == 2:
- dilogtable = _dilogtable()
- if z in dilogtable:
- return dilogtable[z]
- if z.is_zero:
- return S.Zero
- # Make an effort to determine if z is 1 to avoid replacing into
- # expression with singularity
- zone = z.equals(S.One)
- if zone:
- return zeta(s)
- elif zone is False:
- # For s = 0 or -1 use explicit formulas to evaluate, but
- # automatically expanding polylog(1, z) to -log(1-z) seems
- # undesirable for summation methods based on hypergeometric
- # functions
- if s is S.Zero:
- return z/(1 - z)
- elif s is S.NegativeOne:
- return z/(1 - z)**2
- if s.is_zero:
- return z/(1 - z)
- # polylog is branched, but not over the unit disk
- if z.has(exp_polar, polar_lift) and (zone or (Abs(z) <= S.One) == True):
- return cls(s, unpolarify(z))
- def fdiff(self, argindex=1):
- s, z = self.args
- if argindex == 2:
- return polylog(s - 1, z)/z
- raise ArgumentIndexError
- def _eval_rewrite_as_lerchphi(self, s, z, **kwargs):
- return z*lerchphi(z, s, 1)
- def _eval_expand_func(self, **hints):
- s, z = self.args
- if s == 1:
- return -log(1 - z)
- if s.is_Integer and s <= 0:
- u = Dummy('u')
- start = u/(1 - u)
- for _ in range(-s):
- start = u*start.diff(u)
- return expand_mul(start).subs(u, z)
- return polylog(s, z)
- def _eval_is_zero(self):
- z = self.args[1]
- if z.is_zero:
- return True
- def _eval_nseries(self, x, n, logx, cdir=0):
- from sympy.series.order import Order
- nu, z = self.args
- z0 = z.subs(x, 0)
- if z0 is S.NaN:
- z0 = z.limit(x, 0, dir='-' if re(cdir).is_negative else '+')
- if z0.is_zero:
- # In case of powers less than 1, number of terms need to be computed
- # separately to avoid repeated callings of _eval_nseries with wrong n
- try:
- _, exp = z.leadterm(x)
- except (ValueError, NotImplementedError):
- return self
- if exp.is_positive:
- newn = ceiling(n/exp)
- o = Order(x**n, x)
- r = z._eval_nseries(x, n, logx, cdir).removeO()
- if r is S.Zero:
- return o
- term = r
- s = [term]
- for k in range(2, newn):
- term *= r
- s.append(term/k**nu)
- return Add(*s) + o
- return super(polylog, self)._eval_nseries(x, n, logx, cdir)
- ###############################################################################
- ###################### HURWITZ GENERALIZED ZETA FUNCTION ######################
- ###############################################################################
- class zeta(Function):
- r"""
- Hurwitz zeta function (or Riemann zeta function).
- Explanation
- ===========
- For $\operatorname{Re}(a) > 0$ and $\operatorname{Re}(s) > 1$, this
- function is defined as
- .. math:: \zeta(s, a) = \sum_{n=0}^\infty \frac{1}{(n + a)^s},
- where the standard choice of argument for $n + a$ is used. For fixed
- $a$ not a nonpositive integer the Hurwitz zeta function admits a
- meromorphic continuation to all of $\mathbb{C}$; it is an unbranched
- function with a simple pole at $s = 1$.
- The Hurwitz zeta function is a special case of the Lerch transcendent:
- .. math:: \zeta(s, a) = \Phi(1, s, a).
- This formula defines an analytic continuation for all possible values of
- $s$ and $a$ (also $\operatorname{Re}(a) < 0$), see the documentation of
- :class:`lerchphi` for a description of the branching behavior.
- If no value is passed for $a$ a default value of $a = 1$ is assumed,
- yielding the Riemann zeta function.
- Examples
- ========
- For $a = 1$ the Hurwitz zeta function reduces to the famous Riemann
- zeta function:
- .. math:: \zeta(s, 1) = \zeta(s) = \sum_{n=1}^\infty \frac{1}{n^s}.
- >>> from sympy import zeta
- >>> from sympy.abc import s
- >>> zeta(s, 1)
- zeta(s)
- >>> zeta(s)
- zeta(s)
- The Riemann zeta function can also be expressed using the Dirichlet eta
- function:
- >>> from sympy import dirichlet_eta
- >>> zeta(s).rewrite(dirichlet_eta)
- dirichlet_eta(s)/(1 - 2**(1 - s))
- The Riemann zeta function at nonnegative even and negative integer
- values is related to the Bernoulli numbers and polynomials:
- >>> zeta(2)
- pi**2/6
- >>> zeta(4)
- pi**4/90
- >>> zeta(0)
- -1/2
- >>> zeta(-1)
- -1/12
- >>> zeta(-4)
- 0
- The specific formulae are:
- .. math:: \zeta(2n) = -\frac{(2\pi i)^{2n} B_{2n}}{2(2n)!}
- .. math:: \zeta(-n,a) = -\frac{B_{n+1}(a)}{n+1}
- No closed-form expressions are known at positive odd integers, but
- numerical evaluation is possible:
- >>> zeta(3).n()
- 1.20205690315959
- The derivative of $\zeta(s, a)$ with respect to $a$ can be computed:
- >>> from sympy.abc import a
- >>> zeta(s, a).diff(a)
- -s*zeta(s + 1, a)
- However the derivative with respect to $s$ has no useful closed form
- expression:
- >>> zeta(s, a).diff(s)
- Derivative(zeta(s, a), s)
- The Hurwitz zeta function can be expressed in terms of the Lerch
- transcendent, :class:`~.lerchphi`:
- >>> from sympy import lerchphi
- >>> zeta(s, a).rewrite(lerchphi)
- lerchphi(1, s, a)
- See Also
- ========
- dirichlet_eta, lerchphi, polylog
- References
- ==========
- .. [1] https://dlmf.nist.gov/25.11
- .. [2] https://en.wikipedia.org/wiki/Hurwitz_zeta_function
- """
- @classmethod
- def eval(cls, s, a=None):
- if a is S.One:
- return cls(s)
- elif s is S.NaN or a is S.NaN:
- return S.NaN
- elif s is S.One:
- return S.ComplexInfinity
- elif s is S.Infinity:
- return S.One
- elif a is S.Infinity:
- return S.Zero
- sint = s.is_Integer
- if a is None:
- a = S.One
- if sint and s.is_nonpositive:
- return bernoulli(1-s, a) / (s-1)
- elif a is S.One:
- if sint and s.is_even:
- return -(2*pi*I)**s * bernoulli(s) / (2*factorial(s))
- elif sint and a.is_Integer and a.is_positive:
- return cls(s) - harmonic(a-1, s)
- elif a.is_Integer and a.is_nonpositive and \
- (s.is_integer is False or s.is_nonpositive is False):
- return S.NaN
- def _eval_rewrite_as_bernoulli(self, s, a=1, **kwargs):
- if a == 1 and s.is_integer and s.is_nonnegative and s.is_even:
- return -(2*pi*I)**s * bernoulli(s) / (2*factorial(s))
- return bernoulli(1-s, a) / (s-1)
- def _eval_rewrite_as_dirichlet_eta(self, s, a=1, **kwargs):
- if a != 1:
- return self
- s = self.args[0]
- return dirichlet_eta(s)/(1 - 2**(1 - s))
- def _eval_rewrite_as_lerchphi(self, s, a=1, **kwargs):
- return lerchphi(1, s, a)
- def _eval_is_finite(self):
- arg_is_one = (self.args[0] - 1).is_zero
- if arg_is_one is not None:
- return not arg_is_one
- def _eval_expand_func(self, **hints):
- s = self.args[0]
- a = self.args[1] if len(self.args) > 1 else S.One
- if a.is_integer:
- if a.is_positive:
- return zeta(s) - harmonic(a-1, s)
- if a.is_nonpositive and (s.is_integer is False or
- s.is_nonpositive is False):
- return S.NaN
- return self
- def fdiff(self, argindex=1):
- if len(self.args) == 2:
- s, a = self.args
- else:
- s, a = self.args + (1,)
- if argindex == 2:
- return -s*zeta(s + 1, a)
- else:
- raise ArgumentIndexError
- def _eval_as_leading_term(self, x, logx=None, cdir=0):
- if len(self.args) == 2:
- s, a = self.args
- else:
- s, a = self.args + (S.One,)
- try:
- c, e = a.leadterm(x)
- except NotImplementedError:
- return self
- if e.is_negative and not s.is_positive:
- raise NotImplementedError
- return super(zeta, self)._eval_as_leading_term(x, logx, cdir)
- class dirichlet_eta(Function):
- r"""
- Dirichlet eta function.
- Explanation
- ===========
- For $\operatorname{Re}(s) > 0$ and $0 < x \le 1$, this function is defined as
- .. math:: \eta(s, a) = \sum_{n=0}^\infty \frac{(-1)^n}{(n+a)^s}.
- It admits a unique analytic continuation to all of $\mathbb{C}$ for any
- fixed $a$ not a nonpositive integer. It is an entire, unbranched function.
- It can be expressed using the Hurwitz zeta function as
- .. math:: \eta(s, a) = \zeta(s,a) - 2^{1-s} \zeta\left(s, \frac{a+1}{2}\right)
- and using the generalized Genocchi function as
- .. math:: \eta(s, a) = \frac{G(1-s, a)}{2(s-1)}.
- In both cases the limiting value of $\log2 - \psi(a) + \psi\left(\frac{a+1}{2}\right)$
- is used when $s = 1$.
- Examples
- ========
- >>> from sympy import dirichlet_eta, zeta
- >>> from sympy.abc import s
- >>> dirichlet_eta(s).rewrite(zeta)
- Piecewise((log(2), Eq(s, 1)), ((1 - 2**(1 - s))*zeta(s), True))
- See Also
- ========
- zeta
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Dirichlet_eta_function
- .. [2] Peter Luschny, "An introduction to the Bernoulli function",
- https://arxiv.org/abs/2009.06743
- """
- @classmethod
- def eval(cls, s, a=None):
- if a is S.One:
- return cls(s)
- if a is None:
- if s == 1:
- return log(2)
- z = zeta(s)
- if not z.has(zeta):
- return (1 - 2**(1-s)) * z
- return
- elif s == 1:
- from sympy.functions.special.gamma_functions import digamma
- return log(2) - digamma(a) + digamma((a+1)/2)
- z1 = zeta(s, a)
- z2 = zeta(s, (a+1)/2)
- if not z1.has(zeta) and not z2.has(zeta):
- return z1 - 2**(1-s) * z2
- def _eval_rewrite_as_zeta(self, s, a=1, **kwargs):
- from sympy.functions.special.gamma_functions import digamma
- if a == 1:
- return Piecewise((log(2), Eq(s, 1)), ((1 - 2**(1-s)) * zeta(s), True))
- return Piecewise((log(2) - digamma(a) + digamma((a+1)/2), Eq(s, 1)),
- (zeta(s, a) - 2**(1-s) * zeta(s, (a+1)/2), True))
- def _eval_rewrite_as_genocchi(self, s, a=S.One, **kwargs):
- from sympy.functions.special.gamma_functions import digamma
- return Piecewise((log(2) - digamma(a) + digamma((a+1)/2), Eq(s, 1)),
- (genocchi(1-s, a) / (2 * (s-1)), True))
- def _eval_evalf(self, prec):
- if all(i.is_number for i in self.args):
- return self.rewrite(zeta)._eval_evalf(prec)
- class riemann_xi(Function):
- r"""
- Riemann Xi function.
- Examples
- ========
- The Riemann Xi function is closely related to the Riemann zeta function.
- The zeros of Riemann Xi function are precisely the non-trivial zeros
- of the zeta function.
- >>> from sympy import riemann_xi, zeta
- >>> from sympy.abc import s
- >>> riemann_xi(s).rewrite(zeta)
- s*(s - 1)*gamma(s/2)*zeta(s)/(2*pi**(s/2))
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Riemann_Xi_function
- """
- @classmethod
- def eval(cls, s):
- from sympy.functions.special.gamma_functions import gamma
- z = zeta(s)
- if s in (S.Zero, S.One):
- return S.Half
- if not isinstance(z, zeta):
- return s*(s - 1)*gamma(s/2)*z/(2*pi**(s/2))
- def _eval_rewrite_as_zeta(self, s, **kwargs):
- from sympy.functions.special.gamma_functions import gamma
- return s*(s - 1)*gamma(s/2)*zeta(s)/(2*pi**(s/2))
- class stieltjes(Function):
- r"""
- Represents Stieltjes constants, $\gamma_{k}$ that occur in
- Laurent Series expansion of the Riemann zeta function.
- Examples
- ========
- >>> from sympy import stieltjes
- >>> from sympy.abc import n, m
- >>> stieltjes(n)
- stieltjes(n)
- The zero'th stieltjes constant:
- >>> stieltjes(0)
- EulerGamma
- >>> stieltjes(0, 1)
- EulerGamma
- For generalized stieltjes constants:
- >>> stieltjes(n, m)
- stieltjes(n, m)
- Constants are only defined for integers >= 0:
- >>> stieltjes(-1)
- zoo
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Stieltjes_constants
- """
- @classmethod
- def eval(cls, n, a=None):
- if a is not None:
- a = sympify(a)
- if a is S.NaN:
- return S.NaN
- if a.is_Integer and a.is_nonpositive:
- return S.ComplexInfinity
- if n.is_Number:
- if n is S.NaN:
- return S.NaN
- elif n < 0:
- return S.ComplexInfinity
- elif not n.is_Integer:
- return S.ComplexInfinity
- elif n is S.Zero and a in [None, 1]:
- return S.EulerGamma
- if n.is_extended_negative:
- return S.ComplexInfinity
- if n.is_zero and a in [None, 1]:
- return S.EulerGamma
- if n.is_integer == False:
- return S.ComplexInfinity
- @cacheit
- def _dilogtable():
- return {
- S.Half: pi**2/12 - log(2)**2/2,
- Integer(2) : pi**2/4 - I*pi*log(2),
- -(sqrt(5) - 1)/2 : -pi**2/15 + log((sqrt(5)-1)/2)**2/2,
- -(sqrt(5) + 1)/2 : -pi**2/10 - log((sqrt(5)+1)/2)**2,
- (3 - sqrt(5))/2 : pi**2/15 - log((sqrt(5)-1)/2)**2,
- (sqrt(5) - 1)/2 : pi**2/10 - log((sqrt(5)-1)/2)**2,
- I : I*S.Catalan - pi**2/48,
- -I : -I*S.Catalan - pi**2/48,
- 1 - I : pi**2/16 - I*S.Catalan - pi*I/4*log(2),
- 1 + I : pi**2/16 + I*S.Catalan + pi*I/4*log(2),
- (1 - I)/2 : -log(2)**2/8 + pi*I*log(2)/8 + 5*pi**2/96 - I*S.Catalan
- }
|