gamma_functions.py 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344
  1. from math import prod
  2. from sympy.core import Add, S, Dummy, expand_func
  3. from sympy.core.expr import Expr
  4. from sympy.core.function import Function, ArgumentIndexError, PoleError
  5. from sympy.core.logic import fuzzy_and, fuzzy_not
  6. from sympy.core.numbers import Rational, pi, oo, I
  7. from sympy.core.power import Pow
  8. from sympy.functions.special.zeta_functions import zeta
  9. from sympy.functions.special.error_functions import erf, erfc, Ei
  10. from sympy.functions.elementary.complexes import re, unpolarify
  11. from sympy.functions.elementary.exponential import exp, log
  12. from sympy.functions.elementary.integers import ceiling, floor
  13. from sympy.functions.elementary.miscellaneous import sqrt
  14. from sympy.functions.elementary.trigonometric import sin, cos, cot
  15. from sympy.functions.combinatorial.numbers import bernoulli, harmonic
  16. from sympy.functions.combinatorial.factorials import factorial, rf, RisingFactorial
  17. from sympy.utilities.misc import as_int
  18. from mpmath import mp, workprec
  19. from mpmath.libmp.libmpf import prec_to_dps
  20. def intlike(n):
  21. try:
  22. as_int(n, strict=False)
  23. return True
  24. except ValueError:
  25. return False
  26. ###############################################################################
  27. ############################ COMPLETE GAMMA FUNCTION ##########################
  28. ###############################################################################
  29. class gamma(Function):
  30. r"""
  31. The gamma function
  32. .. math::
  33. \Gamma(x) := \int^{\infty}_{0} t^{x-1} e^{-t} \mathrm{d}t.
  34. Explanation
  35. ===========
  36. The ``gamma`` function implements the function which passes through the
  37. values of the factorial function (i.e., $\Gamma(n) = (n - 1)!$ when n is
  38. an integer). More generally, $\Gamma(z)$ is defined in the whole complex
  39. plane except at the negative integers where there are simple poles.
  40. Examples
  41. ========
  42. >>> from sympy import S, I, pi, gamma
  43. >>> from sympy.abc import x
  44. Several special values are known:
  45. >>> gamma(1)
  46. 1
  47. >>> gamma(4)
  48. 6
  49. >>> gamma(S(3)/2)
  50. sqrt(pi)/2
  51. The ``gamma`` function obeys the mirror symmetry:
  52. >>> from sympy import conjugate
  53. >>> conjugate(gamma(x))
  54. gamma(conjugate(x))
  55. Differentiation with respect to $x$ is supported:
  56. >>> from sympy import diff
  57. >>> diff(gamma(x), x)
  58. gamma(x)*polygamma(0, x)
  59. Series expansion is also supported:
  60. >>> from sympy import series
  61. >>> series(gamma(x), x, 0, 3)
  62. 1/x - EulerGamma + x*(EulerGamma**2/2 + pi**2/12) + x**2*(-EulerGamma*pi**2/12 - zeta(3)/3 - EulerGamma**3/6) + O(x**3)
  63. We can numerically evaluate the ``gamma`` function to arbitrary precision
  64. on the whole complex plane:
  65. >>> gamma(pi).evalf(40)
  66. 2.288037795340032417959588909060233922890
  67. >>> gamma(1+I).evalf(20)
  68. 0.49801566811835604271 - 0.15494982830181068512*I
  69. See Also
  70. ========
  71. lowergamma: Lower incomplete gamma function.
  72. uppergamma: Upper incomplete gamma function.
  73. polygamma: Polygamma function.
  74. loggamma: Log Gamma function.
  75. digamma: Digamma function.
  76. trigamma: Trigamma function.
  77. beta: Euler Beta function.
  78. References
  79. ==========
  80. .. [1] https://en.wikipedia.org/wiki/Gamma_function
  81. .. [2] https://dlmf.nist.gov/5
  82. .. [3] https://mathworld.wolfram.com/GammaFunction.html
  83. .. [4] https://functions.wolfram.com/GammaBetaErf/Gamma/
  84. """
  85. unbranched = True
  86. _singularities = (S.ComplexInfinity,)
  87. def fdiff(self, argindex=1):
  88. if argindex == 1:
  89. return self.func(self.args[0])*polygamma(0, self.args[0])
  90. else:
  91. raise ArgumentIndexError(self, argindex)
  92. @classmethod
  93. def eval(cls, arg):
  94. if arg.is_Number:
  95. if arg is S.NaN:
  96. return S.NaN
  97. elif arg is oo:
  98. return oo
  99. elif intlike(arg):
  100. if arg.is_positive:
  101. return factorial(arg - 1)
  102. else:
  103. return S.ComplexInfinity
  104. elif arg.is_Rational:
  105. if arg.q == 2:
  106. n = abs(arg.p) // arg.q
  107. if arg.is_positive:
  108. k, coeff = n, S.One
  109. else:
  110. n = k = n + 1
  111. if n & 1 == 0:
  112. coeff = S.One
  113. else:
  114. coeff = S.NegativeOne
  115. coeff *= prod(range(3, 2*k, 2))
  116. if arg.is_positive:
  117. return coeff*sqrt(pi) / 2**n
  118. else:
  119. return 2**n*sqrt(pi) / coeff
  120. def _eval_expand_func(self, **hints):
  121. arg = self.args[0]
  122. if arg.is_Rational:
  123. if abs(arg.p) > arg.q:
  124. x = Dummy('x')
  125. n = arg.p // arg.q
  126. p = arg.p - n*arg.q
  127. return self.func(x + n)._eval_expand_func().subs(x, Rational(p, arg.q))
  128. if arg.is_Add:
  129. coeff, tail = arg.as_coeff_add()
  130. if coeff and coeff.q != 1:
  131. intpart = floor(coeff)
  132. tail = (coeff - intpart,) + tail
  133. coeff = intpart
  134. tail = arg._new_rawargs(*tail, reeval=False)
  135. return self.func(tail)*RisingFactorial(tail, coeff)
  136. return self.func(*self.args)
  137. def _eval_conjugate(self):
  138. return self.func(self.args[0].conjugate())
  139. def _eval_is_real(self):
  140. x = self.args[0]
  141. if x.is_nonpositive and x.is_integer:
  142. return False
  143. if intlike(x) and x <= 0:
  144. return False
  145. if x.is_positive or x.is_noninteger:
  146. return True
  147. def _eval_is_positive(self):
  148. x = self.args[0]
  149. if x.is_positive:
  150. return True
  151. elif x.is_noninteger:
  152. return floor(x).is_even
  153. def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs):
  154. return exp(loggamma(z))
  155. def _eval_rewrite_as_factorial(self, z, **kwargs):
  156. return factorial(z - 1)
  157. def _eval_nseries(self, x, n, logx, cdir=0):
  158. x0 = self.args[0].limit(x, 0)
  159. if not (x0.is_Integer and x0 <= 0):
  160. return super()._eval_nseries(x, n, logx)
  161. t = self.args[0] - x0
  162. return (self.func(t + 1)/rf(self.args[0], -x0 + 1))._eval_nseries(x, n, logx)
  163. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  164. arg = self.args[0]
  165. x0 = arg.subs(x, 0)
  166. if x0.is_integer and x0.is_nonpositive:
  167. n = -x0
  168. res = S.NegativeOne**n/self.func(n + 1)
  169. return res/(arg + n).as_leading_term(x)
  170. elif not x0.is_infinite:
  171. return self.func(x0)
  172. raise PoleError()
  173. ###############################################################################
  174. ################## LOWER and UPPER INCOMPLETE GAMMA FUNCTIONS #################
  175. ###############################################################################
  176. class lowergamma(Function):
  177. r"""
  178. The lower incomplete gamma function.
  179. Explanation
  180. ===========
  181. It can be defined as the meromorphic continuation of
  182. .. math::
  183. \gamma(s, x) := \int_0^x t^{s-1} e^{-t} \mathrm{d}t = \Gamma(s) - \Gamma(s, x).
  184. This can be shown to be the same as
  185. .. math::
  186. \gamma(s, x) = \frac{x^s}{s} {}_1F_1\left({s \atop s+1} \middle| -x\right),
  187. where ${}_1F_1$ is the (confluent) hypergeometric function.
  188. Examples
  189. ========
  190. >>> from sympy import lowergamma, S
  191. >>> from sympy.abc import s, x
  192. >>> lowergamma(s, x)
  193. lowergamma(s, x)
  194. >>> lowergamma(3, x)
  195. -2*(x**2/2 + x + 1)*exp(-x) + 2
  196. >>> lowergamma(-S(1)/2, x)
  197. -2*sqrt(pi)*erf(sqrt(x)) - 2*exp(-x)/sqrt(x)
  198. See Also
  199. ========
  200. gamma: Gamma function.
  201. uppergamma: Upper incomplete gamma function.
  202. polygamma: Polygamma function.
  203. loggamma: Log Gamma function.
  204. digamma: Digamma function.
  205. trigamma: Trigamma function.
  206. beta: Euler Beta function.
  207. References
  208. ==========
  209. .. [1] https://en.wikipedia.org/wiki/Incomplete_gamma_function#Lower_incomplete_gamma_function
  210. .. [2] Abramowitz, Milton; Stegun, Irene A., eds. (1965), Chapter 6,
  211. Section 5, Handbook of Mathematical Functions with Formulas, Graphs,
  212. and Mathematical Tables
  213. .. [3] https://dlmf.nist.gov/8
  214. .. [4] https://functions.wolfram.com/GammaBetaErf/Gamma2/
  215. .. [5] https://functions.wolfram.com/GammaBetaErf/Gamma3/
  216. """
  217. def fdiff(self, argindex=2):
  218. from sympy.functions.special.hyper import meijerg
  219. if argindex == 2:
  220. a, z = self.args
  221. return exp(-unpolarify(z))*z**(a - 1)
  222. elif argindex == 1:
  223. a, z = self.args
  224. return gamma(a)*digamma(a) - log(z)*uppergamma(a, z) \
  225. - meijerg([], [1, 1], [0, 0, a], [], z)
  226. else:
  227. raise ArgumentIndexError(self, argindex)
  228. @classmethod
  229. def eval(cls, a, x):
  230. # For lack of a better place, we use this one to extract branching
  231. # information. The following can be
  232. # found in the literature (c/f references given above), albeit scattered:
  233. # 1) For fixed x != 0, lowergamma(s, x) is an entire function of s
  234. # 2) For fixed positive integers s, lowergamma(s, x) is an entire
  235. # function of x.
  236. # 3) For fixed non-positive integers s,
  237. # lowergamma(s, exp(I*2*pi*n)*x) =
  238. # 2*pi*I*n*(-1)**(-s)/factorial(-s) + lowergamma(s, x)
  239. # (this follows from lowergamma(s, x).diff(x) = x**(s-1)*exp(-x)).
  240. # 4) For fixed non-integral s,
  241. # lowergamma(s, x) = x**s*gamma(s)*lowergamma_unbranched(s, x),
  242. # where lowergamma_unbranched(s, x) is an entire function (in fact
  243. # of both s and x), i.e.
  244. # lowergamma(s, exp(2*I*pi*n)*x) = exp(2*pi*I*n*a)*lowergamma(a, x)
  245. if x is S.Zero:
  246. return S.Zero
  247. nx, n = x.extract_branch_factor()
  248. if a.is_integer and a.is_positive:
  249. nx = unpolarify(x)
  250. if nx != x:
  251. return lowergamma(a, nx)
  252. elif a.is_integer and a.is_nonpositive:
  253. if n != 0:
  254. return 2*pi*I*n*S.NegativeOne**(-a)/factorial(-a) + lowergamma(a, nx)
  255. elif n != 0:
  256. return exp(2*pi*I*n*a)*lowergamma(a, nx)
  257. # Special values.
  258. if a.is_Number:
  259. if a is S.One:
  260. return S.One - exp(-x)
  261. elif a is S.Half:
  262. return sqrt(pi)*erf(sqrt(x))
  263. elif a.is_Integer or (2*a).is_Integer:
  264. b = a - 1
  265. if b.is_positive:
  266. if a.is_integer:
  267. return factorial(b) - exp(-x) * factorial(b) * Add(*[x ** k / factorial(k) for k in range(a)])
  268. else:
  269. return gamma(a)*(lowergamma(S.Half, x)/sqrt(pi) - exp(-x)*Add(*[x**(k - S.Half)/gamma(S.Half + k) for k in range(1, a + S.Half)]))
  270. if not a.is_Integer:
  271. return S.NegativeOne**(S.Half - a)*pi*erf(sqrt(x))/gamma(1 - a) + exp(-x)*Add(*[x**(k + a - 1)*gamma(a)/gamma(a + k) for k in range(1, Rational(3, 2) - a)])
  272. if x.is_zero:
  273. return S.Zero
  274. def _eval_evalf(self, prec):
  275. if all(x.is_number for x in self.args):
  276. a = self.args[0]._to_mpmath(prec)
  277. z = self.args[1]._to_mpmath(prec)
  278. with workprec(prec):
  279. res = mp.gammainc(a, 0, z)
  280. return Expr._from_mpmath(res, prec)
  281. else:
  282. return self
  283. def _eval_conjugate(self):
  284. x = self.args[1]
  285. if x not in (S.Zero, S.NegativeInfinity):
  286. return self.func(self.args[0].conjugate(), x.conjugate())
  287. def _eval_is_meromorphic(self, x, a):
  288. # By https://en.wikipedia.org/wiki/Incomplete_gamma_function#Holomorphic_extension,
  289. # lowergamma(s, z) = z**s*gamma(s)*gammastar(s, z),
  290. # where gammastar(s, z) is holomorphic for all s and z.
  291. # Hence the singularities of lowergamma are z = 0 (branch
  292. # point) and nonpositive integer values of s (poles of gamma(s)).
  293. s, z = self.args
  294. args_merom = fuzzy_and([z._eval_is_meromorphic(x, a),
  295. s._eval_is_meromorphic(x, a)])
  296. if not args_merom:
  297. return args_merom
  298. z0 = z.subs(x, a)
  299. if s.is_integer:
  300. return fuzzy_and([s.is_positive, z0.is_finite])
  301. s0 = s.subs(x, a)
  302. return fuzzy_and([s0.is_finite, z0.is_finite, fuzzy_not(z0.is_zero)])
  303. def _eval_aseries(self, n, args0, x, logx):
  304. from sympy.series.order import O
  305. s, z = self.args
  306. if args0[0] is oo and not z.has(x):
  307. coeff = z**s*exp(-z)
  308. sum_expr = sum(z**k/rf(s, k + 1) for k in range(n - 1))
  309. o = O(z**s*s**(-n))
  310. return coeff*sum_expr + o
  311. return super()._eval_aseries(n, args0, x, logx)
  312. def _eval_rewrite_as_uppergamma(self, s, x, **kwargs):
  313. return gamma(s) - uppergamma(s, x)
  314. def _eval_rewrite_as_expint(self, s, x, **kwargs):
  315. from sympy.functions.special.error_functions import expint
  316. if s.is_integer and s.is_nonpositive:
  317. return self
  318. return self.rewrite(uppergamma).rewrite(expint)
  319. def _eval_is_zero(self):
  320. x = self.args[1]
  321. if x.is_zero:
  322. return True
  323. class uppergamma(Function):
  324. r"""
  325. The upper incomplete gamma function.
  326. Explanation
  327. ===========
  328. It can be defined as the meromorphic continuation of
  329. .. math::
  330. \Gamma(s, x) := \int_x^\infty t^{s-1} e^{-t} \mathrm{d}t = \Gamma(s) - \gamma(s, x).
  331. where $\gamma(s, x)$ is the lower incomplete gamma function,
  332. :class:`lowergamma`. This can be shown to be the same as
  333. .. math::
  334. \Gamma(s, x) = \Gamma(s) - \frac{x^s}{s} {}_1F_1\left({s \atop s+1} \middle| -x\right),
  335. where ${}_1F_1$ is the (confluent) hypergeometric function.
  336. The upper incomplete gamma function is also essentially equivalent to the
  337. generalized exponential integral:
  338. .. math::
  339. \operatorname{E}_{n}(x) = \int_{1}^{\infty}{\frac{e^{-xt}}{t^n} \, dt} = x^{n-1}\Gamma(1-n,x).
  340. Examples
  341. ========
  342. >>> from sympy import uppergamma, S
  343. >>> from sympy.abc import s, x
  344. >>> uppergamma(s, x)
  345. uppergamma(s, x)
  346. >>> uppergamma(3, x)
  347. 2*(x**2/2 + x + 1)*exp(-x)
  348. >>> uppergamma(-S(1)/2, x)
  349. -2*sqrt(pi)*erfc(sqrt(x)) + 2*exp(-x)/sqrt(x)
  350. >>> uppergamma(-2, x)
  351. expint(3, x)/x**2
  352. See Also
  353. ========
  354. gamma: Gamma function.
  355. lowergamma: Lower incomplete gamma function.
  356. polygamma: Polygamma function.
  357. loggamma: Log Gamma function.
  358. digamma: Digamma function.
  359. trigamma: Trigamma function.
  360. beta: Euler Beta function.
  361. References
  362. ==========
  363. .. [1] https://en.wikipedia.org/wiki/Incomplete_gamma_function#Upper_incomplete_gamma_function
  364. .. [2] Abramowitz, Milton; Stegun, Irene A., eds. (1965), Chapter 6,
  365. Section 5, Handbook of Mathematical Functions with Formulas, Graphs,
  366. and Mathematical Tables
  367. .. [3] https://dlmf.nist.gov/8
  368. .. [4] https://functions.wolfram.com/GammaBetaErf/Gamma2/
  369. .. [5] https://functions.wolfram.com/GammaBetaErf/Gamma3/
  370. .. [6] https://en.wikipedia.org/wiki/Exponential_integral#Relation_with_other_functions
  371. """
  372. def fdiff(self, argindex=2):
  373. from sympy.functions.special.hyper import meijerg
  374. if argindex == 2:
  375. a, z = self.args
  376. return -exp(-unpolarify(z))*z**(a - 1)
  377. elif argindex == 1:
  378. a, z = self.args
  379. return uppergamma(a, z)*log(z) + meijerg([], [1, 1], [0, 0, a], [], z)
  380. else:
  381. raise ArgumentIndexError(self, argindex)
  382. def _eval_evalf(self, prec):
  383. if all(x.is_number for x in self.args):
  384. a = self.args[0]._to_mpmath(prec)
  385. z = self.args[1]._to_mpmath(prec)
  386. with workprec(prec):
  387. res = mp.gammainc(a, z, mp.inf)
  388. return Expr._from_mpmath(res, prec)
  389. return self
  390. @classmethod
  391. def eval(cls, a, z):
  392. from sympy.functions.special.error_functions import expint
  393. if z.is_Number:
  394. if z is S.NaN:
  395. return S.NaN
  396. elif z is oo:
  397. return S.Zero
  398. elif z.is_zero:
  399. if re(a).is_positive:
  400. return gamma(a)
  401. # We extract branching information here. C/f lowergamma.
  402. nx, n = z.extract_branch_factor()
  403. if a.is_integer and a.is_positive:
  404. nx = unpolarify(z)
  405. if z != nx:
  406. return uppergamma(a, nx)
  407. elif a.is_integer and a.is_nonpositive:
  408. if n != 0:
  409. return -2*pi*I*n*S.NegativeOne**(-a)/factorial(-a) + uppergamma(a, nx)
  410. elif n != 0:
  411. return gamma(a)*(1 - exp(2*pi*I*n*a)) + exp(2*pi*I*n*a)*uppergamma(a, nx)
  412. # Special values.
  413. if a.is_Number:
  414. if a is S.Zero and z.is_positive:
  415. return -Ei(-z)
  416. elif a is S.One:
  417. return exp(-z)
  418. elif a is S.Half:
  419. return sqrt(pi)*erfc(sqrt(z))
  420. elif a.is_Integer or (2*a).is_Integer:
  421. b = a - 1
  422. if b.is_positive:
  423. if a.is_integer:
  424. return exp(-z) * factorial(b) * Add(*[z**k / factorial(k)
  425. for k in range(a)])
  426. else:
  427. return (gamma(a) * erfc(sqrt(z)) +
  428. S.NegativeOne**(a - S(3)/2) * exp(-z) * sqrt(z)
  429. * Add(*[gamma(-S.Half - k) * (-z)**k / gamma(1-a)
  430. for k in range(a - S.Half)]))
  431. elif b.is_Integer:
  432. return expint(-b, z)*unpolarify(z)**(b + 1)
  433. if not a.is_Integer:
  434. return (S.NegativeOne**(S.Half - a) * pi*erfc(sqrt(z))/gamma(1-a)
  435. - z**a * exp(-z) * Add(*[z**k * gamma(a) / gamma(a+k+1)
  436. for k in range(S.Half - a)]))
  437. if a.is_zero and z.is_positive:
  438. return -Ei(-z)
  439. if z.is_zero and re(a).is_positive:
  440. return gamma(a)
  441. def _eval_conjugate(self):
  442. z = self.args[1]
  443. if z not in (S.Zero, S.NegativeInfinity):
  444. return self.func(self.args[0].conjugate(), z.conjugate())
  445. def _eval_is_meromorphic(self, x, a):
  446. return lowergamma._eval_is_meromorphic(self, x, a)
  447. def _eval_rewrite_as_lowergamma(self, s, x, **kwargs):
  448. return gamma(s) - lowergamma(s, x)
  449. def _eval_rewrite_as_tractable(self, s, x, **kwargs):
  450. return exp(loggamma(s)) - lowergamma(s, x)
  451. def _eval_rewrite_as_expint(self, s, x, **kwargs):
  452. from sympy.functions.special.error_functions import expint
  453. return expint(1 - s, x)*x**s
  454. ###############################################################################
  455. ###################### POLYGAMMA and LOGGAMMA FUNCTIONS #######################
  456. ###############################################################################
  457. class polygamma(Function):
  458. r"""
  459. The function ``polygamma(n, z)`` returns ``log(gamma(z)).diff(n + 1)``.
  460. Explanation
  461. ===========
  462. It is a meromorphic function on $\mathbb{C}$ and defined as the $(n+1)$-th
  463. derivative of the logarithm of the gamma function:
  464. .. math::
  465. \psi^{(n)} (z) := \frac{\mathrm{d}^{n+1}}{\mathrm{d} z^{n+1}} \log\Gamma(z).
  466. For `n` not a nonnegative integer the generalization by Espinosa and Moll [5]_
  467. is used:
  468. .. math:: \psi(s,z) = \frac{\zeta'(s+1, z) + (\gamma + \psi(-s)) \zeta(s+1, z)}
  469. {\Gamma(-s)}
  470. Examples
  471. ========
  472. Several special values are known:
  473. >>> from sympy import S, polygamma
  474. >>> polygamma(0, 1)
  475. -EulerGamma
  476. >>> polygamma(0, 1/S(2))
  477. -2*log(2) - EulerGamma
  478. >>> polygamma(0, 1/S(3))
  479. -log(3) - sqrt(3)*pi/6 - EulerGamma - log(sqrt(3))
  480. >>> polygamma(0, 1/S(4))
  481. -pi/2 - log(4) - log(2) - EulerGamma
  482. >>> polygamma(0, 2)
  483. 1 - EulerGamma
  484. >>> polygamma(0, 23)
  485. 19093197/5173168 - EulerGamma
  486. >>> from sympy import oo, I
  487. >>> polygamma(0, oo)
  488. oo
  489. >>> polygamma(0, -oo)
  490. oo
  491. >>> polygamma(0, I*oo)
  492. oo
  493. >>> polygamma(0, -I*oo)
  494. oo
  495. Differentiation with respect to $x$ is supported:
  496. >>> from sympy import Symbol, diff
  497. >>> x = Symbol("x")
  498. >>> diff(polygamma(0, x), x)
  499. polygamma(1, x)
  500. >>> diff(polygamma(0, x), x, 2)
  501. polygamma(2, x)
  502. >>> diff(polygamma(0, x), x, 3)
  503. polygamma(3, x)
  504. >>> diff(polygamma(1, x), x)
  505. polygamma(2, x)
  506. >>> diff(polygamma(1, x), x, 2)
  507. polygamma(3, x)
  508. >>> diff(polygamma(2, x), x)
  509. polygamma(3, x)
  510. >>> diff(polygamma(2, x), x, 2)
  511. polygamma(4, x)
  512. >>> n = Symbol("n")
  513. >>> diff(polygamma(n, x), x)
  514. polygamma(n + 1, x)
  515. >>> diff(polygamma(n, x), x, 2)
  516. polygamma(n + 2, x)
  517. We can rewrite ``polygamma`` functions in terms of harmonic numbers:
  518. >>> from sympy import harmonic
  519. >>> polygamma(0, x).rewrite(harmonic)
  520. harmonic(x - 1) - EulerGamma
  521. >>> polygamma(2, x).rewrite(harmonic)
  522. 2*harmonic(x - 1, 3) - 2*zeta(3)
  523. >>> ni = Symbol("n", integer=True)
  524. >>> polygamma(ni, x).rewrite(harmonic)
  525. (-1)**(n + 1)*(-harmonic(x - 1, n + 1) + zeta(n + 1))*factorial(n)
  526. See Also
  527. ========
  528. gamma: Gamma function.
  529. lowergamma: Lower incomplete gamma function.
  530. uppergamma: Upper incomplete gamma function.
  531. loggamma: Log Gamma function.
  532. digamma: Digamma function.
  533. trigamma: Trigamma function.
  534. beta: Euler Beta function.
  535. References
  536. ==========
  537. .. [1] https://en.wikipedia.org/wiki/Polygamma_function
  538. .. [2] https://mathworld.wolfram.com/PolygammaFunction.html
  539. .. [3] https://functions.wolfram.com/GammaBetaErf/PolyGamma/
  540. .. [4] https://functions.wolfram.com/GammaBetaErf/PolyGamma2/
  541. .. [5] O. Espinosa and V. Moll, "A generalized polygamma function",
  542. *Integral Transforms and Special Functions* (2004), 101-115.
  543. """
  544. @classmethod
  545. def eval(cls, n, z):
  546. if n is S.NaN or z is S.NaN:
  547. return S.NaN
  548. elif z is oo:
  549. return oo if n.is_zero else S.Zero
  550. elif z.is_Integer and z.is_nonpositive:
  551. return S.ComplexInfinity
  552. elif n is S.NegativeOne:
  553. return loggamma(z) - log(2*pi) / 2
  554. elif n.is_zero:
  555. if z is -oo or z.extract_multiplicatively(I) in (oo, -oo):
  556. return oo
  557. elif z.is_Integer:
  558. return harmonic(z-1) - S.EulerGamma
  559. elif z.is_Rational:
  560. # TODO n == 1 also can do some rational z
  561. p, q = z.as_numer_denom()
  562. # only expand for small denominators to avoid creating long expressions
  563. if q <= 6:
  564. return expand_func(polygamma(S.Zero, z, evaluate=False))
  565. elif n.is_integer and n.is_nonnegative:
  566. nz = unpolarify(z)
  567. if z != nz:
  568. return polygamma(n, nz)
  569. if z.is_Integer:
  570. return S.NegativeOne**(n+1) * factorial(n) * zeta(n+1, z)
  571. elif z is S.Half:
  572. return S.NegativeOne**(n+1) * factorial(n) * (2**(n+1)-1) * zeta(n+1)
  573. def _eval_is_real(self):
  574. if self.args[0].is_positive and self.args[1].is_positive:
  575. return True
  576. def _eval_is_complex(self):
  577. z = self.args[1]
  578. is_negative_integer = fuzzy_and([z.is_negative, z.is_integer])
  579. return fuzzy_and([z.is_complex, fuzzy_not(is_negative_integer)])
  580. def _eval_is_positive(self):
  581. n, z = self.args
  582. if n.is_positive:
  583. if n.is_odd and z.is_real:
  584. return True
  585. if n.is_even and z.is_positive:
  586. return False
  587. def _eval_is_negative(self):
  588. n, z = self.args
  589. if n.is_positive:
  590. if n.is_even and z.is_positive:
  591. return True
  592. if n.is_odd and z.is_real:
  593. return False
  594. def _eval_expand_func(self, **hints):
  595. n, z = self.args
  596. if n.is_Integer and n.is_nonnegative:
  597. if z.is_Add:
  598. coeff = z.args[0]
  599. if coeff.is_Integer:
  600. e = -(n + 1)
  601. if coeff > 0:
  602. tail = Add(*[Pow(
  603. z - i, e) for i in range(1, int(coeff) + 1)])
  604. else:
  605. tail = -Add(*[Pow(
  606. z + i, e) for i in range(int(-coeff))])
  607. return polygamma(n, z - coeff) + S.NegativeOne**n*factorial(n)*tail
  608. elif z.is_Mul:
  609. coeff, z = z.as_two_terms()
  610. if coeff.is_Integer and coeff.is_positive:
  611. tail = [polygamma(n, z + Rational(
  612. i, coeff)) for i in range(int(coeff))]
  613. if n == 0:
  614. return Add(*tail)/coeff + log(coeff)
  615. else:
  616. return Add(*tail)/coeff**(n + 1)
  617. z *= coeff
  618. if n == 0 and z.is_Rational:
  619. p, q = z.as_numer_denom()
  620. # Reference:
  621. # Values of the polygamma functions at rational arguments, J. Choi, 2007
  622. part_1 = -S.EulerGamma - pi * cot(p * pi / q) / 2 - log(q) + Add(
  623. *[cos(2 * k * pi * p / q) * log(2 * sin(k * pi / q)) for k in range(1, q)])
  624. if z > 0:
  625. n = floor(z)
  626. z0 = z - n
  627. return part_1 + Add(*[1 / (z0 + k) for k in range(n)])
  628. elif z < 0:
  629. n = floor(1 - z)
  630. z0 = z + n
  631. return part_1 - Add(*[1 / (z0 - 1 - k) for k in range(n)])
  632. if n == -1:
  633. return loggamma(z) - log(2*pi) / 2
  634. if n.is_integer is False or n.is_nonnegative is False:
  635. s = Dummy("s")
  636. dzt = zeta(s, z).diff(s).subs(s, n+1)
  637. return (dzt + (S.EulerGamma + digamma(-n)) * zeta(n+1, z)) / gamma(-n)
  638. return polygamma(n, z)
  639. def _eval_rewrite_as_zeta(self, n, z, **kwargs):
  640. if n.is_integer and n.is_positive:
  641. return S.NegativeOne**(n + 1)*factorial(n)*zeta(n + 1, z)
  642. def _eval_rewrite_as_harmonic(self, n, z, **kwargs):
  643. if n.is_integer:
  644. if n.is_zero:
  645. return harmonic(z - 1) - S.EulerGamma
  646. else:
  647. return S.NegativeOne**(n+1) * factorial(n) * (zeta(n+1) - harmonic(z-1, n+1))
  648. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  649. from sympy.series.order import Order
  650. n, z = [a.as_leading_term(x) for a in self.args]
  651. o = Order(z, x)
  652. if n == 0 and o.contains(1/x):
  653. logx = log(x) if logx is None else logx
  654. return o.getn() * logx
  655. else:
  656. return self.func(n, z)
  657. def fdiff(self, argindex=2):
  658. if argindex == 2:
  659. n, z = self.args[:2]
  660. return polygamma(n + 1, z)
  661. else:
  662. raise ArgumentIndexError(self, argindex)
  663. def _eval_aseries(self, n, args0, x, logx):
  664. from sympy.series.order import Order
  665. if args0[1] != oo or not \
  666. (self.args[0].is_Integer and self.args[0].is_nonnegative):
  667. return super()._eval_aseries(n, args0, x, logx)
  668. z = self.args[1]
  669. N = self.args[0]
  670. if N == 0:
  671. # digamma function series
  672. # Abramowitz & Stegun, p. 259, 6.3.18
  673. r = log(z) - 1/(2*z)
  674. o = None
  675. if n < 2:
  676. o = Order(1/z, x)
  677. else:
  678. m = ceiling((n + 1)//2)
  679. l = [bernoulli(2*k) / (2*k*z**(2*k)) for k in range(1, m)]
  680. r -= Add(*l)
  681. o = Order(1/z**n, x)
  682. return r._eval_nseries(x, n, logx) + o
  683. else:
  684. # proper polygamma function
  685. # Abramowitz & Stegun, p. 260, 6.4.10
  686. # We return terms to order higher than O(x**n) on purpose
  687. # -- otherwise we would not be able to return any terms for
  688. # quite a long time!
  689. fac = gamma(N)
  690. e0 = fac + N*fac/(2*z)
  691. m = ceiling((n + 1)//2)
  692. for k in range(1, m):
  693. fac = fac*(2*k + N - 1)*(2*k + N - 2) / ((2*k)*(2*k - 1))
  694. e0 += bernoulli(2*k)*fac/z**(2*k)
  695. o = Order(1/z**(2*m), x)
  696. if n == 0:
  697. o = Order(1/z, x)
  698. elif n == 1:
  699. o = Order(1/z**2, x)
  700. r = e0._eval_nseries(z, n, logx) + o
  701. return (-1 * (-1/z)**N * r)._eval_nseries(x, n, logx)
  702. def _eval_evalf(self, prec):
  703. if not all(i.is_number for i in self.args):
  704. return
  705. s = self.args[0]._to_mpmath(prec+12)
  706. z = self.args[1]._to_mpmath(prec+12)
  707. if mp.isint(z) and z <= 0:
  708. return S.ComplexInfinity
  709. with workprec(prec+12):
  710. if mp.isint(s) and s >= 0:
  711. res = mp.polygamma(s, z)
  712. else:
  713. zt = mp.zeta(s+1, z)
  714. dzt = mp.zeta(s+1, z, 1)
  715. res = (dzt + (mp.euler + mp.digamma(-s)) * zt) * mp.rgamma(-s)
  716. return Expr._from_mpmath(res, prec)
  717. class loggamma(Function):
  718. r"""
  719. The ``loggamma`` function implements the logarithm of the
  720. gamma function (i.e., $\log\Gamma(x)$).
  721. Examples
  722. ========
  723. Several special values are known. For numerical integral
  724. arguments we have:
  725. >>> from sympy import loggamma
  726. >>> loggamma(-2)
  727. oo
  728. >>> loggamma(0)
  729. oo
  730. >>> loggamma(1)
  731. 0
  732. >>> loggamma(2)
  733. 0
  734. >>> loggamma(3)
  735. log(2)
  736. And for symbolic values:
  737. >>> from sympy import Symbol
  738. >>> n = Symbol("n", integer=True, positive=True)
  739. >>> loggamma(n)
  740. log(gamma(n))
  741. >>> loggamma(-n)
  742. oo
  743. For half-integral values:
  744. >>> from sympy import S
  745. >>> loggamma(S(5)/2)
  746. log(3*sqrt(pi)/4)
  747. >>> loggamma(n/2)
  748. log(2**(1 - n)*sqrt(pi)*gamma(n)/gamma(n/2 + 1/2))
  749. And general rational arguments:
  750. >>> from sympy import expand_func
  751. >>> L = loggamma(S(16)/3)
  752. >>> expand_func(L).doit()
  753. -5*log(3) + loggamma(1/3) + log(4) + log(7) + log(10) + log(13)
  754. >>> L = loggamma(S(19)/4)
  755. >>> expand_func(L).doit()
  756. -4*log(4) + loggamma(3/4) + log(3) + log(7) + log(11) + log(15)
  757. >>> L = loggamma(S(23)/7)
  758. >>> expand_func(L).doit()
  759. -3*log(7) + log(2) + loggamma(2/7) + log(9) + log(16)
  760. The ``loggamma`` function has the following limits towards infinity:
  761. >>> from sympy import oo
  762. >>> loggamma(oo)
  763. oo
  764. >>> loggamma(-oo)
  765. zoo
  766. The ``loggamma`` function obeys the mirror symmetry
  767. if $x \in \mathbb{C} \setminus \{-\infty, 0\}$:
  768. >>> from sympy.abc import x
  769. >>> from sympy import conjugate
  770. >>> conjugate(loggamma(x))
  771. loggamma(conjugate(x))
  772. Differentiation with respect to $x$ is supported:
  773. >>> from sympy import diff
  774. >>> diff(loggamma(x), x)
  775. polygamma(0, x)
  776. Series expansion is also supported:
  777. >>> from sympy import series
  778. >>> series(loggamma(x), x, 0, 4).cancel()
  779. -log(x) - EulerGamma*x + pi**2*x**2/12 - x**3*zeta(3)/3 + O(x**4)
  780. We can numerically evaluate the ``loggamma`` function
  781. to arbitrary precision on the whole complex plane:
  782. >>> from sympy import I
  783. >>> loggamma(5).evalf(30)
  784. 3.17805383034794561964694160130
  785. >>> loggamma(I).evalf(20)
  786. -0.65092319930185633889 - 1.8724366472624298171*I
  787. See Also
  788. ========
  789. gamma: Gamma function.
  790. lowergamma: Lower incomplete gamma function.
  791. uppergamma: Upper incomplete gamma function.
  792. polygamma: Polygamma function.
  793. digamma: Digamma function.
  794. trigamma: Trigamma function.
  795. beta: Euler Beta function.
  796. References
  797. ==========
  798. .. [1] https://en.wikipedia.org/wiki/Gamma_function
  799. .. [2] https://dlmf.nist.gov/5
  800. .. [3] https://mathworld.wolfram.com/LogGammaFunction.html
  801. .. [4] https://functions.wolfram.com/GammaBetaErf/LogGamma/
  802. """
  803. @classmethod
  804. def eval(cls, z):
  805. if z.is_integer:
  806. if z.is_nonpositive:
  807. return oo
  808. elif z.is_positive:
  809. return log(gamma(z))
  810. elif z.is_rational:
  811. p, q = z.as_numer_denom()
  812. # Half-integral values:
  813. if p.is_positive and q == 2:
  814. return log(sqrt(pi) * 2**(1 - p) * gamma(p) / gamma((p + 1)*S.Half))
  815. if z is oo:
  816. return oo
  817. elif abs(z) is oo:
  818. return S.ComplexInfinity
  819. if z is S.NaN:
  820. return S.NaN
  821. def _eval_expand_func(self, **hints):
  822. from sympy.concrete.summations import Sum
  823. z = self.args[0]
  824. if z.is_Rational:
  825. p, q = z.as_numer_denom()
  826. # General rational arguments (u + p/q)
  827. # Split z as n + p/q with p < q
  828. n = p // q
  829. p = p - n*q
  830. if p.is_positive and q.is_positive and p < q:
  831. k = Dummy("k")
  832. if n.is_positive:
  833. return loggamma(p / q) - n*log(q) + Sum(log((k - 1)*q + p), (k, 1, n))
  834. elif n.is_negative:
  835. return loggamma(p / q) - n*log(q) + pi*I*n - Sum(log(k*q - p), (k, 1, -n))
  836. elif n.is_zero:
  837. return loggamma(p / q)
  838. return self
  839. def _eval_nseries(self, x, n, logx=None, cdir=0):
  840. x0 = self.args[0].limit(x, 0)
  841. if x0.is_zero:
  842. f = self._eval_rewrite_as_intractable(*self.args)
  843. return f._eval_nseries(x, n, logx)
  844. return super()._eval_nseries(x, n, logx)
  845. def _eval_aseries(self, n, args0, x, logx):
  846. from sympy.series.order import Order
  847. if args0[0] != oo:
  848. return super()._eval_aseries(n, args0, x, logx)
  849. z = self.args[0]
  850. r = log(z)*(z - S.Half) - z + log(2*pi)/2
  851. l = [bernoulli(2*k) / (2*k*(2*k - 1)*z**(2*k - 1)) for k in range(1, n)]
  852. o = None
  853. if n == 0:
  854. o = Order(1, x)
  855. else:
  856. o = Order(1/z**n, x)
  857. # It is very inefficient to first add the order and then do the nseries
  858. return (r + Add(*l))._eval_nseries(x, n, logx) + o
  859. def _eval_rewrite_as_intractable(self, z, **kwargs):
  860. return log(gamma(z))
  861. def _eval_is_real(self):
  862. z = self.args[0]
  863. if z.is_positive:
  864. return True
  865. elif z.is_nonpositive:
  866. return False
  867. def _eval_conjugate(self):
  868. z = self.args[0]
  869. if z not in (S.Zero, S.NegativeInfinity):
  870. return self.func(z.conjugate())
  871. def fdiff(self, argindex=1):
  872. if argindex == 1:
  873. return polygamma(0, self.args[0])
  874. else:
  875. raise ArgumentIndexError(self, argindex)
  876. class digamma(Function):
  877. r"""
  878. The ``digamma`` function is the first derivative of the ``loggamma``
  879. function
  880. .. math::
  881. \psi(x) := \frac{\mathrm{d}}{\mathrm{d} z} \log\Gamma(z)
  882. = \frac{\Gamma'(z)}{\Gamma(z) }.
  883. In this case, ``digamma(z) = polygamma(0, z)``.
  884. Examples
  885. ========
  886. >>> from sympy import digamma
  887. >>> digamma(0)
  888. zoo
  889. >>> from sympy import Symbol
  890. >>> z = Symbol('z')
  891. >>> digamma(z)
  892. polygamma(0, z)
  893. To retain ``digamma`` as it is:
  894. >>> digamma(0, evaluate=False)
  895. digamma(0)
  896. >>> digamma(z, evaluate=False)
  897. digamma(z)
  898. See Also
  899. ========
  900. gamma: Gamma function.
  901. lowergamma: Lower incomplete gamma function.
  902. uppergamma: Upper incomplete gamma function.
  903. polygamma: Polygamma function.
  904. loggamma: Log Gamma function.
  905. trigamma: Trigamma function.
  906. beta: Euler Beta function.
  907. References
  908. ==========
  909. .. [1] https://en.wikipedia.org/wiki/Digamma_function
  910. .. [2] https://mathworld.wolfram.com/DigammaFunction.html
  911. .. [3] https://functions.wolfram.com/GammaBetaErf/PolyGamma2/
  912. """
  913. def _eval_evalf(self, prec):
  914. z = self.args[0]
  915. nprec = prec_to_dps(prec)
  916. return polygamma(0, z).evalf(n=nprec)
  917. def fdiff(self, argindex=1):
  918. z = self.args[0]
  919. return polygamma(0, z).fdiff()
  920. def _eval_is_real(self):
  921. z = self.args[0]
  922. return polygamma(0, z).is_real
  923. def _eval_is_positive(self):
  924. z = self.args[0]
  925. return polygamma(0, z).is_positive
  926. def _eval_is_negative(self):
  927. z = self.args[0]
  928. return polygamma(0, z).is_negative
  929. def _eval_aseries(self, n, args0, x, logx):
  930. as_polygamma = self.rewrite(polygamma)
  931. args0 = [S.Zero,] + args0
  932. return as_polygamma._eval_aseries(n, args0, x, logx)
  933. @classmethod
  934. def eval(cls, z):
  935. return polygamma(0, z)
  936. def _eval_expand_func(self, **hints):
  937. z = self.args[0]
  938. return polygamma(0, z).expand(func=True)
  939. def _eval_rewrite_as_harmonic(self, z, **kwargs):
  940. return harmonic(z - 1) - S.EulerGamma
  941. def _eval_rewrite_as_polygamma(self, z, **kwargs):
  942. return polygamma(0, z)
  943. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  944. z = self.args[0]
  945. return polygamma(0, z).as_leading_term(x)
  946. class trigamma(Function):
  947. r"""
  948. The ``trigamma`` function is the second derivative of the ``loggamma``
  949. function
  950. .. math::
  951. \psi^{(1)}(z) := \frac{\mathrm{d}^{2}}{\mathrm{d} z^{2}} \log\Gamma(z).
  952. In this case, ``trigamma(z) = polygamma(1, z)``.
  953. Examples
  954. ========
  955. >>> from sympy import trigamma
  956. >>> trigamma(0)
  957. zoo
  958. >>> from sympy import Symbol
  959. >>> z = Symbol('z')
  960. >>> trigamma(z)
  961. polygamma(1, z)
  962. To retain ``trigamma`` as it is:
  963. >>> trigamma(0, evaluate=False)
  964. trigamma(0)
  965. >>> trigamma(z, evaluate=False)
  966. trigamma(z)
  967. See Also
  968. ========
  969. gamma: Gamma function.
  970. lowergamma: Lower incomplete gamma function.
  971. uppergamma: Upper incomplete gamma function.
  972. polygamma: Polygamma function.
  973. loggamma: Log Gamma function.
  974. digamma: Digamma function.
  975. beta: Euler Beta function.
  976. References
  977. ==========
  978. .. [1] https://en.wikipedia.org/wiki/Trigamma_function
  979. .. [2] https://mathworld.wolfram.com/TrigammaFunction.html
  980. .. [3] https://functions.wolfram.com/GammaBetaErf/PolyGamma2/
  981. """
  982. def _eval_evalf(self, prec):
  983. z = self.args[0]
  984. nprec = prec_to_dps(prec)
  985. return polygamma(1, z).evalf(n=nprec)
  986. def fdiff(self, argindex=1):
  987. z = self.args[0]
  988. return polygamma(1, z).fdiff()
  989. def _eval_is_real(self):
  990. z = self.args[0]
  991. return polygamma(1, z).is_real
  992. def _eval_is_positive(self):
  993. z = self.args[0]
  994. return polygamma(1, z).is_positive
  995. def _eval_is_negative(self):
  996. z = self.args[0]
  997. return polygamma(1, z).is_negative
  998. def _eval_aseries(self, n, args0, x, logx):
  999. as_polygamma = self.rewrite(polygamma)
  1000. args0 = [S.One,] + args0
  1001. return as_polygamma._eval_aseries(n, args0, x, logx)
  1002. @classmethod
  1003. def eval(cls, z):
  1004. return polygamma(1, z)
  1005. def _eval_expand_func(self, **hints):
  1006. z = self.args[0]
  1007. return polygamma(1, z).expand(func=True)
  1008. def _eval_rewrite_as_zeta(self, z, **kwargs):
  1009. return zeta(2, z)
  1010. def _eval_rewrite_as_polygamma(self, z, **kwargs):
  1011. return polygamma(1, z)
  1012. def _eval_rewrite_as_harmonic(self, z, **kwargs):
  1013. return -harmonic(z - 1, 2) + pi**2 / 6
  1014. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  1015. z = self.args[0]
  1016. return polygamma(1, z).as_leading_term(x)
  1017. ###############################################################################
  1018. ##################### COMPLETE MULTIVARIATE GAMMA FUNCTION ####################
  1019. ###############################################################################
  1020. class multigamma(Function):
  1021. r"""
  1022. The multivariate gamma function is a generalization of the gamma function
  1023. .. math::
  1024. \Gamma_p(z) = \pi^{p(p-1)/4}\prod_{k=1}^p \Gamma[z + (1 - k)/2].
  1025. In a special case, ``multigamma(x, 1) = gamma(x)``.
  1026. Examples
  1027. ========
  1028. >>> from sympy import S, multigamma
  1029. >>> from sympy import Symbol
  1030. >>> x = Symbol('x')
  1031. >>> p = Symbol('p', positive=True, integer=True)
  1032. >>> multigamma(x, p)
  1033. pi**(p*(p - 1)/4)*Product(gamma(-_k/2 + x + 1/2), (_k, 1, p))
  1034. Several special values are known:
  1035. >>> multigamma(1, 1)
  1036. 1
  1037. >>> multigamma(4, 1)
  1038. 6
  1039. >>> multigamma(S(3)/2, 1)
  1040. sqrt(pi)/2
  1041. Writing ``multigamma`` in terms of the ``gamma`` function:
  1042. >>> multigamma(x, 1)
  1043. gamma(x)
  1044. >>> multigamma(x, 2)
  1045. sqrt(pi)*gamma(x)*gamma(x - 1/2)
  1046. >>> multigamma(x, 3)
  1047. pi**(3/2)*gamma(x)*gamma(x - 1)*gamma(x - 1/2)
  1048. Parameters
  1049. ==========
  1050. p : order or dimension of the multivariate gamma function
  1051. See Also
  1052. ========
  1053. gamma, lowergamma, uppergamma, polygamma, loggamma, digamma, trigamma,
  1054. beta
  1055. References
  1056. ==========
  1057. .. [1] https://en.wikipedia.org/wiki/Multivariate_gamma_function
  1058. """
  1059. unbranched = True
  1060. def fdiff(self, argindex=2):
  1061. from sympy.concrete.summations import Sum
  1062. if argindex == 2:
  1063. x, p = self.args
  1064. k = Dummy("k")
  1065. return self.func(x, p)*Sum(polygamma(0, x + (1 - k)/2), (k, 1, p))
  1066. else:
  1067. raise ArgumentIndexError(self, argindex)
  1068. @classmethod
  1069. def eval(cls, x, p):
  1070. from sympy.concrete.products import Product
  1071. if p.is_positive is False or p.is_integer is False:
  1072. raise ValueError('Order parameter p must be positive integer.')
  1073. k = Dummy("k")
  1074. return (pi**(p*(p - 1)/4)*Product(gamma(x + (1 - k)/2),
  1075. (k, 1, p))).doit()
  1076. def _eval_conjugate(self):
  1077. x, p = self.args
  1078. return self.func(x.conjugate(), p)
  1079. def _eval_is_real(self):
  1080. x, p = self.args
  1081. y = 2*x
  1082. if y.is_integer and (y <= (p - 1)) is True:
  1083. return False
  1084. if intlike(y) and (y <= (p - 1)):
  1085. return False
  1086. if y > (p - 1) or y.is_noninteger:
  1087. return True