error_functions.py 75 KB

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