Exponential integrals#
AUTHORS:
Benjamin Jones (2011-06-12)
This module provides easy access to many exponential integral special functions. It utilizes Maxima’s special functions package and the mpmath library.
REFERENCES:
[AS1964] Abramowitz and Stegun: Handbook of Mathematical Functions
Online Encyclopedia of Special Function: http://algo.inria.fr/esf/index.html
NIST Digital Library of Mathematical Functions: https://dlmf.nist.gov/
Maxima special functions package
AUTHORS:
Benjamin Jones
Implementations of the classes
Function_exp_integral_*
.David Joyner and William Stein
Authors of the code which was moved from special.py and trans.py. Implementation of
exp_int()
(from sage/functions/special.py). Implementation ofexponential_integral_1()
(from sage/functions/transcendental.py).
- class sage.functions.exp_integral.Function_cos_integral[source]#
Bases:
BuiltinFunction
The trigonometric integral \(\operatorname{Ci}(z)\) defined by
\[\operatorname{Ci}(z) = \gamma + \log(z) + \int_0^z \frac{\cos(t)-1}{t} \; dt,\]where \(\gamma\) is the Euler gamma constant (
euler_gamma
in Sage), see [AS1964] 5.2.1.EXAMPLES:
sage: z = var('z') # needs sage.symbolic sage: cos_integral(z) # needs sage.symbolic cos_integral(z) sage: cos_integral(3.0) # needs mpmath 0.119629786008000 sage: cos_integral(0) # needs sage.symbolic cos_integral(0) sage: N(cos_integral(0)) # needs mpmath -infinity
>>> from sage.all import * >>> z = var('z') # needs sage.symbolic >>> cos_integral(z) # needs sage.symbolic cos_integral(z) >>> cos_integral(RealNumber('3.0')) # needs mpmath 0.119629786008000 >>> cos_integral(Integer(0)) # needs sage.symbolic cos_integral(0) >>> N(cos_integral(Integer(0))) # needs mpmath -infinity
Numerical evaluation for real and complex arguments is handled using mpmath:
sage: cos_integral(3.0) # needs mpmath 0.119629786008000
>>> from sage.all import * >>> cos_integral(RealNumber('3.0')) # needs mpmath 0.119629786008000
The alias
Ci
can be used instead ofcos_integral
:sage: Ci(3.0) # needs mpmath 0.119629786008000
>>> from sage.all import * >>> Ci(RealNumber('3.0')) # needs mpmath 0.119629786008000
Compare
cos_integral(3.0)
to the definition of the value using numerical integration:sage: a = numerical_integral((cos(x)-1)/x, 0, 3)[0] # needs sage.symbolic sage: abs(N(euler_gamma + log(3)) + a - N(cos_integral(3.0))) < 1e-14 # needs sage.symbolic True
>>> from sage.all import * >>> a = numerical_integral((cos(x)-Integer(1))/x, Integer(0), Integer(3))[Integer(0)] # needs sage.symbolic >>> abs(N(euler_gamma + log(Integer(3))) + a - N(cos_integral(RealNumber('3.0')))) < RealNumber('1e-14') # needs sage.symbolic True
Arbitrary precision and complex arguments are handled:
sage: N(cos_integral(3), digits=30) # needs sage.symbolic 0.119629786008000327626472281177 sage: cos_integral(ComplexField(100)(3+I)) # needs sage.symbolic 0.078134230477495714401983633057 - 0.37814733904787920181190368789*I
>>> from sage.all import * >>> N(cos_integral(Integer(3)), digits=Integer(30)) # needs sage.symbolic 0.119629786008000327626472281177 >>> cos_integral(ComplexField(Integer(100))(Integer(3)+I)) # needs sage.symbolic 0.078134230477495714401983633057 - 0.37814733904787920181190368789*I
The limit \(\operatorname{Ci}(z)\) as \(z \to \infty\) is zero:
sage: N(cos_integral(1e23)) # needs mpmath -3.24053937643003e-24
>>> from sage.all import * >>> N(cos_integral(RealNumber('1e23'))) # needs mpmath -3.24053937643003e-24
Symbolic derivatives and integrals are handled by Sage and Maxima:
sage: # needs sage.symbolic sage: x = var('x') sage: f = cos_integral(x) sage: f.diff(x) cos(x)/x sage: f.integrate(x) x*cos_integral(x) - sin(x)
>>> from sage.all import * >>> # needs sage.symbolic >>> x = var('x') >>> f = cos_integral(x) >>> f.diff(x) cos(x)/x >>> f.integrate(x) x*cos_integral(x) - sin(x)
The Nielsen spiral is the parametric plot of (Si(t), Ci(t)):
sage: # needs sage.symbolic sage: t = var('t') sage: f(t) = sin_integral(t) sage: g(t) = cos_integral(t) sage: P = parametric_plot([f, g], (t, 0.5 ,20)) # needs sage.plot sage: show(P, frame=True, axes=False) # needs sage.plot
>>> from sage.all import * >>> # needs sage.symbolic >>> t = var('t') >>> __tmp__=var("t"); f = symbolic_expression(sin_integral(t)).function(t) >>> __tmp__=var("t"); g = symbolic_expression(cos_integral(t)).function(t) >>> P = parametric_plot([f, g], (t, RealNumber('0.5') ,Integer(20))) # needs sage.plot >>> show(P, frame=True, axes=False) # needs sage.plot
ALGORITHM:
Numerical evaluation is handled using mpmath, but symbolics are handled by Sage and Maxima.
REFERENCES:
mpmath documentation: ci
- class sage.functions.exp_integral.Function_cosh_integral[source]#
Bases:
BuiltinFunction
The trigonometric integral \(\operatorname{Chi}(z)\) defined by
\[\operatorname{Chi}(z) = \gamma + \log(z) + \int_0^z \frac{\cosh(t)-1}{t} \; dt,\]see [AS1964] 5.2.4.
EXAMPLES:
sage: z = var('z') # needs sage.symbolic sage: cosh_integral(z) # needs sage.symbolic cosh_integral(z) sage: cosh_integral(3.0) # needs mpmath 4.96039209476561
>>> from sage.all import * >>> z = var('z') # needs sage.symbolic >>> cosh_integral(z) # needs sage.symbolic cosh_integral(z) >>> cosh_integral(RealNumber('3.0')) # needs mpmath 4.96039209476561
Numerical evaluation for real and complex arguments is handled using mpmath:
sage: cosh_integral(1.0) # needs mpmath 0.837866940980208
>>> from sage.all import * >>> cosh_integral(RealNumber('1.0')) # needs mpmath 0.837866940980208
The alias
Chi
can be used instead ofcosh_integral
:sage: Chi(1.0) # needs mpmath 0.837866940980208
>>> from sage.all import * >>> Chi(RealNumber('1.0')) # needs mpmath 0.837866940980208
Here is an example from the mpmath documentation:
sage: f(x) = cosh_integral(x) # needs sage.symbolic sage: find_root(f, 0.1, 1.0) # needs scipy sage.symbolic 0.523822571389...
>>> from sage.all import * >>> __tmp__=var("x"); f = symbolic_expression(cosh_integral(x) ).function(x)# needs sage.symbolic >>> find_root(f, RealNumber('0.1'), RealNumber('1.0')) # needs scipy sage.symbolic 0.523822571389...
Compare
cosh_integral(3.0)
to the definition of the value using numerical integration:sage: a = numerical_integral((cosh(x)-1)/x, 0, 3)[0] # needs sage.symbolic sage: abs(N(euler_gamma + log(3)) + a - N(cosh_integral(3.0))) < 1e-14 # needs sage.symbolic True
>>> from sage.all import * >>> a = numerical_integral((cosh(x)-Integer(1))/x, Integer(0), Integer(3))[Integer(0)] # needs sage.symbolic >>> abs(N(euler_gamma + log(Integer(3))) + a - N(cosh_integral(RealNumber('3.0')))) < RealNumber('1e-14') # needs sage.symbolic True
Arbitrary precision and complex arguments are handled:
sage: N(cosh_integral(3), digits=30) # needs sage.symbolic 4.96039209476560976029791763669 sage: cosh_integral(ComplexField(100)(3+I)) # needs sage.symbolic 3.9096723099686417127843516794 + 3.0547519627014217273323873274*I
>>> from sage.all import * >>> N(cosh_integral(Integer(3)), digits=Integer(30)) # needs sage.symbolic 4.96039209476560976029791763669 >>> cosh_integral(ComplexField(Integer(100))(Integer(3)+I)) # needs sage.symbolic 3.9096723099686417127843516794 + 3.0547519627014217273323873274*I
The limit of \(\operatorname{Chi}(z)\) as \(z \to \infty\) is \(\infty\):
sage: N(cosh_integral(Infinity)) # needs mpmath +infinity
>>> from sage.all import * >>> N(cosh_integral(Infinity)) # needs mpmath +infinity
Symbolic derivatives and integrals are handled by Sage and Maxima:
sage: # needs sage.symbolic sage: x = var('x') sage: f = cosh_integral(x) sage: f.diff(x) cosh(x)/x sage: f.integrate(x) x*cosh_integral(x) - sinh(x)
>>> from sage.all import * >>> # needs sage.symbolic >>> x = var('x') >>> f = cosh_integral(x) >>> f.diff(x) cosh(x)/x >>> f.integrate(x) x*cosh_integral(x) - sinh(x)
ALGORITHM:
Numerical evaluation is handled using mpmath, but symbolics are handled by Sage and Maxima.
REFERENCES:
mpmath documentation: chi
- class sage.functions.exp_integral.Function_exp_integral[source]#
Bases:
BuiltinFunction
The generalized complex exponential integral Ei(z) defined by
\[\operatorname{Ei}(x) = \int_{-\infty}^x \frac{e^t}{t} \; dt\]for x > 0 and for complex arguments by analytic continuation, see [AS1964] 5.1.2.
EXAMPLES:
sage: # needs sage.symbolic sage: Ei(10) Ei(10) sage: Ei(I) Ei(I) sage: Ei(3+I) Ei(I + 3) sage: Ei(10r) Ei(10) sage: Ei(1.3) # needs mpmath 2.72139888023202 sage: Ei(1.3r) # needs mpmath 2.7213988802320235
>>> from sage.all import * >>> # needs sage.symbolic >>> Ei(Integer(10)) Ei(10) >>> Ei(I) Ei(I) >>> Ei(Integer(3)+I) Ei(I + 3) >>> Ei(10) Ei(10) >>> Ei(RealNumber('1.3')) # needs mpmath 2.72139888023202 >>> Ei(1.3) # needs mpmath 2.7213988802320235
The branch cut for this function is along the negative real axis:
sage: Ei(-3 + 0.1*I) # needs sage.symbolic -0.0129379427181693 + 3.13993830250942*I sage: Ei(-3 - 0.1*I) # needs sage.symbolic -0.0129379427181693 - 3.13993830250942*I
>>> from sage.all import * >>> Ei(-Integer(3) + RealNumber('0.1')*I) # needs sage.symbolic -0.0129379427181693 + 3.13993830250942*I >>> Ei(-Integer(3) - RealNumber('0.1')*I) # needs sage.symbolic -0.0129379427181693 - 3.13993830250942*I
The precision for the result is deduced from the precision of the input. Convert the input to a higher precision explicitly if a result with higher precision is desired:
sage: Ei(RealField(300)(1.1)) # needs sage.rings.real_mpfr 2.16737827956340282358378734233807621497112737591639704719499002090327541763352339357795426
>>> from sage.all import * >>> Ei(RealField(Integer(300))(RealNumber('1.1'))) # needs sage.rings.real_mpfr 2.16737827956340282358378734233807621497112737591639704719499002090327541763352339357795426
ALGORITHM: Uses mpmath.
- class sage.functions.exp_integral.Function_exp_integral_e[source]#
Bases:
BuiltinFunction
The generalized complex exponential integral \(E_n(z)\) defined by
\[E_n(z) = \int_1^{\infty} \frac{e^{-z t}}{t^n} \; dt\]for complex numbers \(n\) and \(z\), see [AS1964] 5.1.4.
The special case where \(n = 1\) is denoted in Sage by
exp_integral_e1
.EXAMPLES:
Numerical evaluation is handled using mpmath:
sage: N(exp_integral_e(1, 1)) # needs sage.symbolic 0.219383934395520 sage: exp_integral_e(1, RealField(100)(1)) # needs sage.symbolic 0.21938393439552027367716377546
>>> from sage.all import * >>> N(exp_integral_e(Integer(1), Integer(1))) # needs sage.symbolic 0.219383934395520 >>> exp_integral_e(Integer(1), RealField(Integer(100))(Integer(1))) # needs sage.symbolic 0.21938393439552027367716377546
We can compare this to PARI’s evaluation of
exponential_integral_1()
:sage: N(exponential_integral_1(1)) # needs sage.symbolic 0.219383934395520
>>> from sage.all import * >>> N(exponential_integral_1(Integer(1))) # needs sage.symbolic 0.219383934395520
We can verify one case of [AS1964] 5.1.45, i.e. \(E_n(z) = z^{n-1}\Gamma(1-n,z)\):
sage: N(exp_integral_e(2, 3+I)) # needs sage.symbolic 0.00354575823814662 - 0.00973200528288687*I sage: N((3+I)*gamma(-1, 3+I)) # needs sage.symbolic 0.00354575823814662 - 0.00973200528288687*I
>>> from sage.all import * >>> N(exp_integral_e(Integer(2), Integer(3)+I)) # needs sage.symbolic 0.00354575823814662 - 0.00973200528288687*I >>> N((Integer(3)+I)*gamma(-Integer(1), Integer(3)+I)) # needs sage.symbolic 0.00354575823814662 - 0.00973200528288687*I
Maxima returns the following improper integral as a multiple of
exp_integral_e(1,1)
:sage: uu = integral(e^(-x)*log(x+1), x, 0, oo); uu # needs sage.symbolic e*exp_integral_e(1, 1) sage: uu.n(digits=30) # needs sage.symbolic 0.596347362323194074341078499369
>>> from sage.all import * >>> uu = integral(e**(-x)*log(x+Integer(1)), x, Integer(0), oo); uu # needs sage.symbolic e*exp_integral_e(1, 1) >>> uu.n(digits=Integer(30)) # needs sage.symbolic 0.596347362323194074341078499369
Symbolic derivatives and integrals are handled by Sage and Maxima:
sage: # needs sage.symbolic sage: x = var('x') sage: f = exp_integral_e(2,x) sage: f.diff(x) -exp_integral_e(1, x) sage: f.integrate(x) -exp_integral_e(3, x) sage: f = exp_integral_e(-1, x) sage: f.integrate(x) Ei(-x) - gamma(-1, x)
>>> from sage.all import * >>> # needs sage.symbolic >>> x = var('x') >>> f = exp_integral_e(Integer(2),x) >>> f.diff(x) -exp_integral_e(1, x) >>> f.integrate(x) -exp_integral_e(3, x) >>> f = exp_integral_e(-Integer(1), x) >>> f.integrate(x) Ei(-x) - gamma(-1, x)
Some special values of
exp_integral_e
can be simplified. [AS1964] 5.1.23:sage: exp_integral_e(0, x) # needs sage.symbolic e^(-x)/x
>>> from sage.all import * >>> exp_integral_e(Integer(0), x) # needs sage.symbolic e^(-x)/x
[AS1964] 5.1.24:
sage: # needs sage.symbolic sage: exp_integral_e(6, 0) 1/5 sage: nn = var('nn') sage: assume(nn > 1) sage: f = exp_integral_e(nn, 0) sage: f.simplify() 1/(nn - 1)
>>> from sage.all import * >>> # needs sage.symbolic >>> exp_integral_e(Integer(6), Integer(0)) 1/5 >>> nn = var('nn') >>> assume(nn > Integer(1)) >>> f = exp_integral_e(nn, Integer(0)) >>> f.simplify() 1/(nn - 1)
ALGORITHM:
Numerical evaluation is handled using mpmath, but symbolics are handled by Sage and Maxima.
- class sage.functions.exp_integral.Function_exp_integral_e1[source]#
Bases:
BuiltinFunction
The generalized complex exponential integral \(E_1(z)\) defined by
\[E_1(z) = \int_z^\infty \frac{e^{-t}}{t} \; dt\]see [AS1964] 5.1.4.
EXAMPLES:
sage: exp_integral_e1(x) # needs sage.symbolic exp_integral_e1(x) sage: exp_integral_e1(1.0) # needs mpmath 0.219383934395520
>>> from sage.all import * >>> exp_integral_e1(x) # needs sage.symbolic exp_integral_e1(x) >>> exp_integral_e1(RealNumber('1.0')) # needs mpmath 0.219383934395520
Numerical evaluation is handled using mpmath:
sage: N(exp_integral_e1(1)) # needs sage.symbolic 0.219383934395520 sage: exp_integral_e1(RealField(100)(1)) # needs sage.rings.real_mpfr 0.21938393439552027367716377546
>>> from sage.all import * >>> N(exp_integral_e1(Integer(1))) # needs sage.symbolic 0.219383934395520 >>> exp_integral_e1(RealField(Integer(100))(Integer(1))) # needs sage.rings.real_mpfr 0.21938393439552027367716377546
We can compare this to PARI’s evaluation of
exponential_integral_1()
:sage: N(exp_integral_e1(2.0)) # needs mpmath 0.0489005107080611 sage: N(exponential_integral_1(2.0)) # needs sage.rings.real_mpfr 0.0489005107080611
>>> from sage.all import * >>> N(exp_integral_e1(RealNumber('2.0'))) # needs mpmath 0.0489005107080611 >>> N(exponential_integral_1(RealNumber('2.0'))) # needs sage.rings.real_mpfr 0.0489005107080611
Symbolic derivatives and integrals are handled by Sage and Maxima:
sage: # needs sage.symbolic sage: x = var('x') sage: f = exp_integral_e1(x) sage: f.diff(x) -e^(-x)/x sage: f.integrate(x) -exp_integral_e(2, x)
>>> from sage.all import * >>> # needs sage.symbolic >>> x = var('x') >>> f = exp_integral_e1(x) >>> f.diff(x) -e^(-x)/x >>> f.integrate(x) -exp_integral_e(2, x)
ALGORITHM:
Numerical evaluation is handled using mpmath, but symbolics are handled by Sage and Maxima.
- class sage.functions.exp_integral.Function_log_integral[source]#
Bases:
BuiltinFunction
The logarithmic integral \(\operatorname{li}(z)\) defined by
\[\operatorname{li}(x) = \int_0^z \frac{dt}{\ln(t)} = \operatorname{Ei}(\ln(x))\]for x > 1 and by analytic continuation for complex arguments z (see [AS1964] 5.1.3).
EXAMPLES:
Numerical evaluation for real and complex arguments is handled using mpmath:
sage: N(log_integral(3)) # needs sage.symbolic 2.16358859466719 sage: N(log_integral(3), digits=30) # needs sage.symbolic 2.16358859466719197287692236735 sage: log_integral(ComplexField(100)(3+I)) # needs sage.symbolic 2.2879892769816826157078450911 + 0.87232935488528370139883806779*I sage: log_integral(0) # needs mpmath 0
>>> from sage.all import * >>> N(log_integral(Integer(3))) # needs sage.symbolic 2.16358859466719 >>> N(log_integral(Integer(3)), digits=Integer(30)) # needs sage.symbolic 2.16358859466719197287692236735 >>> log_integral(ComplexField(Integer(100))(Integer(3)+I)) # needs sage.symbolic 2.2879892769816826157078450911 + 0.87232935488528370139883806779*I >>> log_integral(Integer(0)) # needs mpmath 0
Symbolic derivatives and integrals are handled by Sage and Maxima:
sage: # needs sage.symbolic sage: x = var('x') sage: f = log_integral(x) sage: f.diff(x) 1/log(x) sage: f.integrate(x) x*log_integral(x) - Ei(2*log(x))
>>> from sage.all import * >>> # needs sage.symbolic >>> x = var('x') >>> f = log_integral(x) >>> f.diff(x) 1/log(x) >>> f.integrate(x) x*log_integral(x) - Ei(2*log(x))
Here is a test from the mpmath documentation. There are 1,925,320,391,606,803,968,923 many prime numbers less than 1e23. The value of
log_integral(1e23)
is very close to this:sage: log_integral(1e23) # needs mpmath 1.92532039161405e21
>>> from sage.all import * >>> log_integral(RealNumber('1e23')) # needs mpmath 1.92532039161405e21
ALGORITHM:
Numerical evaluation is handled using mpmath, but symbolics are handled by Sage and Maxima.
REFERENCES:
mpmath documentation: logarithmic-integral
- class sage.functions.exp_integral.Function_log_integral_offset[source]#
Bases:
BuiltinFunction
The offset logarithmic integral, or Eulerian logarithmic integral, \(\operatorname{Li}(x)\) is defined by
\[\operatorname{Li}(x) = \int_2^x \frac{dt}{\ln(t)} = \operatorname{li}(x)-\operatorname{li}(2)\]for \(x \ge 2\).
The offset logarithmic integral should also not be confused with the polylogarithm (also denoted by \(\operatorname{Li}(x)\) ), which is implemented as
sage.functions.log.Function_polylog
.\(\operatorname{Li}(x)\) is identical to \(\operatorname{li}(x)\) except that the lower limit of integration is \(2\) rather than \(0\) to avoid the singularity at \(x = 1\) of
\[\frac{1}{\ln(t)}\]See
Function_log_integral
for details of \(\operatorname{li}(x)\). Thus \(\operatorname{Li}(x)\) can also be represented by\[\operatorname{Li}(x) = \operatorname{li}(x)-\operatorname{li}(2)\]So we have:
sage: li(4.5) - li(2.0) - Li(4.5) # needs mpmath 0.000000000000000
>>> from sage.all import * >>> li(RealNumber('4.5')) - li(RealNumber('2.0')) - Li(RealNumber('4.5')) # needs mpmath 0.000000000000000
\(\operatorname{Li}(x)\) is extended to complex arguments \(z\) by analytic continuation (see [AS1964] 5.1.3):
sage: Li(6.6 + 5.4*I) # needs sage.symbolic 3.97032201503632 + 2.62311237593572*I
>>> from sage.all import * >>> Li(RealNumber('6.6') + RealNumber('5.4')*I) # needs sage.symbolic 3.97032201503632 + 2.62311237593572*I
The function \(\operatorname{Li}\) is an approximation for the number of primes up to \(x\). In fact, the famous Riemann Hypothesis is
\[|\pi(x) - \operatorname{Li}(x)| \leq \sqrt{x} \log(x).\]For “small” \(x\), \(\operatorname{Li}(x)\) is always slightly bigger than \(\pi(x)\). However it is a theorem that there are very large values of \(x\) (e.g., around \(10^{316}\)), such that \(\exists x: \pi(x) > \operatorname{Li}(x)\). See “A new bound for the smallest x with \(\pi(x) > \operatorname{li}(x)\)”, Bays and Hudson, Mathematics of Computation, 69 (2000) 1285-1296.
Note
Definite integration returns a part symbolic and part numerical result. This is because when Li(x) is evaluated it is passed as li(x)-li(2).
EXAMPLES:
Numerical evaluation for real and complex arguments is handled using mpmath:
sage: # needs sage.symbolic sage: N(log_integral_offset(3)) 1.11842481454970 sage: N(log_integral_offset(3), digits=30) 1.11842481454969918803233347815 sage: log_integral_offset(ComplexField(100)(3+I)) 1.2428254968641898308632562019 + 0.87232935488528370139883806779*I sage: log_integral_offset(2) 0 sage: for n in range(1,7): # needs primecountpy ....: print('%-10s%-10s%-20s'%(10^n, prime_pi(10^n), N(Li(10^n)))) 10 4 5.12043572466980 100 25 29.0809778039621 1000 168 176.564494210035 10000 1229 1245.09205211927 100000 9592 9628.76383727068 1000000 78498 78626.5039956821
>>> from sage.all import * >>> # needs sage.symbolic >>> N(log_integral_offset(Integer(3))) 1.11842481454970 >>> N(log_integral_offset(Integer(3)), digits=Integer(30)) 1.11842481454969918803233347815 >>> log_integral_offset(ComplexField(Integer(100))(Integer(3)+I)) 1.2428254968641898308632562019 + 0.87232935488528370139883806779*I >>> log_integral_offset(Integer(2)) 0 >>> for n in range(Integer(1),Integer(7)): # needs primecountpy ... print('%-10s%-10s%-20s'%(Integer(10)**n, prime_pi(Integer(10)**n), N(Li(Integer(10)**n)))) 10 4 5.12043572466980 100 25 29.0809778039621 1000 168 176.564494210035 10000 1229 1245.09205211927 100000 9592 9628.76383727068 1000000 78498 78626.5039956821
Here is a test from the mpmath documentation. There are 1,925,320,391,606,803,968,923 prime numbers less than 1e23. The value of
log_integral_offset(1e23)
is very close to this:sage: log_integral_offset(1e23) # needs mpmath 1.92532039161405e21
>>> from sage.all import * >>> log_integral_offset(RealNumber('1e23')) # needs mpmath 1.92532039161405e21
Symbolic derivatives are handled by Sage and integration by Maxima:
sage: # needs sage.symbolic sage: x = var('x') sage: f = log_integral_offset(x) sage: f.diff(x) 1/log(x) sage: f.integrate(x) -x*log_integral(2) + x*log_integral(x) - Ei(2*log(x)) sage: Li(x).integrate(x, 2.0, 4.5).n(digits=10) 3.186411697 sage: N(f.integrate(x, 2.0, 3.0)) # abs tol 1e-15 0.601621785860587
>>> from sage.all import * >>> # needs sage.symbolic >>> x = var('x') >>> f = log_integral_offset(x) >>> f.diff(x) 1/log(x) >>> f.integrate(x) -x*log_integral(2) + x*log_integral(x) - Ei(2*log(x)) >>> Li(x).integrate(x, RealNumber('2.0'), RealNumber('4.5')).n(digits=Integer(10)) 3.186411697 >>> N(f.integrate(x, RealNumber('2.0'), RealNumber('3.0'))) # abs tol 1e-15 0.601621785860587
ALGORITHM:
Numerical evaluation is handled using mpmath, but symbolics are handled by Sage and Maxima.
REFERENCES:
mpmath documentation: logarithmic-integral
- class sage.functions.exp_integral.Function_sin_integral[source]#
Bases:
BuiltinFunction
The trigonometric integral \(\operatorname{Si}(z)\) defined by
\[\operatorname{Si}(z) = \int_0^z \frac{\sin(t)}{t} \; dt,\]see [AS1964] 5.2.1.
EXAMPLES:
Numerical evaluation for real and complex arguments is handled using mpmath:
sage: sin_integral(0) # needs mpmath 0 sage: sin_integral(0.0) # needs mpmath 0.000000000000000 sage: sin_integral(3.0) # needs mpmath 1.84865252799947 sage: N(sin_integral(3), digits=30) # needs sage.symbolic 1.84865252799946825639773025111 sage: sin_integral(ComplexField(100)(3+I)) # needs sage.symbolic 2.0277151656451253616038525998 + 0.015210926166954211913653130271*I
>>> from sage.all import * >>> sin_integral(Integer(0)) # needs mpmath 0 >>> sin_integral(RealNumber('0.0')) # needs mpmath 0.000000000000000 >>> sin_integral(RealNumber('3.0')) # needs mpmath 1.84865252799947 >>> N(sin_integral(Integer(3)), digits=Integer(30)) # needs sage.symbolic 1.84865252799946825639773025111 >>> sin_integral(ComplexField(Integer(100))(Integer(3)+I)) # needs sage.symbolic 2.0277151656451253616038525998 + 0.015210926166954211913653130271*I
The alias
Si
can be used instead ofsin_integral
:sage: Si(3.0) # needs mpmath 1.84865252799947
>>> from sage.all import * >>> Si(RealNumber('3.0')) # needs mpmath 1.84865252799947
The limit of \(\operatorname{Si}(z)\) as \(z \to \infty\) is \(\pi/2\):
sage: N(sin_integral(1e23)) # needs mpmath 1.57079632679490 sage: N(pi/2) # needs sage.symbolic 1.57079632679490
>>> from sage.all import * >>> N(sin_integral(RealNumber('1e23'))) # needs mpmath 1.57079632679490 >>> N(pi/Integer(2)) # needs sage.symbolic 1.57079632679490
At 200 bits of precision \(\operatorname{Si}(10^{23})\) agrees with \(\pi/2\) up to \(10^{-24}\):
sage: sin_integral(RealField(200)(1e23)) # needs sage.rings.real_mpfr 1.5707963267948966192313288218697837425815368604836679189519 sage: N(pi/2, prec=200) # needs sage.symbolic 1.5707963267948966192313216916397514420985846996875529104875
>>> from sage.all import * >>> sin_integral(RealField(Integer(200))(RealNumber('1e23'))) # needs sage.rings.real_mpfr 1.5707963267948966192313288218697837425815368604836679189519 >>> N(pi/Integer(2), prec=Integer(200)) # needs sage.symbolic 1.5707963267948966192313216916397514420985846996875529104875
The exponential sine integral is analytic everywhere:
sage: sin_integral(-1.0) # needs mpmath -0.946083070367183 sage: sin_integral(-2.0) # needs mpmath -1.60541297680269 sage: sin_integral(-1e23) # needs mpmath -1.57079632679490
>>> from sage.all import * >>> sin_integral(-RealNumber('1.0')) # needs mpmath -0.946083070367183 >>> sin_integral(-RealNumber('2.0')) # needs mpmath -1.60541297680269 >>> sin_integral(-RealNumber('1e23')) # needs mpmath -1.57079632679490
Symbolic derivatives and integrals are handled by Sage and Maxima:
sage: # needs sage.symbolic sage: x = var('x') sage: f = sin_integral(x) sage: f.diff(x) sin(x)/x sage: f.integrate(x) x*sin_integral(x) + cos(x) sage: integrate(sin(x)/x, x) -1/2*I*Ei(I*x) + 1/2*I*Ei(-I*x)
>>> from sage.all import * >>> # needs sage.symbolic >>> x = var('x') >>> f = sin_integral(x) >>> f.diff(x) sin(x)/x >>> f.integrate(x) x*sin_integral(x) + cos(x) >>> integrate(sin(x)/x, x) -1/2*I*Ei(I*x) + 1/2*I*Ei(-I*x)
Compare values of the functions \(\operatorname{Si}(x)\) and \(f(x) = (1/2)i \cdot \operatorname{Ei}(-ix) - (1/2)i \cdot \operatorname{Ei}(ix) - \pi/2\), which are both anti-derivatives of \(\sin(x)/x\), at some random positive real numbers:
sage: f(x) = 1/2*I*Ei(-I*x) - 1/2*I*Ei(I*x) - pi/2 # needs sage.symbolic sage: g(x) = sin_integral(x) # needs sage.symbolic sage: R = [abs(RDF.random_element()) for i in range(100)] sage: all(abs(f(x) - g(x)) < 1e-10 for x in R) # needs sage.symbolic True
>>> from sage.all import * >>> __tmp__=var("x"); f = symbolic_expression(Integer(1)/Integer(2)*I*Ei(-I*x) - Integer(1)/Integer(2)*I*Ei(I*x) - pi/Integer(2) ).function(x)# needs sage.symbolic >>> __tmp__=var("x"); g = symbolic_expression(sin_integral(x) ).function(x)# needs sage.symbolic >>> R = [abs(RDF.random_element()) for i in range(Integer(100))] >>> all(abs(f(x) - g(x)) < RealNumber('1e-10') for x in R) # needs sage.symbolic True
The Nielsen spiral is the parametric plot of (Si(t), Ci(t)):
sage: # needs sage.symbolic sage: x = var('x') sage: f(x) = sin_integral(x) sage: g(x) = cos_integral(x) sage: P = parametric_plot([f, g], (x, 0.5 ,20)) # needs sage.plot sage: show(P, frame=True, axes=False) # needs sage.plot
>>> from sage.all import * >>> # needs sage.symbolic >>> x = var('x') >>> __tmp__=var("x"); f = symbolic_expression(sin_integral(x)).function(x) >>> __tmp__=var("x"); g = symbolic_expression(cos_integral(x)).function(x) >>> P = parametric_plot([f, g], (x, RealNumber('0.5') ,Integer(20))) # needs sage.plot >>> show(P, frame=True, axes=False) # needs sage.plot
ALGORITHM:
Numerical evaluation is handled using mpmath, but symbolics are handled by Sage and Maxima.
REFERENCES:
mpmath documentation: si
- class sage.functions.exp_integral.Function_sinh_integral[source]#
Bases:
BuiltinFunction
The trigonometric integral \(\operatorname{Shi}(z)\) defined by
\[\operatorname{Shi}(z) = \int_0^z \frac{\sinh(t)}{t} \; dt,\]see [AS1964] 5.2.3.
EXAMPLES:
Numerical evaluation for real and complex arguments is handled using mpmath:
sage: sinh_integral(3.0) # needs mpmath 4.97344047585981 sage: sinh_integral(1.0) # needs mpmath 1.05725087537573 sage: sinh_integral(-1.0) # needs mpmath -1.05725087537573
>>> from sage.all import * >>> sinh_integral(RealNumber('3.0')) # needs mpmath 4.97344047585981 >>> sinh_integral(RealNumber('1.0')) # needs mpmath 1.05725087537573 >>> sinh_integral(-RealNumber('1.0')) # needs mpmath -1.05725087537573
The alias
Shi
can be used instead ofsinh_integral
:sage: Shi(3.0) # needs mpmath 4.97344047585981
>>> from sage.all import * >>> Shi(RealNumber('3.0')) # needs mpmath 4.97344047585981
Compare
sinh_integral(3.0)
to the definition of the value using numerical integration:sage: a = numerical_integral(sinh(x)/x, 0, 3)[0] # needs sage.symbolic sage: abs(a - N(sinh_integral(3))) < 1e-14 # needs sage.symbolic True
>>> from sage.all import * >>> a = numerical_integral(sinh(x)/x, Integer(0), Integer(3))[Integer(0)] # needs sage.symbolic >>> abs(a - N(sinh_integral(Integer(3)))) < RealNumber('1e-14') # needs sage.symbolic True
Arbitrary precision and complex arguments are handled:
sage: N(sinh_integral(3), digits=30) # needs sage.symbolic 4.97344047585980679771041838252 sage: sinh_integral(ComplexField(100)(3+I)) # needs sage.symbolic 3.9134623660329374406788354078 + 3.0427678212908839256360163759*I
>>> from sage.all import * >>> N(sinh_integral(Integer(3)), digits=Integer(30)) # needs sage.symbolic 4.97344047585980679771041838252 >>> sinh_integral(ComplexField(Integer(100))(Integer(3)+I)) # needs sage.symbolic 3.9134623660329374406788354078 + 3.0427678212908839256360163759*I
The limit \(\operatorname{Shi}(z)\) as \(z \to \infty\) is \(\infty\):
sage: N(sinh_integral(Infinity)) # needs mpmath +infinity
>>> from sage.all import * >>> N(sinh_integral(Infinity)) # needs mpmath +infinity
Symbolic derivatives and integrals are handled by Sage and Maxima:
sage: x = var('x') # needs sage.symbolic sage: f = sinh_integral(x) # needs sage.symbolic sage: f.diff(x) # needs sage.symbolic sinh(x)/x sage: f.integrate(x) # needs sage.symbolic x*sinh_integral(x) - cosh(x)
>>> from sage.all import * >>> x = var('x') # needs sage.symbolic >>> f = sinh_integral(x) # needs sage.symbolic >>> f.diff(x) # needs sage.symbolic sinh(x)/x >>> f.integrate(x) # needs sage.symbolic x*sinh_integral(x) - cosh(x)
Note that due to some problems with the way Maxima handles these expressions, definite integrals can sometimes give unexpected results (typically when using inexact endpoints) due to inconsistent branching:
sage: integrate(sinh_integral(x), x, 0, 1/2) # needs sage.symbolic -cosh(1/2) + 1/2*sinh_integral(1/2) + 1 sage: integrate(sinh_integral(x), x, 0, 1/2).n() # correct # needs sage.symbolic 0.125872409703453 sage: integrate(sinh_integral(x), x, 0, 0.5).n() # fixed in maxima 5.29.1 # needs sage.symbolic 0.125872409703453
>>> from sage.all import * >>> integrate(sinh_integral(x), x, Integer(0), Integer(1)/Integer(2)) # needs sage.symbolic -cosh(1/2) + 1/2*sinh_integral(1/2) + 1 >>> integrate(sinh_integral(x), x, Integer(0), Integer(1)/Integer(2)).n() # correct # needs sage.symbolic 0.125872409703453 >>> integrate(sinh_integral(x), x, Integer(0), RealNumber('0.5')).n() # fixed in maxima 5.29.1 # needs sage.symbolic 0.125872409703453
ALGORITHM:
Numerical evaluation is handled using mpmath, but symbolics are handled by Sage and Maxima.
REFERENCES:
mpmath documentation: shi
- sage.functions.exp_integral.exponential_integral_1(x, n=0)[source]#
Returns the exponential integral \(E_1(x)\). If the optional argument \(n\) is given, computes list of the first \(n\) values of the exponential integral \(E_1(x m)\).
The exponential integral \(E_1(x)\) is
\[E_1(x) = \int_{x}^{\infty} \frac{e^{-t}}{t} \; dt\]INPUT:
x
– a positive real numbern
– (default: 0) a nonnegative integer; if nonzero, then return a list of valuesE_1(x*m)
for m = 1,2,3,…,n. This is useful, e.g., when computing derivatives of L-functions.
OUTPUT:
A real number if n is 0 (the default) or a list of reals if n > 0. The precision is the same as the input, with a default of 53 bits in case the input is exact.
EXAMPLES:
sage: # needs sage.libs.pari sage.rings.real_mpfr sage: exponential_integral_1(2) 0.0489005107080611 sage: exponential_integral_1(2, 4) # abs tol 1e-18 [0.0489005107080611, 0.00377935240984891, 0.000360082452162659, 0.0000376656228439245] sage: exponential_integral_1(40, 5) [0.000000000000000, 2.22854325868847e-37, 6.33732515501151e-55, 2.02336191509997e-72, 6.88522610630764e-90] sage: r = exponential_integral_1(RealField(150)(1)); r 0.21938393439552027367716377546012164903104729 sage: parent(r) Real Field with 150 bits of precision sage: exponential_integral_1(RealField(150)(100)) 3.6835977616820321802351926205081189876552201e-46 sage: exponential_integral_1(0) +Infinity
>>> from sage.all import * >>> # needs sage.libs.pari sage.rings.real_mpfr >>> exponential_integral_1(Integer(2)) 0.0489005107080611 >>> exponential_integral_1(Integer(2), Integer(4)) # abs tol 1e-18 [0.0489005107080611, 0.00377935240984891, 0.000360082452162659, 0.0000376656228439245] >>> exponential_integral_1(Integer(40), Integer(5)) [0.000000000000000, 2.22854325868847e-37, 6.33732515501151e-55, 2.02336191509997e-72, 6.88522610630764e-90] >>> r = exponential_integral_1(RealField(Integer(150))(Integer(1))); r 0.21938393439552027367716377546012164903104729 >>> parent(r) Real Field with 150 bits of precision >>> exponential_integral_1(RealField(Integer(150))(Integer(100))) 3.6835977616820321802351926205081189876552201e-46 >>> exponential_integral_1(Integer(0)) +Infinity
ALGORITHM: use the PARI C-library function pari:eint1.
REFERENCE:
See Proposition 5.6.12 of Cohen’s book “A Course in Computational Algebraic Number Theory”.