m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2731 lines
75 KiB

6 months ago
  1. """ This module contains various functions that are special cases
  2. of incomplete gamma functions. It should probably be renamed. """
  3. from sympy.core import Add, S, sympify, cacheit, pi, I, Rational, EulerGamma
  4. from sympy.core.function import Function, ArgumentIndexError, expand_mul
  5. from sympy.core.relational import is_eq
  6. from sympy.core.power import Pow
  7. from sympy.core.symbol import Symbol
  8. from sympy.functions.combinatorial.factorials import factorial, factorial2, RisingFactorial
  9. from sympy.functions.elementary.complexes import re
  10. from sympy.functions.elementary.integers import floor
  11. from sympy.functions.elementary.miscellaneous import sqrt, root
  12. from sympy.functions.elementary.exponential import exp, log, exp_polar
  13. from sympy.functions.elementary.complexes import polar_lift, unpolarify
  14. from sympy.functions.elementary.hyperbolic import cosh, sinh
  15. from sympy.functions.elementary.trigonometric import cos, sin, sinc
  16. from sympy.functions.special.hyper import hyper, meijerg
  17. # TODO series expansions
  18. # TODO see the "Note:" in Ei
  19. # Helper function
  20. def real_to_real_as_real_imag(self, deep=True, **hints):
  21. if self.args[0].is_extended_real:
  22. if deep:
  23. hints['complex'] = False
  24. return (self.expand(deep, **hints), S.Zero)
  25. else:
  26. return (self, S.Zero)
  27. if deep:
  28. x, y = self.args[0].expand(deep, **hints).as_real_imag()
  29. else:
  30. x, y = self.args[0].as_real_imag()
  31. re = (self.func(x + I*y) + self.func(x - I*y))/2
  32. im = (self.func(x + I*y) - self.func(x - I*y))/(2*I)
  33. return (re, im)
  34. ###############################################################################
  35. ################################ ERROR FUNCTION ###############################
  36. ###############################################################################
  37. class erf(Function):
  38. r"""
  39. The Gauss error function.
  40. Explanation
  41. ===========
  42. This function is defined as:
  43. .. math ::
  44. \mathrm{erf}(x) = \frac{2}{\sqrt{\pi}} \int_0^x e^{-t^2} \mathrm{d}t.
  45. Examples
  46. ========
  47. >>> from sympy import I, oo, erf
  48. >>> from sympy.abc import z
  49. Several special values are known:
  50. >>> erf(0)
  51. 0
  52. >>> erf(oo)
  53. 1
  54. >>> erf(-oo)
  55. -1
  56. >>> erf(I*oo)
  57. oo*I
  58. >>> erf(-I*oo)
  59. -oo*I
  60. In general one can pull out factors of -1 and $I$ from the argument:
  61. >>> erf(-z)
  62. -erf(z)
  63. The error function obeys the mirror symmetry:
  64. >>> from sympy import conjugate
  65. >>> conjugate(erf(z))
  66. erf(conjugate(z))
  67. Differentiation with respect to $z$ is supported:
  68. >>> from sympy import diff
  69. >>> diff(erf(z), z)
  70. 2*exp(-z**2)/sqrt(pi)
  71. We can numerically evaluate the error function to arbitrary precision
  72. on the whole complex plane:
  73. >>> erf(4).evalf(30)
  74. 0.999999984582742099719981147840
  75. >>> erf(-4*I).evalf(30)
  76. -1296959.73071763923152794095062*I
  77. See Also
  78. ========
  79. erfc: Complementary error function.
  80. erfi: Imaginary error function.
  81. erf2: Two-argument error function.
  82. erfinv: Inverse error function.
  83. erfcinv: Inverse Complementary error function.
  84. erf2inv: Inverse two-argument error function.
  85. References
  86. ==========
  87. .. [1] https://en.wikipedia.org/wiki/Error_function
  88. .. [2] http://dlmf.nist.gov/7
  89. .. [3] http://mathworld.wolfram.com/Erf.html
  90. .. [4] http://functions.wolfram.com/GammaBetaErf/Erf
  91. """
  92. unbranched = True
  93. def fdiff(self, argindex=1):
  94. if argindex == 1:
  95. return 2*exp(-self.args[0]**2)/sqrt(S.Pi)
  96. else:
  97. raise ArgumentIndexError(self, argindex)
  98. def inverse(self, argindex=1):
  99. """
  100. Returns the inverse of this function.
  101. """
  102. return erfinv
  103. @classmethod
  104. def eval(cls, arg):
  105. if arg.is_Number:
  106. if arg is S.NaN:
  107. return S.NaN
  108. elif arg is S.Infinity:
  109. return S.One
  110. elif arg is S.NegativeInfinity:
  111. return S.NegativeOne
  112. elif arg.is_zero:
  113. return S.Zero
  114. if isinstance(arg, erfinv):
  115. return arg.args[0]
  116. if isinstance(arg, erfcinv):
  117. return S.One - arg.args[0]
  118. if arg.is_zero:
  119. return S.Zero
  120. # Only happens with unevaluated erf2inv
  121. if isinstance(arg, erf2inv) and arg.args[0].is_zero:
  122. return arg.args[1]
  123. # Try to pull out factors of I
  124. t = arg.extract_multiplicatively(S.ImaginaryUnit)
  125. if t in (S.Infinity, S.NegativeInfinity):
  126. return arg
  127. # Try to pull out factors of -1
  128. if arg.could_extract_minus_sign():
  129. return -cls(-arg)
  130. @staticmethod
  131. @cacheit
  132. def taylor_term(n, x, *previous_terms):
  133. if n < 0 or n % 2 == 0:
  134. return S.Zero
  135. else:
  136. x = sympify(x)
  137. k = floor((n - 1)/S(2))
  138. if len(previous_terms) > 2:
  139. return -previous_terms[-2] * x**2 * (n - 2)/(n*k)
  140. else:
  141. return 2*S.NegativeOne**k * x**n/(n*factorial(k)*sqrt(S.Pi))
  142. def _eval_conjugate(self):
  143. return self.func(self.args[0].conjugate())
  144. def _eval_is_real(self):
  145. return self.args[0].is_extended_real
  146. def _eval_is_finite(self):
  147. if self.args[0].is_finite:
  148. return True
  149. else:
  150. return self.args[0].is_extended_real
  151. def _eval_is_zero(self):
  152. return self.args[0].is_zero
  153. def _eval_rewrite_as_uppergamma(self, z, **kwargs):
  154. from sympy.functions.special.gamma_functions import uppergamma
  155. return sqrt(z**2)/z*(S.One - uppergamma(S.Half, z**2)/sqrt(S.Pi))
  156. def _eval_rewrite_as_fresnels(self, z, **kwargs):
  157. arg = (S.One - S.ImaginaryUnit)*z/sqrt(pi)
  158. return (S.One + S.ImaginaryUnit)*(fresnelc(arg) - I*fresnels(arg))
  159. def _eval_rewrite_as_fresnelc(self, z, **kwargs):
  160. arg = (S.One - S.ImaginaryUnit)*z/sqrt(pi)
  161. return (S.One + S.ImaginaryUnit)*(fresnelc(arg) - I*fresnels(arg))
  162. def _eval_rewrite_as_meijerg(self, z, **kwargs):
  163. return z/sqrt(pi)*meijerg([S.Half], [], [0], [Rational(-1, 2)], z**2)
  164. def _eval_rewrite_as_hyper(self, z, **kwargs):
  165. return 2*z/sqrt(pi)*hyper([S.Half], [3*S.Half], -z**2)
  166. def _eval_rewrite_as_expint(self, z, **kwargs):
  167. return sqrt(z**2)/z - z*expint(S.Half, z**2)/sqrt(S.Pi)
  168. def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs):
  169. from sympy.series.limits import limit
  170. if limitvar:
  171. lim = limit(z, limitvar, S.Infinity)
  172. if lim is S.NegativeInfinity:
  173. return S.NegativeOne + _erfs(-z)*exp(-z**2)
  174. return S.One - _erfs(z)*exp(-z**2)
  175. def _eval_rewrite_as_erfc(self, z, **kwargs):
  176. return S.One - erfc(z)
  177. def _eval_rewrite_as_erfi(self, z, **kwargs):
  178. return -I*erfi(I*z)
  179. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  180. arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir)
  181. arg0 = arg.subs(x, 0)
  182. if arg0 is S.ComplexInfinity:
  183. arg0 = arg.limit(x, 0, dir='-' if cdir == -1 else '+')
  184. if x in arg.free_symbols and arg0.is_zero:
  185. return 2*arg/sqrt(pi)
  186. else:
  187. return self.func(arg0)
  188. def _eval_aseries(self, n, args0, x, logx):
  189. from sympy.series.order import Order
  190. from sympy.functions.elementary.integers import ceiling
  191. point = args0[0]
  192. if point in [S.Infinity, S.NegativeInfinity]:
  193. z = self.args[0]
  194. try:
  195. _, ex = z.leadterm(x)
  196. except (ValueError, NotImplementedError):
  197. return self
  198. ex = -ex # as x->1/x for aseries
  199. if ex.is_positive:
  200. newn = ceiling(n/ex)
  201. s = [S.NegativeOne**k * factorial2(2*k - 1) / (z**(2*k + 1) * 2**k)
  202. for k in range(0, newn)] + [Order(1/z**newn, x)]
  203. return S.One - (exp(-z**2)/sqrt(pi)) * Add(*s)
  204. return super(erf, self)._eval_aseries(n, args0, x, logx)
  205. as_real_imag = real_to_real_as_real_imag
  206. class erfc(Function):
  207. r"""
  208. Complementary Error Function.
  209. Explanation
  210. ===========
  211. The function is defined as:
  212. .. math ::
  213. \mathrm{erfc}(x) = \frac{2}{\sqrt{\pi}} \int_x^\infty e^{-t^2} \mathrm{d}t
  214. Examples
  215. ========
  216. >>> from sympy import I, oo, erfc
  217. >>> from sympy.abc import z
  218. Several special values are known:
  219. >>> erfc(0)
  220. 1
  221. >>> erfc(oo)
  222. 0
  223. >>> erfc(-oo)
  224. 2
  225. >>> erfc(I*oo)
  226. -oo*I
  227. >>> erfc(-I*oo)
  228. oo*I
  229. The error function obeys the mirror symmetry:
  230. >>> from sympy import conjugate
  231. >>> conjugate(erfc(z))
  232. erfc(conjugate(z))
  233. Differentiation with respect to $z$ is supported:
  234. >>> from sympy import diff
  235. >>> diff(erfc(z), z)
  236. -2*exp(-z**2)/sqrt(pi)
  237. It also follows
  238. >>> erfc(-z)
  239. 2 - erfc(z)
  240. We can numerically evaluate the complementary error function to arbitrary
  241. precision on the whole complex plane:
  242. >>> erfc(4).evalf(30)
  243. 0.0000000154172579002800188521596734869
  244. >>> erfc(4*I).evalf(30)
  245. 1.0 - 1296959.73071763923152794095062*I
  246. See Also
  247. ========
  248. erf: Gaussian error function.
  249. erfi: Imaginary error function.
  250. erf2: Two-argument error function.
  251. erfinv: Inverse error function.
  252. erfcinv: Inverse Complementary error function.
  253. erf2inv: Inverse two-argument error function.
  254. References
  255. ==========
  256. .. [1] https://en.wikipedia.org/wiki/Error_function
  257. .. [2] http://dlmf.nist.gov/7
  258. .. [3] http://mathworld.wolfram.com/Erfc.html
  259. .. [4] http://functions.wolfram.com/GammaBetaErf/Erfc
  260. """
  261. unbranched = True
  262. def fdiff(self, argindex=1):
  263. if argindex == 1:
  264. return -2*exp(-self.args[0]**2)/sqrt(S.Pi)
  265. else:
  266. raise ArgumentIndexError(self, argindex)
  267. def inverse(self, argindex=1):
  268. """
  269. Returns the inverse of this function.
  270. """
  271. return erfcinv
  272. @classmethod
  273. def eval(cls, arg):
  274. if arg.is_Number:
  275. if arg is S.NaN:
  276. return S.NaN
  277. elif arg is S.Infinity:
  278. return S.Zero
  279. elif arg.is_zero:
  280. return S.One
  281. if isinstance(arg, erfinv):
  282. return S.One - arg.args[0]
  283. if isinstance(arg, erfcinv):
  284. return arg.args[0]
  285. if arg.is_zero:
  286. return S.One
  287. # Try to pull out factors of I
  288. t = arg.extract_multiplicatively(S.ImaginaryUnit)
  289. if t in (S.Infinity, S.NegativeInfinity):
  290. return -arg
  291. # Try to pull out factors of -1
  292. if arg.could_extract_minus_sign():
  293. return 2 - cls(-arg)
  294. @staticmethod
  295. @cacheit
  296. def taylor_term(n, x, *previous_terms):
  297. if n == 0:
  298. return S.One
  299. elif n < 0 or n % 2 == 0:
  300. return S.Zero
  301. else:
  302. x = sympify(x)
  303. k = floor((n - 1)/S(2))
  304. if len(previous_terms) > 2:
  305. return -previous_terms[-2] * x**2 * (n - 2)/(n*k)
  306. else:
  307. return -2*S.NegativeOne**k * x**n/(n*factorial(k)*sqrt(S.Pi))
  308. def _eval_conjugate(self):
  309. return self.func(self.args[0].conjugate())
  310. def _eval_is_real(self):
  311. return self.args[0].is_extended_real
  312. def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs):
  313. return self.rewrite(erf).rewrite("tractable", deep=True, limitvar=limitvar)
  314. def _eval_rewrite_as_erf(self, z, **kwargs):
  315. return S.One - erf(z)
  316. def _eval_rewrite_as_erfi(self, z, **kwargs):
  317. return S.One + I*erfi(I*z)
  318. def _eval_rewrite_as_fresnels(self, z, **kwargs):
  319. arg = (S.One - S.ImaginaryUnit)*z/sqrt(pi)
  320. return S.One - (S.One + S.ImaginaryUnit)*(fresnelc(arg) - I*fresnels(arg))
  321. def _eval_rewrite_as_fresnelc(self, z, **kwargs):
  322. arg = (S.One-S.ImaginaryUnit)*z/sqrt(pi)
  323. return S.One - (S.One + S.ImaginaryUnit)*(fresnelc(arg) - I*fresnels(arg))
  324. def _eval_rewrite_as_meijerg(self, z, **kwargs):
  325. return S.One - z/sqrt(pi)*meijerg([S.Half], [], [0], [Rational(-1, 2)], z**2)
  326. def _eval_rewrite_as_hyper(self, z, **kwargs):
  327. return S.One - 2*z/sqrt(pi)*hyper([S.Half], [3*S.Half], -z**2)
  328. def _eval_rewrite_as_uppergamma(self, z, **kwargs):
  329. from sympy.functions.special.gamma_functions import uppergamma
  330. return S.One - sqrt(z**2)/z*(S.One - uppergamma(S.Half, z**2)/sqrt(S.Pi))
  331. def _eval_rewrite_as_expint(self, z, **kwargs):
  332. return S.One - sqrt(z**2)/z + z*expint(S.Half, z**2)/sqrt(S.Pi)
  333. def _eval_expand_func(self, **hints):
  334. return self.rewrite(erf)
  335. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  336. arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir)
  337. arg0 = arg.subs(x, 0)
  338. if arg0 is S.ComplexInfinity:
  339. arg0 = arg.limit(x, 0, dir='-' if cdir == -1 else '+')
  340. if arg0.is_zero:
  341. return S.One
  342. else:
  343. return self.func(arg0)
  344. as_real_imag = real_to_real_as_real_imag
  345. def _eval_aseries(self, n, args0, x, logx):
  346. return S.One - erf(*self.args)._eval_aseries(n, args0, x, logx)
  347. class erfi(Function):
  348. r"""
  349. Imaginary error function.
  350. Explanation
  351. ===========
  352. The function erfi is defined as:
  353. .. math ::
  354. \mathrm{erfi}(x) = \frac{2}{\sqrt{\pi}} \int_0^x e^{t^2} \mathrm{d}t
  355. Examples
  356. ========
  357. >>> from sympy import I, oo, erfi
  358. >>> from sympy.abc import z
  359. Several special values are known:
  360. >>> erfi(0)
  361. 0
  362. >>> erfi(oo)
  363. oo
  364. >>> erfi(-oo)
  365. -oo
  366. >>> erfi(I*oo)
  367. I
  368. >>> erfi(-I*oo)
  369. -I
  370. In general one can pull out factors of -1 and $I$ from the argument:
  371. >>> erfi(-z)
  372. -erfi(z)
  373. >>> from sympy import conjugate
  374. >>> conjugate(erfi(z))
  375. erfi(conjugate(z))
  376. Differentiation with respect to $z$ is supported:
  377. >>> from sympy import diff
  378. >>> diff(erfi(z), z)
  379. 2*exp(z**2)/sqrt(pi)
  380. We can numerically evaluate the imaginary error function to arbitrary
  381. precision on the whole complex plane:
  382. >>> erfi(2).evalf(30)
  383. 18.5648024145755525987042919132
  384. >>> erfi(-2*I).evalf(30)
  385. -0.995322265018952734162069256367*I
  386. See Also
  387. ========
  388. erf: Gaussian error function.
  389. erfc: Complementary error function.
  390. erf2: Two-argument error function.
  391. erfinv: Inverse error function.
  392. erfcinv: Inverse Complementary error function.
  393. erf2inv: Inverse two-argument error function.
  394. References
  395. ==========
  396. .. [1] https://en.wikipedia.org/wiki/Error_function
  397. .. [2] http://mathworld.wolfram.com/Erfi.html
  398. .. [3] http://functions.wolfram.com/GammaBetaErf/Erfi
  399. """
  400. unbranched = True
  401. def fdiff(self, argindex=1):
  402. if argindex == 1:
  403. return 2*exp(self.args[0]**2)/sqrt(S.Pi)
  404. else:
  405. raise ArgumentIndexError(self, argindex)
  406. @classmethod
  407. def eval(cls, z):
  408. if z.is_Number:
  409. if z is S.NaN:
  410. return S.NaN
  411. elif z.is_zero:
  412. return S.Zero
  413. elif z is S.Infinity:
  414. return S.Infinity
  415. if z.is_zero:
  416. return S.Zero
  417. # Try to pull out factors of -1
  418. if z.could_extract_minus_sign():
  419. return -cls(-z)
  420. # Try to pull out factors of I
  421. nz = z.extract_multiplicatively(I)
  422. if nz is not None:
  423. if nz is S.Infinity:
  424. return I
  425. if isinstance(nz, erfinv):
  426. return I*nz.args[0]
  427. if isinstance(nz, erfcinv):
  428. return I*(S.One - nz.args[0])
  429. # Only happens with unevaluated erf2inv
  430. if isinstance(nz, erf2inv) and nz.args[0].is_zero:
  431. return I*nz.args[1]
  432. @staticmethod
  433. @cacheit
  434. def taylor_term(n, x, *previous_terms):
  435. if n < 0 or n % 2 == 0:
  436. return S.Zero
  437. else:
  438. x = sympify(x)
  439. k = floor((n - 1)/S(2))
  440. if len(previous_terms) > 2:
  441. return previous_terms[-2] * x**2 * (n - 2)/(n*k)
  442. else:
  443. return 2 * x**n/(n*factorial(k)*sqrt(S.Pi))
  444. def _eval_conjugate(self):
  445. return self.func(self.args[0].conjugate())
  446. def _eval_is_extended_real(self):
  447. return self.args[0].is_extended_real
  448. def _eval_is_zero(self):
  449. return self.args[0].is_zero
  450. def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs):
  451. return self.rewrite(erf).rewrite("tractable", deep=True, limitvar=limitvar)
  452. def _eval_rewrite_as_erf(self, z, **kwargs):
  453. return -I*erf(I*z)
  454. def _eval_rewrite_as_erfc(self, z, **kwargs):
  455. return I*erfc(I*z) - I
  456. def _eval_rewrite_as_fresnels(self, z, **kwargs):
  457. arg = (S.One + S.ImaginaryUnit)*z/sqrt(pi)
  458. return (S.One - S.ImaginaryUnit)*(fresnelc(arg) - I*fresnels(arg))
  459. def _eval_rewrite_as_fresnelc(self, z, **kwargs):
  460. arg = (S.One + S.ImaginaryUnit)*z/sqrt(pi)
  461. return (S.One - S.ImaginaryUnit)*(fresnelc(arg) - I*fresnels(arg))
  462. def _eval_rewrite_as_meijerg(self, z, **kwargs):
  463. return z/sqrt(pi)*meijerg([S.Half], [], [0], [Rational(-1, 2)], -z**2)
  464. def _eval_rewrite_as_hyper(self, z, **kwargs):
  465. return 2*z/sqrt(pi)*hyper([S.Half], [3*S.Half], z**2)
  466. def _eval_rewrite_as_uppergamma(self, z, **kwargs):
  467. from sympy.functions.special.gamma_functions import uppergamma
  468. return sqrt(-z**2)/z*(uppergamma(S.Half, -z**2)/sqrt(S.Pi) - S.One)
  469. def _eval_rewrite_as_expint(self, z, **kwargs):
  470. return sqrt(-z**2)/z - z*expint(S.Half, -z**2)/sqrt(S.Pi)
  471. def _eval_expand_func(self, **hints):
  472. return self.rewrite(erf)
  473. as_real_imag = real_to_real_as_real_imag
  474. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  475. arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir)
  476. arg0 = arg.subs(x, 0)
  477. if x in arg.free_symbols and arg0.is_zero:
  478. return 2*arg/sqrt(pi)
  479. elif arg0.is_finite:
  480. return self.func(arg0)
  481. return self.func(arg)
  482. def _eval_aseries(self, n, args0, x, logx):
  483. from sympy.series.order import Order
  484. point = args0[0]
  485. if point is S.Infinity:
  486. z = self.args[0]
  487. s = [factorial2(2*k - 1) / (2**k * z**(2*k + 1))
  488. for k in range(0, n)] + [Order(1/z**n, x)]
  489. return -S.ImaginaryUnit + (exp(z**2)/sqrt(pi)) * Add(*s)
  490. return super(erfi, self)._eval_aseries(n, args0, x, logx)
  491. class erf2(Function):
  492. r"""
  493. Two-argument error function.
  494. Explanation
  495. ===========
  496. This function is defined as:
  497. .. math ::
  498. \mathrm{erf2}(x, y) = \frac{2}{\sqrt{\pi}} \int_x^y e^{-t^2} \mathrm{d}t
  499. Examples
  500. ========
  501. >>> from sympy import oo, erf2
  502. >>> from sympy.abc import x, y
  503. Several special values are known:
  504. >>> erf2(0, 0)
  505. 0
  506. >>> erf2(x, x)
  507. 0
  508. >>> erf2(x, oo)
  509. 1 - erf(x)
  510. >>> erf2(x, -oo)
  511. -erf(x) - 1
  512. >>> erf2(oo, y)
  513. erf(y) - 1
  514. >>> erf2(-oo, y)
  515. erf(y) + 1
  516. In general one can pull out factors of -1:
  517. >>> erf2(-x, -y)
  518. -erf2(x, y)
  519. The error function obeys the mirror symmetry:
  520. >>> from sympy import conjugate
  521. >>> conjugate(erf2(x, y))
  522. erf2(conjugate(x), conjugate(y))
  523. Differentiation with respect to $x$, $y$ is supported:
  524. >>> from sympy import diff
  525. >>> diff(erf2(x, y), x)
  526. -2*exp(-x**2)/sqrt(pi)
  527. >>> diff(erf2(x, y), y)
  528. 2*exp(-y**2)/sqrt(pi)
  529. See Also
  530. ========
  531. erf: Gaussian error function.
  532. erfc: Complementary error function.
  533. erfi: Imaginary error function.
  534. erfinv: Inverse error function.
  535. erfcinv: Inverse Complementary error function.
  536. erf2inv: Inverse two-argument error function.
  537. References
  538. ==========
  539. .. [1] http://functions.wolfram.com/GammaBetaErf/Erf2/
  540. """
  541. def fdiff(self, argindex):
  542. x, y = self.args
  543. if argindex == 1:
  544. return -2*exp(-x**2)/sqrt(S.Pi)
  545. elif argindex == 2:
  546. return 2*exp(-y**2)/sqrt(S.Pi)
  547. else:
  548. raise ArgumentIndexError(self, argindex)
  549. @classmethod
  550. def eval(cls, x, y):
  551. chk = (S.Infinity, S.NegativeInfinity, S.Zero)
  552. if x is S.NaN or y is S.NaN:
  553. return S.NaN
  554. elif x == y:
  555. return S.Zero
  556. elif x in chk or y in chk:
  557. return erf(y) - erf(x)
  558. if isinstance(y, erf2inv) and y.args[0] == x:
  559. return y.args[1]
  560. if x.is_zero or y.is_zero or x.is_extended_real and x.is_infinite or \
  561. y.is_extended_real and y.is_infinite:
  562. return erf(y) - erf(x)
  563. #Try to pull out -1 factor
  564. sign_x = x.could_extract_minus_sign()
  565. sign_y = y.could_extract_minus_sign()
  566. if (sign_x and sign_y):
  567. return -cls(-x, -y)
  568. elif (sign_x or sign_y):
  569. return erf(y)-erf(x)
  570. def _eval_conjugate(self):
  571. return self.func(self.args[0].conjugate(), self.args[1].conjugate())
  572. def _eval_is_extended_real(self):
  573. return self.args[0].is_extended_real and self.args[1].is_extended_real
  574. def _eval_rewrite_as_erf(self, x, y, **kwargs):
  575. return erf(y) - erf(x)
  576. def _eval_rewrite_as_erfc(self, x, y, **kwargs):
  577. return erfc(x) - erfc(y)
  578. def _eval_rewrite_as_erfi(self, x, y, **kwargs):
  579. return I*(erfi(I*x)-erfi(I*y))
  580. def _eval_rewrite_as_fresnels(self, x, y, **kwargs):
  581. return erf(y).rewrite(fresnels) - erf(x).rewrite(fresnels)
  582. def _eval_rewrite_as_fresnelc(self, x, y, **kwargs):
  583. return erf(y).rewrite(fresnelc) - erf(x).rewrite(fresnelc)
  584. def _eval_rewrite_as_meijerg(self, x, y, **kwargs):
  585. return erf(y).rewrite(meijerg) - erf(x).rewrite(meijerg)
  586. def _eval_rewrite_as_hyper(self, x, y, **kwargs):
  587. return erf(y).rewrite(hyper) - erf(x).rewrite(hyper)
  588. def _eval_rewrite_as_uppergamma(self, x, y, **kwargs):
  589. from sympy.functions.special.gamma_functions import uppergamma
  590. return (sqrt(y**2)/y*(S.One - uppergamma(S.Half, y**2)/sqrt(S.Pi)) -
  591. sqrt(x**2)/x*(S.One - uppergamma(S.Half, x**2)/sqrt(S.Pi)))
  592. def _eval_rewrite_as_expint(self, x, y, **kwargs):
  593. return erf(y).rewrite(expint) - erf(x).rewrite(expint)
  594. def _eval_expand_func(self, **hints):
  595. return self.rewrite(erf)
  596. def _eval_is_zero(self):
  597. return is_eq(*self.args)
  598. class erfinv(Function):
  599. r"""
  600. Inverse Error Function. The erfinv function is defined as:
  601. .. math ::
  602. \mathrm{erf}(x) = y \quad \Rightarrow \quad \mathrm{erfinv}(y) = x
  603. Examples
  604. ========
  605. >>> from sympy import erfinv
  606. >>> from sympy.abc import x
  607. Several special values are known:
  608. >>> erfinv(0)
  609. 0
  610. >>> erfinv(1)
  611. oo
  612. Differentiation with respect to $x$ is supported:
  613. >>> from sympy import diff
  614. >>> diff(erfinv(x), x)
  615. sqrt(pi)*exp(erfinv(x)**2)/2
  616. We can numerically evaluate the inverse error function to arbitrary
  617. precision on [-1, 1]:
  618. >>> erfinv(0.2).evalf(30)
  619. 0.179143454621291692285822705344
  620. See Also
  621. ========
  622. erf: Gaussian error function.
  623. erfc: Complementary error function.
  624. erfi: Imaginary error function.
  625. erf2: Two-argument error function.
  626. erfcinv: Inverse Complementary error function.
  627. erf2inv: Inverse two-argument error function.
  628. References
  629. ==========
  630. .. [1] https://en.wikipedia.org/wiki/Error_function#Inverse_functions
  631. .. [2] http://functions.wolfram.com/GammaBetaErf/InverseErf/
  632. """
  633. def fdiff(self, argindex =1):
  634. if argindex == 1:
  635. return sqrt(S.Pi)*exp(self.func(self.args[0])**2)*S.Half
  636. else :
  637. raise ArgumentIndexError(self, argindex)
  638. def inverse(self, argindex=1):
  639. """
  640. Returns the inverse of this function.
  641. """
  642. return erf
  643. @classmethod
  644. def eval(cls, z):
  645. if z is S.NaN:
  646. return S.NaN
  647. elif z is S.NegativeOne:
  648. return S.NegativeInfinity
  649. elif z.is_zero:
  650. return S.Zero
  651. elif z is S.One:
  652. return S.Infinity
  653. if isinstance(z, erf) and z.args[0].is_extended_real:
  654. return z.args[0]
  655. if z.is_zero:
  656. return S.Zero
  657. # Try to pull out factors of -1
  658. nz = z.extract_multiplicatively(-1)
  659. if nz is not None and (isinstance(nz, erf) and (nz.args[0]).is_extended_real):
  660. return -nz.args[0]
  661. def _eval_rewrite_as_erfcinv(self, z, **kwargs):
  662. return erfcinv(1-z)
  663. def _eval_is_zero(self):
  664. return self.args[0].is_zero
  665. class erfcinv (Function):
  666. r"""
  667. Inverse Complementary Error Function. The erfcinv function is defined as:
  668. .. math ::
  669. \mathrm{erfc}(x) = y \quad \Rightarrow \quad \mathrm{erfcinv}(y) = x
  670. Examples
  671. ========
  672. >>> from sympy import erfcinv
  673. >>> from sympy.abc import x
  674. Several special values are known:
  675. >>> erfcinv(1)
  676. 0
  677. >>> erfcinv(0)
  678. oo
  679. Differentiation with respect to $x$ is supported:
  680. >>> from sympy import diff
  681. >>> diff(erfcinv(x), x)
  682. -sqrt(pi)*exp(erfcinv(x)**2)/2
  683. See Also
  684. ========
  685. erf: Gaussian error function.
  686. erfc: Complementary error function.
  687. erfi: Imaginary error function.
  688. erf2: Two-argument error function.
  689. erfinv: Inverse error function.
  690. erf2inv: Inverse two-argument error function.
  691. References
  692. ==========
  693. .. [1] https://en.wikipedia.org/wiki/Error_function#Inverse_functions
  694. .. [2] http://functions.wolfram.com/GammaBetaErf/InverseErfc/
  695. """
  696. def fdiff(self, argindex =1):
  697. if argindex == 1:
  698. return -sqrt(S.Pi)*exp(self.func(self.args[0])**2)*S.Half
  699. else:
  700. raise ArgumentIndexError(self, argindex)
  701. def inverse(self, argindex=1):
  702. """
  703. Returns the inverse of this function.
  704. """
  705. return erfc
  706. @classmethod
  707. def eval(cls, z):
  708. if z is S.NaN:
  709. return S.NaN
  710. elif z.is_zero:
  711. return S.Infinity
  712. elif z is S.One:
  713. return S.Zero
  714. elif z == 2:
  715. return S.NegativeInfinity
  716. if z.is_zero:
  717. return S.Infinity
  718. def _eval_rewrite_as_erfinv(self, z, **kwargs):
  719. return erfinv(1-z)
  720. def _eval_is_zero(self):
  721. return (self.args[0] - 1).is_zero
  722. def _eval_is_infinite(self):
  723. return self.args[0].is_zero
  724. class erf2inv(Function):
  725. r"""
  726. Two-argument Inverse error function. The erf2inv function is defined as:
  727. .. math ::
  728. \mathrm{erf2}(x, w) = y \quad \Rightarrow \quad \mathrm{erf2inv}(x, y) = w
  729. Examples
  730. ========
  731. >>> from sympy import erf2inv, oo
  732. >>> from sympy.abc import x, y
  733. Several special values are known:
  734. >>> erf2inv(0, 0)
  735. 0
  736. >>> erf2inv(1, 0)
  737. 1
  738. >>> erf2inv(0, 1)
  739. oo
  740. >>> erf2inv(0, y)
  741. erfinv(y)
  742. >>> erf2inv(oo, y)
  743. erfcinv(-y)
  744. Differentiation with respect to $x$ and $y$ is supported:
  745. >>> from sympy import diff
  746. >>> diff(erf2inv(x, y), x)
  747. exp(-x**2 + erf2inv(x, y)**2)
  748. >>> diff(erf2inv(x, y), y)
  749. sqrt(pi)*exp(erf2inv(x, y)**2)/2
  750. See Also
  751. ========
  752. erf: Gaussian error function.
  753. erfc: Complementary error function.
  754. erfi: Imaginary error function.
  755. erf2: Two-argument error function.
  756. erfinv: Inverse error function.
  757. erfcinv: Inverse complementary error function.
  758. References
  759. ==========
  760. .. [1] http://functions.wolfram.com/GammaBetaErf/InverseErf2/
  761. """
  762. def fdiff(self, argindex):
  763. x, y = self.args
  764. if argindex == 1:
  765. return exp(self.func(x,y)**2-x**2)
  766. elif argindex == 2:
  767. return sqrt(S.Pi)*S.Half*exp(self.func(x,y)**2)
  768. else:
  769. raise ArgumentIndexError(self, argindex)
  770. @classmethod
  771. def eval(cls, x, y):
  772. if x is S.NaN or y is S.NaN:
  773. return S.NaN
  774. elif x.is_zero and y.is_zero:
  775. return S.Zero
  776. elif x.is_zero and y is S.One:
  777. return S.Infinity
  778. elif x is S.One and y.is_zero:
  779. return S.One
  780. elif x.is_zero:
  781. return erfinv(y)
  782. elif x is S.Infinity:
  783. return erfcinv(-y)
  784. elif y.is_zero:
  785. return x
  786. elif y is S.Infinity:
  787. return erfinv(x)
  788. if x.is_zero:
  789. if y.is_zero:
  790. return S.Zero
  791. else:
  792. return erfinv(y)
  793. if y.is_zero:
  794. return x
  795. def _eval_is_zero(self):
  796. x, y = self.args
  797. if x.is_zero and y.is_zero:
  798. return True
  799. ###############################################################################
  800. #################### EXPONENTIAL INTEGRALS ####################################
  801. ###############################################################################
  802. class Ei(Function):
  803. r"""
  804. The classical exponential integral.
  805. Explanation
  806. ===========
  807. For use in SymPy, this function is defined as
  808. .. math:: \operatorname{Ei}(x) = \sum_{n=1}^\infty \frac{x^n}{n\, n!}
  809. + \log(x) + \gamma,
  810. where $\gamma$ is the Euler-Mascheroni constant.
  811. If $x$ is a polar number, this defines an analytic function on the
  812. Riemann surface of the logarithm. Otherwise this defines an analytic
  813. function in the cut plane $\mathbb{C} \setminus (-\infty, 0]$.
  814. **Background**
  815. The name exponential integral comes from the following statement:
  816. .. math:: \operatorname{Ei}(x) = \int_{-\infty}^x \frac{e^t}{t} \mathrm{d}t
  817. If the integral is interpreted as a Cauchy principal value, this statement
  818. holds for $x > 0$ and $\operatorname{Ei}(x)$ as defined above.
  819. Examples
  820. ========
  821. >>> from sympy import Ei, polar_lift, exp_polar, I, pi
  822. >>> from sympy.abc import x
  823. >>> Ei(-1)
  824. Ei(-1)
  825. This yields a real value:
  826. >>> Ei(-1).n(chop=True)
  827. -0.219383934395520
  828. On the other hand the analytic continuation is not real:
  829. >>> Ei(polar_lift(-1)).n(chop=True)
  830. -0.21938393439552 + 3.14159265358979*I
  831. The exponential integral has a logarithmic branch point at the origin:
  832. >>> Ei(x*exp_polar(2*I*pi))
  833. Ei(x) + 2*I*pi
  834. Differentiation is supported:
  835. >>> Ei(x).diff(x)
  836. exp(x)/x
  837. The exponential integral is related to many other special functions.
  838. For example:
  839. >>> from sympy import expint, Shi
  840. >>> Ei(x).rewrite(expint)
  841. -expint(1, x*exp_polar(I*pi)) - I*pi
  842. >>> Ei(x).rewrite(Shi)
  843. Chi(x) + Shi(x)
  844. See Also
  845. ========
  846. expint: Generalised exponential integral.
  847. E1: Special case of the generalised exponential integral.
  848. li: Logarithmic integral.
  849. Li: Offset logarithmic integral.
  850. Si: Sine integral.
  851. Ci: Cosine integral.
  852. Shi: Hyperbolic sine integral.
  853. Chi: Hyperbolic cosine integral.
  854. uppergamma: Upper incomplete gamma function.
  855. References
  856. ==========
  857. .. [1] http://dlmf.nist.gov/6.6
  858. .. [2] https://en.wikipedia.org/wiki/Exponential_integral
  859. .. [3] Abramowitz & Stegun, section 5: http://people.math.sfu.ca/~cbm/aands/page_228.htm
  860. """
  861. @classmethod
  862. def eval(cls, z):
  863. if z.is_zero:
  864. return S.NegativeInfinity
  865. elif z is S.Infinity:
  866. return S.Infinity
  867. elif z is S.NegativeInfinity:
  868. return S.Zero
  869. if z.is_zero:
  870. return S.NegativeInfinity
  871. nz, n = z.extract_branch_factor()
  872. if n:
  873. return Ei(nz) + 2*I*pi*n
  874. def fdiff(self, argindex=1):
  875. arg = unpolarify(self.args[0])
  876. if argindex == 1:
  877. return exp(arg)/arg
  878. else:
  879. raise ArgumentIndexError(self, argindex)
  880. def _eval_evalf(self, prec):
  881. if (self.args[0]/polar_lift(-1)).is_positive:
  882. return Function._eval_evalf(self, prec) + (I*pi)._eval_evalf(prec)
  883. return Function._eval_evalf(self, prec)
  884. def _eval_rewrite_as_uppergamma(self, z, **kwargs):
  885. from sympy.functions.special.gamma_functions import uppergamma
  886. # XXX this does not currently work usefully because uppergamma
  887. # immediately turns into expint
  888. return -uppergamma(0, polar_lift(-1)*z) - I*pi
  889. def _eval_rewrite_as_expint(self, z, **kwargs):
  890. return -expint(1, polar_lift(-1)*z) - I*pi
  891. def _eval_rewrite_as_li(self, z, **kwargs):
  892. if isinstance(z, log):
  893. return li(z.args[0])
  894. # TODO:
  895. # Actually it only holds that:
  896. # Ei(z) = li(exp(z))
  897. # for -pi < imag(z) <= pi
  898. return li(exp(z))
  899. def _eval_rewrite_as_Si(self, z, **kwargs):
  900. if z.is_negative:
  901. return Shi(z) + Chi(z) - I*pi
  902. else:
  903. return Shi(z) + Chi(z)
  904. _eval_rewrite_as_Ci = _eval_rewrite_as_Si
  905. _eval_rewrite_as_Chi = _eval_rewrite_as_Si
  906. _eval_rewrite_as_Shi = _eval_rewrite_as_Si
  907. def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs):
  908. return exp(z) * _eis(z)
  909. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  910. x0 = self.args[0].limit(x, 0)
  911. if x0.is_zero:
  912. f = self._eval_rewrite_as_Si(*self.args)
  913. return f._eval_as_leading_term(x, logx=logx, cdir=cdir)
  914. return super()._eval_as_leading_term(x, logx=logx, cdir=cdir)
  915. def _eval_nseries(self, x, n, logx, cdir=0):
  916. x0 = self.args[0].limit(x, 0)
  917. if x0.is_zero:
  918. f = self._eval_rewrite_as_Si(*self.args)
  919. return f._eval_nseries(x, n, logx)
  920. return super()._eval_nseries(x, n, logx)
  921. def _eval_aseries(self, n, args0, x, logx):
  922. from sympy.series.order import Order
  923. point = args0[0]
  924. if point is S.Infinity:
  925. z = self.args[0]
  926. s = [factorial(k) / (z)**k for k in range(0, n)] + \
  927. [Order(1/z**n, x)]
  928. return (exp(z)/z) * Add(*s)
  929. return super(Ei, self)._eval_aseries(n, args0, x, logx)
  930. class expint(Function):
  931. r"""
  932. Generalized exponential integral.
  933. Explanation
  934. ===========
  935. This function is defined as
  936. .. math:: \operatorname{E}_\nu(z) = z^{\nu - 1} \Gamma(1 - \nu, z),
  937. where $\Gamma(1 - \nu, z)$ is the upper incomplete gamma function
  938. (``uppergamma``).
  939. Hence for $z$ with positive real part we have
  940. .. math:: \operatorname{E}_\nu(z)
  941. = \int_1^\infty \frac{e^{-zt}}{t^\nu} \mathrm{d}t,
  942. which explains the name.
  943. The representation as an incomplete gamma function provides an analytic
  944. continuation for $\operatorname{E}_\nu(z)$. If $\nu$ is a
  945. non-positive integer, the exponential integral is thus an unbranched
  946. function of $z$, otherwise there is a branch point at the origin.
  947. Refer to the incomplete gamma function documentation for details of the
  948. branching behavior.
  949. Examples
  950. ========
  951. >>> from sympy import expint, S
  952. >>> from sympy.abc import nu, z
  953. Differentiation is supported. Differentiation with respect to $z$ further
  954. explains the name: for integral orders, the exponential integral is an
  955. iterated integral of the exponential function.
  956. >>> expint(nu, z).diff(z)
  957. -expint(nu - 1, z)
  958. Differentiation with respect to $\nu$ has no classical expression:
  959. >>> expint(nu, z).diff(nu)
  960. -z**(nu - 1)*meijerg(((), (1, 1)), ((0, 0, 1 - nu), ()), z)
  961. At non-postive integer orders, the exponential integral reduces to the
  962. exponential function:
  963. >>> expint(0, z)
  964. exp(-z)/z
  965. >>> expint(-1, z)
  966. exp(-z)/z + exp(-z)/z**2
  967. At half-integers it reduces to error functions:
  968. >>> expint(S(1)/2, z)
  969. sqrt(pi)*erfc(sqrt(z))/sqrt(z)
  970. At positive integer orders it can be rewritten in terms of exponentials
  971. and ``expint(1, z)``. Use ``expand_func()`` to do this:
  972. >>> from sympy import expand_func
  973. >>> expand_func(expint(5, z))
  974. z**4*expint(1, z)/24 + (-z**3 + z**2 - 2*z + 6)*exp(-z)/24
  975. The generalised exponential integral is essentially equivalent to the
  976. incomplete gamma function:
  977. >>> from sympy import uppergamma
  978. >>> expint(nu, z).rewrite(uppergamma)
  979. z**(nu - 1)*uppergamma(1 - nu, z)
  980. As such it is branched at the origin:
  981. >>> from sympy import exp_polar, pi, I
  982. >>> expint(4, z*exp_polar(2*pi*I))
  983. I*pi*z**3/3 + expint(4, z)
  984. >>> expint(nu, z*exp_polar(2*pi*I))
  985. z**(nu - 1)*(exp(2*I*pi*nu) - 1)*gamma(1 - nu) + expint(nu, z)
  986. See Also
  987. ========
  988. Ei: Another related function called exponential integral.
  989. E1: The classical case, returns expint(1, z).
  990. li: Logarithmic integral.
  991. Li: Offset logarithmic integral.
  992. Si: Sine integral.
  993. Ci: Cosine integral.
  994. Shi: Hyperbolic sine integral.
  995. Chi: Hyperbolic cosine integral.
  996. uppergamma
  997. References
  998. ==========
  999. .. [1] http://dlmf.nist.gov/8.19
  1000. .. [2] http://functions.wolfram.com/GammaBetaErf/ExpIntegralE/
  1001. .. [3] https://en.wikipedia.org/wiki/Exponential_integral
  1002. """
  1003. @classmethod
  1004. def eval(cls, nu, z):
  1005. from sympy.functions.special.gamma_functions import (gamma, uppergamma)
  1006. nu2 = unpolarify(nu)
  1007. if nu != nu2:
  1008. return expint(nu2, z)
  1009. if nu.is_Integer and nu <= 0 or (not nu.is_Integer and (2*nu).is_Integer):
  1010. return unpolarify(expand_mul(z**(nu - 1)*uppergamma(1 - nu, z)))
  1011. # Extract branching information. This can be deduced from what is
  1012. # explained in lowergamma.eval().
  1013. z, n = z.extract_branch_factor()
  1014. if n is S.Zero:
  1015. return
  1016. if nu.is_integer:
  1017. if not nu > 0:
  1018. return
  1019. return expint(nu, z) \
  1020. - 2*pi*I*n*S.NegativeOne**(nu - 1)/factorial(nu - 1)*unpolarify(z)**(nu - 1)
  1021. else:
  1022. return (exp(2*I*pi*nu*n) - 1)*z**(nu - 1)*gamma(1 - nu) + expint(nu, z)
  1023. def fdiff(self, argindex):
  1024. nu, z = self.args
  1025. if argindex == 1:
  1026. return -z**(nu - 1)*meijerg([], [1, 1], [0, 0, 1 - nu], [], z)
  1027. elif argindex == 2:
  1028. return -expint(nu - 1, z)
  1029. else:
  1030. raise ArgumentIndexError(self, argindex)
  1031. def _eval_rewrite_as_uppergamma(self, nu, z, **kwargs):
  1032. from sympy.functions.special.gamma_functions import uppergamma
  1033. return z**(nu - 1)*uppergamma(1 - nu, z)
  1034. def _eval_rewrite_as_Ei(self, nu, z, **kwargs):
  1035. if nu == 1:
  1036. return -Ei(z*exp_polar(-I*pi)) - I*pi
  1037. elif nu.is_Integer and nu > 1:
  1038. # DLMF, 8.19.7
  1039. x = -unpolarify(z)
  1040. return x**(nu - 1)/factorial(nu - 1)*E1(z).rewrite(Ei) + \
  1041. exp(x)/factorial(nu - 1) * \
  1042. Add(*[factorial(nu - k - 2)*x**k for k in range(nu - 1)])
  1043. else:
  1044. return self
  1045. def _eval_expand_func(self, **hints):
  1046. return self.rewrite(Ei).rewrite(expint, **hints)
  1047. def _eval_rewrite_as_Si(self, nu, z, **kwargs):
  1048. if nu != 1:
  1049. return self
  1050. return Shi(z) - Chi(z)
  1051. _eval_rewrite_as_Ci = _eval_rewrite_as_Si
  1052. _eval_rewrite_as_Chi = _eval_rewrite_as_Si
  1053. _eval_rewrite_as_Shi = _eval_rewrite_as_Si
  1054. def _eval_nseries(self, x, n, logx, cdir=0):
  1055. if not self.args[0].has(x):
  1056. nu = self.args[0]
  1057. if nu == 1:
  1058. f = self._eval_rewrite_as_Si(*self.args)
  1059. return f._eval_nseries(x, n, logx)
  1060. elif nu.is_Integer and nu > 1:
  1061. f = self._eval_rewrite_as_Ei(*self.args)
  1062. return f._eval_nseries(x, n, logx)
  1063. return super()._eval_nseries(x, n, logx)
  1064. def _eval_aseries(self, n, args0, x, logx):
  1065. from sympy.series.order import Order
  1066. point = args0[1]
  1067. nu = self.args[0]
  1068. if point is S.Infinity:
  1069. z = self.args[1]
  1070. s = [S.NegativeOne**k * RisingFactorial(nu, k) / z**k for k in range(0, n)] + [Order(1/z**n, x)]
  1071. return (exp(-z)/z) * Add(*s)
  1072. return super(expint, self)._eval_aseries(n, args0, x, logx)
  1073. def E1(z):
  1074. """
  1075. Classical case of the generalized exponential integral.
  1076. Explanation
  1077. ===========
  1078. This is equivalent to ``expint(1, z)``.
  1079. Examples
  1080. ========
  1081. >>> from sympy import E1
  1082. >>> E1(0)
  1083. expint(1, 0)
  1084. >>> E1(5)
  1085. expint(1, 5)
  1086. See Also
  1087. ========
  1088. Ei: Exponential integral.
  1089. expint: Generalised exponential integral.
  1090. li: Logarithmic integral.
  1091. Li: Offset logarithmic integral.
  1092. Si: Sine integral.
  1093. Ci: Cosine integral.
  1094. Shi: Hyperbolic sine integral.
  1095. Chi: Hyperbolic cosine integral.
  1096. """
  1097. return expint(1, z)
  1098. class li(Function):
  1099. r"""
  1100. The classical logarithmic integral.
  1101. Explanation
  1102. ===========
  1103. For use in SymPy, this function is defined as
  1104. .. math:: \operatorname{li}(x) = \int_0^x \frac{1}{\log(t)} \mathrm{d}t \,.
  1105. Examples
  1106. ========
  1107. >>> from sympy import I, oo, li
  1108. >>> from sympy.abc import z
  1109. Several special values are known:
  1110. >>> li(0)
  1111. 0
  1112. >>> li(1)
  1113. -oo
  1114. >>> li(oo)
  1115. oo
  1116. Differentiation with respect to $z$ is supported:
  1117. >>> from sympy import diff
  1118. >>> diff(li(z), z)
  1119. 1/log(z)
  1120. Defining the ``li`` function via an integral:
  1121. >>> from sympy import integrate
  1122. >>> integrate(li(z))
  1123. z*li(z) - Ei(2*log(z))
  1124. >>> integrate(li(z),z)
  1125. z*li(z) - Ei(2*log(z))
  1126. The logarithmic integral can also be defined in terms of ``Ei``:
  1127. >>> from sympy import Ei
  1128. >>> li(z).rewrite(Ei)
  1129. Ei(log(z))
  1130. >>> diff(li(z).rewrite(Ei), z)
  1131. 1/log(z)
  1132. We can numerically evaluate the logarithmic integral to arbitrary precision
  1133. on the whole complex plane (except the singular points):
  1134. >>> li(2).evalf(30)
  1135. 1.04516378011749278484458888919
  1136. >>> li(2*I).evalf(30)
  1137. 1.0652795784357498247001125598 + 3.08346052231061726610939702133*I
  1138. We can even compute Soldner's constant by the help of mpmath:
  1139. >>> from mpmath import findroot
  1140. >>> findroot(li, 2)
  1141. 1.45136923488338
  1142. Further transformations include rewriting ``li`` in terms of
  1143. the trigonometric integrals ``Si``, ``Ci``, ``Shi`` and ``Chi``:
  1144. >>> from sympy import Si, Ci, Shi, Chi
  1145. >>> li(z).rewrite(Si)
  1146. -log(I*log(z)) - log(1/log(z))/2 + log(log(z))/2 + Ci(I*log(z)) + Shi(log(z))
  1147. >>> li(z).rewrite(Ci)
  1148. -log(I*log(z)) - log(1/log(z))/2 + log(log(z))/2 + Ci(I*log(z)) + Shi(log(z))
  1149. >>> li(z).rewrite(Shi)
  1150. -log(1/log(z))/2 + log(log(z))/2 + Chi(log(z)) - Shi(log(z))
  1151. >>> li(z).rewrite(Chi)
  1152. -log(1/log(z))/2 + log(log(z))/2 + Chi(log(z)) - Shi(log(z))
  1153. See Also
  1154. ========
  1155. Li: Offset logarithmic integral.
  1156. Ei: Exponential integral.
  1157. expint: Generalised exponential integral.
  1158. E1: Special case of the generalised exponential integral.
  1159. Si: Sine integral.
  1160. Ci: Cosine integral.
  1161. Shi: Hyperbolic sine integral.
  1162. Chi: Hyperbolic cosine integral.
  1163. References
  1164. ==========
  1165. .. [1] https://en.wikipedia.org/wiki/Logarithmic_integral
  1166. .. [2] http://mathworld.wolfram.com/LogarithmicIntegral.html
  1167. .. [3] http://dlmf.nist.gov/6
  1168. .. [4] http://mathworld.wolfram.com/SoldnersConstant.html
  1169. """
  1170. @classmethod
  1171. def eval(cls, z):
  1172. if z.is_zero:
  1173. return S.Zero
  1174. elif z is S.One:
  1175. return S.NegativeInfinity
  1176. elif z is S.Infinity:
  1177. return S.Infinity
  1178. if z.is_zero:
  1179. return S.Zero
  1180. def fdiff(self, argindex=1):
  1181. arg = self.args[0]
  1182. if argindex == 1:
  1183. return S.One / log(arg)
  1184. else:
  1185. raise ArgumentIndexError(self, argindex)
  1186. def _eval_conjugate(self):
  1187. z = self.args[0]
  1188. # Exclude values on the branch cut (-oo, 0)
  1189. if not z.is_extended_negative:
  1190. return self.func(z.conjugate())
  1191. def _eval_rewrite_as_Li(self, z, **kwargs):
  1192. return Li(z) + li(2)
  1193. def _eval_rewrite_as_Ei(self, z, **kwargs):
  1194. return Ei(log(z))
  1195. def _eval_rewrite_as_uppergamma(self, z, **kwargs):
  1196. from sympy.functions.special.gamma_functions import uppergamma
  1197. return (-uppergamma(0, -log(z)) +
  1198. S.Half*(log(log(z)) - log(S.One/log(z))) - log(-log(z)))
  1199. def _eval_rewrite_as_Si(self, z, **kwargs):
  1200. return (Ci(I*log(z)) - I*Si(I*log(z)) -
  1201. S.Half*(log(S.One/log(z)) - log(log(z))) - log(I*log(z)))
  1202. _eval_rewrite_as_Ci = _eval_rewrite_as_Si
  1203. def _eval_rewrite_as_Shi(self, z, **kwargs):
  1204. return (Chi(log(z)) - Shi(log(z)) - S.Half*(log(S.One/log(z)) - log(log(z))))
  1205. _eval_rewrite_as_Chi = _eval_rewrite_as_Shi
  1206. def _eval_rewrite_as_hyper(self, z, **kwargs):
  1207. return (log(z)*hyper((1, 1), (2, 2), log(z)) +
  1208. S.Half*(log(log(z)) - log(S.One/log(z))) + S.EulerGamma)
  1209. def _eval_rewrite_as_meijerg(self, z, **kwargs):
  1210. return (-log(-log(z)) - S.Half*(log(S.One/log(z)) - log(log(z)))
  1211. - meijerg(((), (1,)), ((0, 0), ()), -log(z)))
  1212. def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs):
  1213. return z * _eis(log(z))
  1214. def _eval_nseries(self, x, n, logx, cdir=0):
  1215. z = self.args[0]
  1216. s = [(log(z))**k / (factorial(k) * k) for k in range(1, n)]
  1217. return S.EulerGamma + log(log(z)) + Add(*s)
  1218. def _eval_is_zero(self):
  1219. z = self.args[0]
  1220. if z.is_zero:
  1221. return True
  1222. class Li(Function):
  1223. r"""
  1224. The offset logarithmic integral.
  1225. Explanation
  1226. ===========
  1227. For use in SymPy, this function is defined as
  1228. .. math:: \operatorname{Li}(x) = \operatorname{li}(x) - \operatorname{li}(2)
  1229. Examples
  1230. ========
  1231. >>> from sympy import Li
  1232. >>> from sympy.abc import z
  1233. The following special value is known:
  1234. >>> Li(2)
  1235. 0
  1236. Differentiation with respect to $z$ is supported:
  1237. >>> from sympy import diff
  1238. >>> diff(Li(z), z)
  1239. 1/log(z)
  1240. The shifted logarithmic integral can be written in terms of $li(z)$:
  1241. >>> from sympy import li
  1242. >>> Li(z).rewrite(li)
  1243. li(z) - li(2)
  1244. We can numerically evaluate the logarithmic integral to arbitrary precision
  1245. on the whole complex plane (except the singular points):
  1246. >>> Li(2).evalf(30)
  1247. 0
  1248. >>> Li(4).evalf(30)
  1249. 1.92242131492155809316615998938
  1250. See Also
  1251. ========
  1252. li: Logarithmic integral.
  1253. Ei: Exponential integral.
  1254. expint: Generalised exponential integral.
  1255. E1: Special case of the generalised exponential integral.
  1256. Si: Sine integral.
  1257. Ci: Cosine integral.
  1258. Shi: Hyperbolic sine integral.
  1259. Chi: Hyperbolic cosine integral.
  1260. References
  1261. ==========
  1262. .. [1] https://en.wikipedia.org/wiki/Logarithmic_integral
  1263. .. [2] http://mathworld.wolfram.com/LogarithmicIntegral.html
  1264. .. [3] http://dlmf.nist.gov/6
  1265. """
  1266. @classmethod
  1267. def eval(cls, z):
  1268. if z is S.Infinity:
  1269. return S.Infinity
  1270. elif z == S(2):
  1271. return S.Zero
  1272. def fdiff(self, argindex=1):
  1273. arg = self.args[0]
  1274. if argindex == 1:
  1275. return S.One / log(arg)
  1276. else:
  1277. raise ArgumentIndexError(self, argindex)
  1278. def _eval_evalf(self, prec):
  1279. return self.rewrite(li).evalf(prec)
  1280. def _eval_rewrite_as_li(self, z, **kwargs):
  1281. return li(z) - li(2)
  1282. def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs):
  1283. return self.rewrite(li).rewrite("tractable", deep=True)
  1284. def _eval_nseries(self, x, n, logx, cdir=0):
  1285. f = self._eval_rewrite_as_li(*self.args)
  1286. return f._eval_nseries(x, n, logx)
  1287. ###############################################################################
  1288. #################### TRIGONOMETRIC INTEGRALS ##################################
  1289. ###############################################################################
  1290. class TrigonometricIntegral(Function):
  1291. """ Base class for trigonometric integrals. """
  1292. @classmethod
  1293. def eval(cls, z):
  1294. if z is S.Zero:
  1295. return cls._atzero
  1296. elif z is S.Infinity:
  1297. return cls._atinf()
  1298. elif z is S.NegativeInfinity:
  1299. return cls._atneginf()
  1300. if z.is_zero:
  1301. return cls._atzero
  1302. nz = z.extract_multiplicatively(polar_lift(I))
  1303. if nz is None and cls._trigfunc(0) == 0:
  1304. nz = z.extract_multiplicatively(I)
  1305. if nz is not None:
  1306. return cls._Ifactor(nz, 1)
  1307. nz = z.extract_multiplicatively(polar_lift(-I))
  1308. if nz is not None:
  1309. return cls._Ifactor(nz, -1)
  1310. nz = z.extract_multiplicatively(polar_lift(-1))
  1311. if nz is None and cls._trigfunc(0) == 0:
  1312. nz = z.extract_multiplicatively(-1)
  1313. if nz is not None:
  1314. return cls._minusfactor(nz)
  1315. nz, n = z.extract_branch_factor()
  1316. if n == 0 and nz == z:
  1317. return
  1318. return 2*pi*I*n*cls._trigfunc(0) + cls(nz)
  1319. def fdiff(self, argindex=1):
  1320. arg = unpolarify(self.args[0])
  1321. if argindex == 1:
  1322. return self._trigfunc(arg)/arg
  1323. else:
  1324. raise ArgumentIndexError(self, argindex)
  1325. def _eval_rewrite_as_Ei(self, z, **kwargs):
  1326. return self._eval_rewrite_as_expint(z).rewrite(Ei)
  1327. def _eval_rewrite_as_uppergamma(self, z, **kwargs):
  1328. from sympy.functions.special.gamma_functions import uppergamma
  1329. return self._eval_rewrite_as_expint(z).rewrite(uppergamma)
  1330. def _eval_nseries(self, x, n, logx, cdir=0):
  1331. # NOTE this is fairly inefficient
  1332. n += 1
  1333. if self.args[0].subs(x, 0) != 0:
  1334. return super()._eval_nseries(x, n, logx)
  1335. baseseries = self._trigfunc(x)._eval_nseries(x, n, logx)
  1336. if self._trigfunc(0) != 0:
  1337. baseseries -= 1
  1338. baseseries = baseseries.replace(Pow, lambda t, n: t**n/n, simultaneous=False)
  1339. if self._trigfunc(0) != 0:
  1340. baseseries += EulerGamma + log(x)
  1341. return baseseries.subs(x, self.args[0])._eval_nseries(x, n, logx)
  1342. class Si(TrigonometricIntegral):
  1343. r"""
  1344. Sine integral.
  1345. Explanation
  1346. ===========
  1347. This function is defined by
  1348. .. math:: \operatorname{Si}(z) = \int_0^z \frac{\sin{t}}{t} \mathrm{d}t.
  1349. It is an entire function.
  1350. Examples
  1351. ========
  1352. >>> from sympy import Si
  1353. >>> from sympy.abc import z
  1354. The sine integral is an antiderivative of $sin(z)/z$:
  1355. >>> Si(z).diff(z)
  1356. sin(z)/z
  1357. It is unbranched:
  1358. >>> from sympy import exp_polar, I, pi
  1359. >>> Si(z*exp_polar(2*I*pi))
  1360. Si(z)
  1361. Sine integral behaves much like ordinary sine under multiplication by ``I``:
  1362. >>> Si(I*z)
  1363. I*Shi(z)
  1364. >>> Si(-z)
  1365. -Si(z)
  1366. It can also be expressed in terms of exponential integrals, but beware
  1367. that the latter is branched:
  1368. >>> from sympy import expint
  1369. >>> Si(z).rewrite(expint)
  1370. -I*(-expint(1, z*exp_polar(-I*pi/2))/2 +
  1371. expint(1, z*exp_polar(I*pi/2))/2) + pi/2
  1372. It can be rewritten in the form of sinc function (by definition):
  1373. >>> from sympy import sinc
  1374. >>> Si(z).rewrite(sinc)
  1375. Integral(sinc(t), (t, 0, z))
  1376. See Also
  1377. ========
  1378. Ci: Cosine integral.
  1379. Shi: Hyperbolic sine integral.
  1380. Chi: Hyperbolic cosine integral.
  1381. Ei: Exponential integral.
  1382. expint: Generalised exponential integral.
  1383. sinc: unnormalized sinc function
  1384. E1: Special case of the generalised exponential integral.
  1385. li: Logarithmic integral.
  1386. Li: Offset logarithmic integral.
  1387. References
  1388. ==========
  1389. .. [1] https://en.wikipedia.org/wiki/Trigonometric_integral
  1390. """
  1391. _trigfunc = sin
  1392. _atzero = S.Zero
  1393. @classmethod
  1394. def _atinf(cls):
  1395. return pi*S.Half
  1396. @classmethod
  1397. def _atneginf(cls):
  1398. return -pi*S.Half
  1399. @classmethod
  1400. def _minusfactor(cls, z):
  1401. return -Si(z)
  1402. @classmethod
  1403. def _Ifactor(cls, z, sign):
  1404. return I*Shi(z)*sign
  1405. def _eval_rewrite_as_expint(self, z, **kwargs):
  1406. # XXX should we polarify z?
  1407. return pi/2 + (E1(polar_lift(I)*z) - E1(polar_lift(-I)*z))/2/I
  1408. def _eval_rewrite_as_sinc(self, z, **kwargs):
  1409. from sympy.integrals.integrals import Integral
  1410. t = Symbol('t', Dummy=True)
  1411. return Integral(sinc(t), (t, 0, z))
  1412. def _eval_aseries(self, n, args0, x, logx):
  1413. from sympy.series.order import Order
  1414. point = args0[0]
  1415. # Expansion at oo
  1416. if point is S.Infinity:
  1417. z = self.args[0]
  1418. p = [S.NegativeOne**k * factorial(2*k) / z**(2*k)
  1419. for k in range(0, int((n - 1)/2))] + [Order(1/z**n, x)]
  1420. q = [S.NegativeOne**k * factorial(2*k + 1) / z**(2*k + 1)
  1421. for k in range(0, int(n/2) - 1)] + [Order(1/z**n, x)]
  1422. return pi/2 - (cos(z)/z)*Add(*p) - (sin(z)/z)*Add(*q)
  1423. # All other points are not handled
  1424. return super(Si, self)._eval_aseries(n, args0, x, logx)
  1425. def _eval_is_zero(self):
  1426. z = self.args[0]
  1427. if z.is_zero:
  1428. return True
  1429. class Ci(TrigonometricIntegral):
  1430. r"""
  1431. Cosine integral.
  1432. Explanation
  1433. ===========
  1434. This function is defined for positive $x$ by
  1435. .. math:: \operatorname{Ci}(x) = \gamma + \log{x}
  1436. + \int_0^x \frac{\cos{t} - 1}{t} \mathrm{d}t
  1437. = -\int_x^\infty \frac{\cos{t}}{t} \mathrm{d}t,
  1438. where $\gamma$ is the Euler-Mascheroni constant.
  1439. We have
  1440. .. math:: \operatorname{Ci}(z) =
  1441. -\frac{\operatorname{E}_1\left(e^{i\pi/2} z\right)
  1442. + \operatorname{E}_1\left(e^{-i \pi/2} z\right)}{2}
  1443. which holds for all polar $z$ and thus provides an analytic
  1444. continuation to the Riemann surface of the logarithm.
  1445. The formula also holds as stated
  1446. for $z \in \mathbb{C}$ with $\Re(z) > 0$.
  1447. By lifting to the principal branch, we obtain an analytic function on the
  1448. cut complex plane.
  1449. Examples
  1450. ========
  1451. >>> from sympy import Ci
  1452. >>> from sympy.abc import z
  1453. The cosine integral is a primitive of $\cos(z)/z$:
  1454. >>> Ci(z).diff(z)
  1455. cos(z)/z
  1456. It has a logarithmic branch point at the origin:
  1457. >>> from sympy import exp_polar, I, pi
  1458. >>> Ci(z*exp_polar(2*I*pi))
  1459. Ci(z) + 2*I*pi
  1460. The cosine integral behaves somewhat like ordinary $\cos$ under
  1461. multiplication by $i$:
  1462. >>> from sympy import polar_lift
  1463. >>> Ci(polar_lift(I)*z)
  1464. Chi(z) + I*pi/2
  1465. >>> Ci(polar_lift(-1)*z)
  1466. Ci(z) + I*pi
  1467. It can also be expressed in terms of exponential integrals:
  1468. >>> from sympy import expint
  1469. >>> Ci(z).rewrite(expint)
  1470. -expint(1, z*exp_polar(-I*pi/2))/2 - expint(1, z*exp_polar(I*pi/2))/2
  1471. See Also
  1472. ========
  1473. Si: Sine integral.
  1474. Shi: Hyperbolic sine integral.
  1475. Chi: Hyperbolic cosine integral.
  1476. Ei: Exponential integral.
  1477. expint: Generalised exponential integral.
  1478. E1: Special case of the generalised exponential integral.
  1479. li: Logarithmic integral.
  1480. Li: Offset logarithmic integral.
  1481. References
  1482. ==========
  1483. .. [1] https://en.wikipedia.org/wiki/Trigonometric_integral
  1484. """
  1485. _trigfunc = cos
  1486. _atzero = S.ComplexInfinity
  1487. @classmethod
  1488. def _atinf(cls):
  1489. return S.Zero
  1490. @classmethod
  1491. def _atneginf(cls):
  1492. return I*pi
  1493. @classmethod
  1494. def _minusfactor(cls, z):
  1495. return Ci(z) + I*pi
  1496. @classmethod
  1497. def _Ifactor(cls, z, sign):
  1498. return Chi(z) + I*pi/2*sign
  1499. def _eval_rewrite_as_expint(self, z, **kwargs):
  1500. return -(E1(polar_lift(I)*z) + E1(polar_lift(-I)*z))/2
  1501. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  1502. arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir)
  1503. arg0 = arg.subs(x, 0)
  1504. if arg0 is S.NaN:
  1505. arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+')
  1506. if arg0.is_zero:
  1507. return S.EulerGamma
  1508. elif arg0.is_finite:
  1509. return self.func(arg0)
  1510. else:
  1511. return self
  1512. def _eval_aseries(self, n, args0, x, logx):
  1513. from sympy.series.order import Order
  1514. point = args0[0]
  1515. # Expansion at oo
  1516. if point is S.Infinity:
  1517. z = self.args[0]
  1518. p = [S.NegativeOne**k * factorial(2*k) / z**(2*k)
  1519. for k in range(0, int((n - 1)/2))] + [Order(1/z**n, x)]
  1520. q = [S.NegativeOne**k * factorial(2*k + 1) / z**(2*k + 1)
  1521. for k in range(0, int(n/2) - 1)] + [Order(1/z**n, x)]
  1522. return (sin(z)/z)*Add(*p) - (cos(z)/z)*Add(*q)
  1523. # All other points are not handled
  1524. return super(Ci, self)._eval_aseries(n, args0, x, logx)
  1525. class Shi(TrigonometricIntegral):
  1526. r"""
  1527. Sinh integral.
  1528. Explanation
  1529. ===========
  1530. This function is defined by
  1531. .. math:: \operatorname{Shi}(z) = \int_0^z \frac{\sinh{t}}{t} \mathrm{d}t.
  1532. It is an entire function.
  1533. Examples
  1534. ========
  1535. >>> from sympy import Shi
  1536. >>> from sympy.abc import z
  1537. The Sinh integral is a primitive of $\sinh(z)/z$:
  1538. >>> Shi(z).diff(z)
  1539. sinh(z)/z
  1540. It is unbranched:
  1541. >>> from sympy import exp_polar, I, pi
  1542. >>> Shi(z*exp_polar(2*I*pi))
  1543. Shi(z)
  1544. The $\sinh$ integral behaves much like ordinary $\sinh$ under
  1545. multiplication by $i$:
  1546. >>> Shi(I*z)
  1547. I*Si(z)
  1548. >>> Shi(-z)
  1549. -Shi(z)
  1550. It can also be expressed in terms of exponential integrals, but beware
  1551. that the latter is branched:
  1552. >>> from sympy import expint
  1553. >>> Shi(z).rewrite(expint)
  1554. expint(1, z)/2 - expint(1, z*exp_polar(I*pi))/2 - I*pi/2
  1555. See Also
  1556. ========
  1557. Si: Sine integral.
  1558. Ci: Cosine integral.
  1559. Chi: Hyperbolic cosine integral.
  1560. Ei: Exponential integral.
  1561. expint: Generalised exponential integral.
  1562. E1: Special case of the generalised exponential integral.
  1563. li: Logarithmic integral.
  1564. Li: Offset logarithmic integral.
  1565. References
  1566. ==========
  1567. .. [1] https://en.wikipedia.org/wiki/Trigonometric_integral
  1568. """
  1569. _trigfunc = sinh
  1570. _atzero = S.Zero
  1571. @classmethod
  1572. def _atinf(cls):
  1573. return S.Infinity
  1574. @classmethod
  1575. def _atneginf(cls):
  1576. return S.NegativeInfinity
  1577. @classmethod
  1578. def _minusfactor(cls, z):
  1579. return -Shi(z)
  1580. @classmethod
  1581. def _Ifactor(cls, z, sign):
  1582. return I*Si(z)*sign
  1583. def _eval_rewrite_as_expint(self, z, **kwargs):
  1584. # XXX should we polarify z?
  1585. return (E1(z) - E1(exp_polar(I*pi)*z))/2 - I*pi/2
  1586. def _eval_is_zero(self):
  1587. z = self.args[0]
  1588. if z.is_zero:
  1589. return True
  1590. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  1591. arg = self.args[0].as_leading_term(x)
  1592. arg0 = arg.subs(x, 0)
  1593. if arg0 is S.NaN:
  1594. arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+')
  1595. if arg0.is_zero:
  1596. return arg
  1597. elif not arg0.is_infinite:
  1598. return self.func(arg0)
  1599. elif arg0.is_infinite:
  1600. return -pi*S.ImaginaryUnit/2
  1601. else:
  1602. return self
  1603. class Chi(TrigonometricIntegral):
  1604. r"""
  1605. Cosh integral.
  1606. Explanation
  1607. ===========
  1608. This function is defined for positive $x$ by
  1609. .. math:: \operatorname{Chi}(x) = \gamma + \log{x}
  1610. + \int_0^x \frac{\cosh{t} - 1}{t} \mathrm{d}t,
  1611. where $\gamma$ is the Euler-Mascheroni constant.
  1612. We have
  1613. .. math:: \operatorname{Chi}(z) = \operatorname{Ci}\left(e^{i \pi/2}z\right)
  1614. - i\frac{\pi}{2},
  1615. which holds for all polar $z$ and thus provides an analytic
  1616. continuation to the Riemann surface of the logarithm.
  1617. By lifting to the principal branch we obtain an analytic function on the
  1618. cut complex plane.
  1619. Examples
  1620. ========
  1621. >>> from sympy import Chi
  1622. >>> from sympy.abc import z
  1623. The $\cosh$ integral is a primitive of $\cosh(z)/z$:
  1624. >>> Chi(z).diff(z)
  1625. cosh(z)/z
  1626. It has a logarithmic branch point at the origin:
  1627. >>> from sympy import exp_polar, I, pi
  1628. >>> Chi(z*exp_polar(2*I*pi))
  1629. Chi(z) + 2*I*pi
  1630. The $\cosh$ integral behaves somewhat like ordinary $\cosh$ under
  1631. multiplication by $i$:
  1632. >>> from sympy import polar_lift
  1633. >>> Chi(polar_lift(I)*z)
  1634. Ci(z) + I*pi/2
  1635. >>> Chi(polar_lift(-1)*z)
  1636. Chi(z) + I*pi
  1637. It can also be expressed in terms of exponential integrals:
  1638. >>> from sympy import expint
  1639. >>> Chi(z).rewrite(expint)
  1640. -expint(1, z)/2 - expint(1, z*exp_polar(I*pi))/2 - I*pi/2
  1641. See Also
  1642. ========
  1643. Si: Sine integral.
  1644. Ci: Cosine integral.
  1645. Shi: Hyperbolic sine integral.
  1646. Ei: Exponential integral.
  1647. expint: Generalised exponential integral.
  1648. E1: Special case of the generalised exponential integral.
  1649. li: Logarithmic integral.
  1650. Li: Offset logarithmic integral.
  1651. References
  1652. ==========
  1653. .. [1] https://en.wikipedia.org/wiki/Trigonometric_integral
  1654. """
  1655. _trigfunc = cosh
  1656. _atzero = S.ComplexInfinity
  1657. @classmethod
  1658. def _atinf(cls):
  1659. return S.Infinity
  1660. @classmethod
  1661. def _atneginf(cls):
  1662. return S.Infinity
  1663. @classmethod
  1664. def _minusfactor(cls, z):
  1665. return Chi(z) + I*pi
  1666. @classmethod
  1667. def _Ifactor(cls, z, sign):
  1668. return Ci(z) + I*pi/2*sign
  1669. def _eval_rewrite_as_expint(self, z, **kwargs):
  1670. return -I*pi/2 - (E1(z) + E1(exp_polar(I*pi)*z))/2
  1671. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  1672. arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir)
  1673. arg0 = arg.subs(x, 0)
  1674. if arg0 is S.NaN:
  1675. arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+')
  1676. if arg0.is_zero:
  1677. return S.EulerGamma
  1678. elif arg0.is_finite:
  1679. return self.func(arg0)
  1680. else:
  1681. return self
  1682. ###############################################################################
  1683. #################### FRESNEL INTEGRALS ########################################
  1684. ###############################################################################
  1685. class FresnelIntegral(Function):
  1686. """ Base class for the Fresnel integrals."""
  1687. unbranched = True
  1688. @classmethod
  1689. def eval(cls, z):
  1690. # Values at positive infinities signs
  1691. # if any were extracted automatically
  1692. if z is S.Infinity:
  1693. return S.Half
  1694. # Value at zero
  1695. if z.is_zero:
  1696. return S.Zero
  1697. # Try to pull out factors of -1 and I
  1698. prefact = S.One
  1699. newarg = z
  1700. changed = False
  1701. nz = newarg.extract_multiplicatively(-1)
  1702. if nz is not None:
  1703. prefact = -prefact
  1704. newarg = nz
  1705. changed = True
  1706. nz = newarg.extract_multiplicatively(I)
  1707. if nz is not None:
  1708. prefact = cls._sign*I*prefact
  1709. newarg = nz
  1710. changed = True
  1711. if changed:
  1712. return prefact*cls(newarg)
  1713. def fdiff(self, argindex=1):
  1714. if argindex == 1:
  1715. return self._trigfunc(S.Half*pi*self.args[0]**2)
  1716. else:
  1717. raise ArgumentIndexError(self, argindex)
  1718. def _eval_is_extended_real(self):
  1719. return self.args[0].is_extended_real
  1720. _eval_is_finite = _eval_is_extended_real
  1721. def _eval_is_zero(self):
  1722. return self.args[0].is_zero
  1723. def _eval_conjugate(self):
  1724. return self.func(self.args[0].conjugate())
  1725. as_real_imag = real_to_real_as_real_imag
  1726. class fresnels(FresnelIntegral):
  1727. r"""
  1728. Fresnel integral S.
  1729. Explanation
  1730. ===========
  1731. This function is defined by
  1732. .. math:: \operatorname{S}(z) = \int_0^z \sin{\frac{\pi}{2} t^2} \mathrm{d}t.
  1733. It is an entire function.
  1734. Examples
  1735. ========
  1736. >>> from sympy import I, oo, fresnels
  1737. >>> from sympy.abc import z
  1738. Several special values are known:
  1739. >>> fresnels(0)
  1740. 0
  1741. >>> fresnels(oo)
  1742. 1/2
  1743. >>> fresnels(-oo)
  1744. -1/2
  1745. >>> fresnels(I*oo)
  1746. -I/2
  1747. >>> fresnels(-I*oo)
  1748. I/2
  1749. In general one can pull out factors of -1 and $i$ from the argument:
  1750. >>> fresnels(-z)
  1751. -fresnels(z)
  1752. >>> fresnels(I*z)
  1753. -I*fresnels(z)
  1754. The Fresnel S integral obeys the mirror symmetry
  1755. $\overline{S(z)} = S(\bar{z})$:
  1756. >>> from sympy import conjugate
  1757. >>> conjugate(fresnels(z))
  1758. fresnels(conjugate(z))
  1759. Differentiation with respect to $z$ is supported:
  1760. >>> from sympy import diff
  1761. >>> diff(fresnels(z), z)
  1762. sin(pi*z**2/2)
  1763. Defining the Fresnel functions via an integral:
  1764. >>> from sympy import integrate, pi, sin, expand_func
  1765. >>> integrate(sin(pi*z**2/2), z)
  1766. 3*fresnels(z)*gamma(3/4)/(4*gamma(7/4))
  1767. >>> expand_func(integrate(sin(pi*z**2/2), z))
  1768. fresnels(z)
  1769. We can numerically evaluate the Fresnel integral to arbitrary precision
  1770. on the whole complex plane:
  1771. >>> fresnels(2).evalf(30)
  1772. 0.343415678363698242195300815958
  1773. >>> fresnels(-2*I).evalf(30)
  1774. 0.343415678363698242195300815958*I
  1775. See Also
  1776. ========
  1777. fresnelc: Fresnel cosine integral.
  1778. References
  1779. ==========
  1780. .. [1] https://en.wikipedia.org/wiki/Fresnel_integral
  1781. .. [2] http://dlmf.nist.gov/7
  1782. .. [3] http://mathworld.wolfram.com/FresnelIntegrals.html
  1783. .. [4] http://functions.wolfram.com/GammaBetaErf/FresnelS
  1784. .. [5] The converging factors for the fresnel integrals
  1785. by John W. Wrench Jr. and Vicki Alley
  1786. """
  1787. _trigfunc = sin
  1788. _sign = -S.One
  1789. @staticmethod
  1790. @cacheit
  1791. def taylor_term(n, x, *previous_terms):
  1792. if n < 0:
  1793. return S.Zero
  1794. else:
  1795. x = sympify(x)
  1796. if len(previous_terms) > 1:
  1797. p = previous_terms[-1]
  1798. return (-pi**2*x**4*(4*n - 1)/(8*n*(2*n + 1)*(4*n + 3))) * p
  1799. else:
  1800. return x**3 * (-x**4)**n * (S(2)**(-2*n - 1)*pi**(2*n + 1)) / ((4*n + 3)*factorial(2*n + 1))
  1801. def _eval_rewrite_as_erf(self, z, **kwargs):
  1802. return (S.One + I)/4 * (erf((S.One + I)/2*sqrt(pi)*z) - I*erf((S.One - I)/2*sqrt(pi)*z))
  1803. def _eval_rewrite_as_hyper(self, z, **kwargs):
  1804. return pi*z**3/6 * hyper([Rational(3, 4)], [Rational(3, 2), Rational(7, 4)], -pi**2*z**4/16)
  1805. def _eval_rewrite_as_meijerg(self, z, **kwargs):
  1806. return (pi*z**Rational(9, 4) / (sqrt(2)*(z**2)**Rational(3, 4)*(-z)**Rational(3, 4))
  1807. * meijerg([], [1], [Rational(3, 4)], [Rational(1, 4), 0], -pi**2*z**4/16))
  1808. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  1809. from sympy.series.order import Order
  1810. arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir)
  1811. arg0 = arg.subs(x, 0)
  1812. if arg0 is S.ComplexInfinity:
  1813. arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+')
  1814. if arg0.is_zero:
  1815. return pi*arg**3/6
  1816. elif arg0 in [S.Infinity, S.NegativeInfinity]:
  1817. s = 1 if arg0 is S.Infinity else -1
  1818. return s*S.Half + Order(x, x)
  1819. else:
  1820. return self.func(arg0)
  1821. def _eval_aseries(self, n, args0, x, logx):
  1822. from sympy.series.order import Order
  1823. point = args0[0]
  1824. # Expansion at oo and -oo
  1825. if point in [S.Infinity, -S.Infinity]:
  1826. z = self.args[0]
  1827. # expansion of S(x) = S1(x*sqrt(pi/2)), see reference[5] page 1-8
  1828. # as only real infinities are dealt with, sin and cos are O(1)
  1829. p = [S.NegativeOne**k * factorial(4*k + 1) /
  1830. (2**(2*k + 2) * z**(4*k + 3) * 2**(2*k)*factorial(2*k))
  1831. for k in range(0, n) if 4*k + 3 < n]
  1832. q = [1/(2*z)] + [S.NegativeOne**k * factorial(4*k - 1) /
  1833. (2**(2*k + 1) * z**(4*k + 1) * 2**(2*k - 1)*factorial(2*k - 1))
  1834. for k in range(1, n) if 4*k + 1 < n]
  1835. p = [-sqrt(2/pi)*t for t in p]
  1836. q = [-sqrt(2/pi)*t for t in q]
  1837. s = 1 if point is S.Infinity else -1
  1838. # The expansion at oo is 1/2 + some odd powers of z
  1839. # To get the expansion at -oo, replace z by -z and flip the sign
  1840. # The result -1/2 + the same odd powers of z as before.
  1841. return s*S.Half + (sin(z**2)*Add(*p) + cos(z**2)*Add(*q)
  1842. ).subs(x, sqrt(2/pi)*x) + Order(1/z**n, x)
  1843. # All other points are not handled
  1844. return super()._eval_aseries(n, args0, x, logx)
  1845. class fresnelc(FresnelIntegral):
  1846. r"""
  1847. Fresnel integral C.
  1848. Explanation
  1849. ===========
  1850. This function is defined by
  1851. .. math:: \operatorname{C}(z) = \int_0^z \cos{\frac{\pi}{2} t^2} \mathrm{d}t.
  1852. It is an entire function.
  1853. Examples
  1854. ========
  1855. >>> from sympy import I, oo, fresnelc
  1856. >>> from sympy.abc import z
  1857. Several special values are known:
  1858. >>> fresnelc(0)
  1859. 0
  1860. >>> fresnelc(oo)
  1861. 1/2
  1862. >>> fresnelc(-oo)
  1863. -1/2
  1864. >>> fresnelc(I*oo)
  1865. I/2
  1866. >>> fresnelc(-I*oo)
  1867. -I/2
  1868. In general one can pull out factors of -1 and $i$ from the argument:
  1869. >>> fresnelc(-z)
  1870. -fresnelc(z)
  1871. >>> fresnelc(I*z)
  1872. I*fresnelc(z)
  1873. The Fresnel C integral obeys the mirror symmetry
  1874. $\overline{C(z)} = C(\bar{z})$:
  1875. >>> from sympy import conjugate
  1876. >>> conjugate(fresnelc(z))
  1877. fresnelc(conjugate(z))
  1878. Differentiation with respect to $z$ is supported:
  1879. >>> from sympy import diff
  1880. >>> diff(fresnelc(z), z)
  1881. cos(pi*z**2/2)
  1882. Defining the Fresnel functions via an integral:
  1883. >>> from sympy import integrate, pi, cos, expand_func
  1884. >>> integrate(cos(pi*z**2/2), z)
  1885. fresnelc(z)*gamma(1/4)/(4*gamma(5/4))
  1886. >>> expand_func(integrate(cos(pi*z**2/2), z))
  1887. fresnelc(z)
  1888. We can numerically evaluate the Fresnel integral to arbitrary precision
  1889. on the whole complex plane:
  1890. >>> fresnelc(2).evalf(30)
  1891. 0.488253406075340754500223503357
  1892. >>> fresnelc(-2*I).evalf(30)
  1893. -0.488253406075340754500223503357*I
  1894. See Also
  1895. ========
  1896. fresnels: Fresnel sine integral.
  1897. References
  1898. ==========
  1899. .. [1] https://en.wikipedia.org/wiki/Fresnel_integral
  1900. .. [2] http://dlmf.nist.gov/7
  1901. .. [3] http://mathworld.wolfram.com/FresnelIntegrals.html
  1902. .. [4] http://functions.wolfram.com/GammaBetaErf/FresnelC
  1903. .. [5] The converging factors for the fresnel integrals
  1904. by John W. Wrench Jr. and Vicki Alley
  1905. """
  1906. _trigfunc = cos
  1907. _sign = S.One
  1908. @staticmethod
  1909. @cacheit
  1910. def taylor_term(n, x, *previous_terms):
  1911. if n < 0:
  1912. return S.Zero
  1913. else:
  1914. x = sympify(x)
  1915. if len(previous_terms) > 1:
  1916. p = previous_terms[-1]
  1917. return (-pi**2*x**4*(4*n - 3)/(8*n*(2*n - 1)*(4*n + 1))) * p
  1918. else:
  1919. return x * (-x**4)**n * (S(2)**(-2*n)*pi**(2*n)) / ((4*n + 1)*factorial(2*n))
  1920. def _eval_rewrite_as_erf(self, z, **kwargs):
  1921. return (S.One - I)/4 * (erf((S.One + I)/2*sqrt(pi)*z) + I*erf((S.One - I)/2*sqrt(pi)*z))
  1922. def _eval_rewrite_as_hyper(self, z, **kwargs):
  1923. return z * hyper([Rational(1, 4)], [S.Half, Rational(5, 4)], -pi**2*z**4/16)
  1924. def _eval_rewrite_as_meijerg(self, z, **kwargs):
  1925. return (pi*z**Rational(3, 4) / (sqrt(2)*root(z**2, 4)*root(-z, 4))
  1926. * meijerg([], [1], [Rational(1, 4)], [Rational(3, 4), 0], -pi**2*z**4/16))
  1927. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  1928. from sympy.series.order import Order
  1929. arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir)
  1930. arg0 = arg.subs(x, 0)
  1931. if arg0 is S.ComplexInfinity:
  1932. arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+')
  1933. if arg0.is_zero:
  1934. return arg
  1935. elif arg0 in [S.Infinity, S.NegativeInfinity]:
  1936. s = 1 if arg0 is S.Infinity else -1
  1937. return s*S.Half + Order(x, x)
  1938. else:
  1939. return self.func(arg0)
  1940. def _eval_aseries(self, n, args0, x, logx):
  1941. from sympy.series.order import Order
  1942. point = args0[0]
  1943. # Expansion at oo
  1944. if point in [S.Infinity, -S.Infinity]:
  1945. z = self.args[0]
  1946. # expansion of C(x) = C1(x*sqrt(pi/2)), see reference[5] page 1-8
  1947. # as only real infinities are dealt with, sin and cos are O(1)
  1948. p = [S.NegativeOne**k * factorial(4*k + 1) /
  1949. (2**(2*k + 2) * z**(4*k + 3) * 2**(2*k)*factorial(2*k))
  1950. for k in range(0, n) if 4*k + 3 < n]
  1951. q = [1/(2*z)] + [S.NegativeOne**k * factorial(4*k - 1) /
  1952. (2**(2*k + 1) * z**(4*k + 1) * 2**(2*k - 1)*factorial(2*k - 1))
  1953. for k in range(1, n) if 4*k + 1 < n]
  1954. p = [-sqrt(2/pi)*t for t in p]
  1955. q = [ sqrt(2/pi)*t for t in q]
  1956. s = 1 if point is S.Infinity else -1
  1957. # The expansion at oo is 1/2 + some odd powers of z
  1958. # To get the expansion at -oo, replace z by -z and flip the sign
  1959. # The result -1/2 + the same odd powers of z as before.
  1960. return s*S.Half + (cos(z**2)*Add(*p) + sin(z**2)*Add(*q)
  1961. ).subs(x, sqrt(2/pi)*x) + Order(1/z**n, x)
  1962. # All other points are not handled
  1963. return super()._eval_aseries(n, args0, x, logx)
  1964. ###############################################################################
  1965. #################### HELPER FUNCTIONS #########################################
  1966. ###############################################################################
  1967. class _erfs(Function):
  1968. """
  1969. Helper function to make the $\\mathrm{erf}(z)$ function
  1970. tractable for the Gruntz algorithm.
  1971. """
  1972. @classmethod
  1973. def eval(cls, arg):
  1974. if arg.is_zero:
  1975. return S.One
  1976. def _eval_aseries(self, n, args0, x, logx):
  1977. from sympy.series.order import Order
  1978. point = args0[0]
  1979. # Expansion at oo
  1980. if point is S.Infinity:
  1981. z = self.args[0]
  1982. l = [ 1/sqrt(S.Pi) * factorial(2*k)*(-S(
  1983. 4))**(-k)/factorial(k) * (1/z)**(2*k + 1) for k in range(0, n) ]
  1984. o = Order(1/z**(2*n + 1), x)
  1985. # It is very inefficient to first add the order and then do the nseries
  1986. return (Add(*l))._eval_nseries(x, n, logx) + o
  1987. # Expansion at I*oo
  1988. t = point.extract_multiplicatively(S.ImaginaryUnit)
  1989. if t is S.Infinity:
  1990. z = self.args[0]
  1991. # TODO: is the series really correct?
  1992. l = [ 1/sqrt(S.Pi) * factorial(2*k)*(-S(
  1993. 4))**(-k)/factorial(k) * (1/z)**(2*k + 1) for k in range(0, n) ]
  1994. o = Order(1/z**(2*n + 1), x)
  1995. # It is very inefficient to first add the order and then do the nseries
  1996. return (Add(*l))._eval_nseries(x, n, logx) + o
  1997. # All other points are not handled
  1998. return super()._eval_aseries(n, args0, x, logx)
  1999. def fdiff(self, argindex=1):
  2000. if argindex == 1:
  2001. z = self.args[0]
  2002. return -2/sqrt(S.Pi) + 2*z*_erfs(z)
  2003. else:
  2004. raise ArgumentIndexError(self, argindex)
  2005. def _eval_rewrite_as_intractable(self, z, **kwargs):
  2006. return (S.One - erf(z))*exp(z**2)
  2007. class _eis(Function):
  2008. """
  2009. Helper function to make the $\\mathrm{Ei}(z)$ and $\\mathrm{li}(z)$
  2010. functions tractable for the Gruntz algorithm.
  2011. """
  2012. def _eval_aseries(self, n, args0, x, logx):
  2013. from sympy.series.order import Order
  2014. if args0[0] != S.Infinity:
  2015. return super(_erfs, self)._eval_aseries(n, args0, x, logx)
  2016. z = self.args[0]
  2017. l = [ factorial(k) * (1/z)**(k + 1) for k in range(0, n) ]
  2018. o = Order(1/z**(n + 1), x)
  2019. # It is very inefficient to first add the order and then do the nseries
  2020. return (Add(*l))._eval_nseries(x, n, logx) + o
  2021. def fdiff(self, argindex=1):
  2022. if argindex == 1:
  2023. z = self.args[0]
  2024. return S.One / z - _eis(z)
  2025. else:
  2026. raise ArgumentIndexError(self, argindex)
  2027. def _eval_rewrite_as_intractable(self, z, **kwargs):
  2028. return exp(-z)*Ei(z)
  2029. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  2030. x0 = self.args[0].limit(x, 0)
  2031. if x0.is_zero:
  2032. f = self._eval_rewrite_as_intractable(*self.args)
  2033. return f._eval_as_leading_term(x, logx=logx, cdir=cdir)
  2034. return super()._eval_as_leading_term(x, logx=logx, cdir=cdir)
  2035. def _eval_nseries(self, x, n, logx, cdir=0):
  2036. x0 = self.args[0].limit(x, 0)
  2037. if x0.is_zero:
  2038. f = self._eval_rewrite_as_intractable(*self.args)
  2039. return f._eval_nseries(x, n, logx)
  2040. return super()._eval_nseries(x, n, logx)