Coverage for /usr/lib/python3/dist-packages/sympy/functions/special/bessel.py: 22%
868 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1from functools import wraps
3from sympy.core import S
4from sympy.core.add import Add
5from sympy.core.cache import cacheit
6from sympy.core.expr import Expr
7from sympy.core.function import Function, ArgumentIndexError, _mexpand
8from sympy.core.logic import fuzzy_or, fuzzy_not
9from sympy.core.numbers import Rational, pi, I
10from sympy.core.power import Pow
11from sympy.core.symbol import Dummy, Wild
12from sympy.core.sympify import sympify
13from sympy.functions.combinatorial.factorials import factorial
14from sympy.functions.elementary.trigonometric import sin, cos, csc, cot
15from sympy.functions.elementary.integers import ceiling
16from sympy.functions.elementary.exponential import exp, log
17from sympy.functions.elementary.miscellaneous import cbrt, sqrt, root
18from sympy.functions.elementary.complexes import (Abs, re, im, polar_lift, unpolarify)
19from sympy.functions.special.gamma_functions import gamma, digamma, uppergamma
20from sympy.functions.special.hyper import hyper
21from sympy.polys.orthopolys import spherical_bessel_fn
23from mpmath import mp, workprec
25# TODO
26# o Scorer functions G1 and G2
27# o Asymptotic expansions
28# These are possible, e.g. for fixed order, but since the bessel type
29# functions are oscillatory they are not actually tractable at
30# infinity, so this is not particularly useful right now.
31# o Nicer series expansions.
32# o More rewriting.
33# o Add solvers to ode.py (or rather add solvers for the hypergeometric equation).
36class BesselBase(Function):
37 """
38 Abstract base class for Bessel-type functions.
40 This class is meant to reduce code duplication.
41 All Bessel-type functions can 1) be differentiated, with the derivatives
42 expressed in terms of similar functions, and 2) be rewritten in terms
43 of other Bessel-type functions.
45 Here, Bessel-type functions are assumed to have one complex parameter.
47 To use this base class, define class attributes ``_a`` and ``_b`` such that
48 ``2*F_n' = -_a*F_{n+1} + b*F_{n-1}``.
50 """
52 @property
53 def order(self):
54 """ The order of the Bessel-type function. """
55 return self.args[0]
57 @property
58 def argument(self):
59 """ The argument of the Bessel-type function. """
60 return self.args[1]
62 @classmethod
63 def eval(cls, nu, z):
64 return
66 def fdiff(self, argindex=2):
67 if argindex != 2:
68 raise ArgumentIndexError(self, argindex)
69 return (self._b/2 * self.__class__(self.order - 1, self.argument) -
70 self._a/2 * self.__class__(self.order + 1, self.argument))
72 def _eval_conjugate(self):
73 z = self.argument
74 if z.is_extended_negative is False:
75 return self.__class__(self.order.conjugate(), z.conjugate())
77 def _eval_is_meromorphic(self, x, a):
78 nu, z = self.order, self.argument
80 if nu.has(x):
81 return False
82 if not z._eval_is_meromorphic(x, a):
83 return None
84 z0 = z.subs(x, a)
85 if nu.is_integer:
86 if isinstance(self, (besselj, besseli, hn1, hn2, jn, yn)) or not nu.is_zero:
87 return fuzzy_not(z0.is_infinite)
88 return fuzzy_not(fuzzy_or([z0.is_zero, z0.is_infinite]))
90 def _eval_expand_func(self, **hints):
91 nu, z, f = self.order, self.argument, self.__class__
92 if nu.is_real:
93 if (nu - 1).is_positive:
94 return (-self._a*self._b*f(nu - 2, z)._eval_expand_func() +
95 2*self._a*(nu - 1)*f(nu - 1, z)._eval_expand_func()/z)
96 elif (nu + 1).is_negative:
97 return (2*self._b*(nu + 1)*f(nu + 1, z)._eval_expand_func()/z -
98 self._a*self._b*f(nu + 2, z)._eval_expand_func())
99 return self
101 def _eval_simplify(self, **kwargs):
102 from sympy.simplify.simplify import besselsimp
103 return besselsimp(self)
106class besselj(BesselBase):
107 r"""
108 Bessel function of the first kind.
110 Explanation
111 ===========
113 The Bessel $J$ function of order $\nu$ is defined to be the function
114 satisfying Bessel's differential equation
116 .. math ::
117 z^2 \frac{\mathrm{d}^2 w}{\mathrm{d}z^2}
118 + z \frac{\mathrm{d}w}{\mathrm{d}z} + (z^2 - \nu^2) w = 0,
120 with Laurent expansion
122 .. math ::
123 J_\nu(z) = z^\nu \left(\frac{1}{\Gamma(\nu + 1) 2^\nu} + O(z^2) \right),
125 if $\nu$ is not a negative integer. If $\nu=-n \in \mathbb{Z}_{<0}$
126 *is* a negative integer, then the definition is
128 .. math ::
129 J_{-n}(z) = (-1)^n J_n(z).
131 Examples
132 ========
134 Create a Bessel function object:
136 >>> from sympy import besselj, jn
137 >>> from sympy.abc import z, n
138 >>> b = besselj(n, z)
140 Differentiate it:
142 >>> b.diff(z)
143 besselj(n - 1, z)/2 - besselj(n + 1, z)/2
145 Rewrite in terms of spherical Bessel functions:
147 >>> b.rewrite(jn)
148 sqrt(2)*sqrt(z)*jn(n - 1/2, z)/sqrt(pi)
150 Access the parameter and argument:
152 >>> b.order
153 n
154 >>> b.argument
155 z
157 See Also
158 ========
160 bessely, besseli, besselk
162 References
163 ==========
165 .. [1] Abramowitz, Milton; Stegun, Irene A., eds. (1965), "Chapter 9",
166 Handbook of Mathematical Functions with Formulas, Graphs, and
167 Mathematical Tables
168 .. [2] Luke, Y. L. (1969), The Special Functions and Their
169 Approximations, Volume 1
170 .. [3] https://en.wikipedia.org/wiki/Bessel_function
171 .. [4] https://functions.wolfram.com/Bessel-TypeFunctions/BesselJ/
173 """
175 _a = S.One
176 _b = S.One
178 @classmethod
179 def eval(cls, nu, z):
180 if z.is_zero:
181 if nu.is_zero:
182 return S.One
183 elif (nu.is_integer and nu.is_zero is False) or re(nu).is_positive:
184 return S.Zero
185 elif re(nu).is_negative and not (nu.is_integer is True):
186 return S.ComplexInfinity
187 elif nu.is_imaginary:
188 return S.NaN
189 if z in (S.Infinity, S.NegativeInfinity):
190 return S.Zero
192 if z.could_extract_minus_sign():
193 return (z)**nu*(-z)**(-nu)*besselj(nu, -z)
194 if nu.is_integer:
195 if nu.could_extract_minus_sign():
196 return S.NegativeOne**(-nu)*besselj(-nu, z)
197 newz = z.extract_multiplicatively(I)
198 if newz: # NOTE we don't want to change the function if z==0
199 return I**(nu)*besseli(nu, newz)
201 # branch handling:
202 if nu.is_integer:
203 newz = unpolarify(z)
204 if newz != z:
205 return besselj(nu, newz)
206 else:
207 newz, n = z.extract_branch_factor()
208 if n != 0:
209 return exp(2*n*pi*nu*I)*besselj(nu, newz)
210 nnu = unpolarify(nu)
211 if nu != nnu:
212 return besselj(nnu, z)
214 def _eval_rewrite_as_besseli(self, nu, z, **kwargs):
215 return exp(I*pi*nu/2)*besseli(nu, polar_lift(-I)*z)
217 def _eval_rewrite_as_bessely(self, nu, z, **kwargs):
218 if nu.is_integer is False:
219 return csc(pi*nu)*bessely(-nu, z) - cot(pi*nu)*bessely(nu, z)
221 def _eval_rewrite_as_jn(self, nu, z, **kwargs):
222 return sqrt(2*z/pi)*jn(nu - S.Half, self.argument)
224 def _eval_as_leading_term(self, x, logx=None, cdir=0):
225 nu, z = self.args
226 try:
227 arg = z.as_leading_term(x)
228 except NotImplementedError:
229 return self
230 c, e = arg.as_coeff_exponent(x)
232 if e.is_positive:
233 return arg**nu/(2**nu*gamma(nu + 1))
234 elif e.is_negative:
235 cdir = 1 if cdir == 0 else cdir
236 sign = c*cdir**e
237 if not sign.is_negative:
238 # Refer Abramowitz and Stegun 1965, p. 364 for more information on
239 # asymptotic approximation of besselj function.
240 return sqrt(2)*cos(z - pi*(2*nu + 1)/4)/sqrt(pi*z)
241 return self
243 return super(besselj, self)._eval_as_leading_term(x, logx, cdir)
245 def _eval_is_extended_real(self):
246 nu, z = self.args
247 if nu.is_integer and z.is_extended_real:
248 return True
250 def _eval_nseries(self, x, n, logx, cdir=0):
251 # Refer https://functions.wolfram.com/Bessel-TypeFunctions/BesselJ/06/01/04/01/01/0003/
252 # for more information on nseries expansion of besselj function.
253 from sympy.series.order import Order
254 nu, z = self.args
256 # In case of powers less than 1, number of terms need to be computed
257 # separately to avoid repeated callings of _eval_nseries with wrong n
258 try:
259 _, exp = z.leadterm(x)
260 except (ValueError, NotImplementedError):
261 return self
263 if exp.is_positive:
264 newn = ceiling(n/exp)
265 o = Order(x**n, x)
266 r = (z/2)._eval_nseries(x, n, logx, cdir).removeO()
267 if r is S.Zero:
268 return o
269 t = (_mexpand(r**2) + o).removeO()
271 term = r**nu/gamma(nu + 1)
272 s = [term]
273 for k in range(1, (newn + 1)//2):
274 term *= -t/(k*(nu + k))
275 term = (_mexpand(term) + o).removeO()
276 s.append(term)
277 return Add(*s) + o
279 return super(besselj, self)._eval_nseries(x, n, logx, cdir)
282class bessely(BesselBase):
283 r"""
284 Bessel function of the second kind.
286 Explanation
287 ===========
289 The Bessel $Y$ function of order $\nu$ is defined as
291 .. math ::
292 Y_\nu(z) = \lim_{\mu \to \nu} \frac{J_\mu(z) \cos(\pi \mu)
293 - J_{-\mu}(z)}{\sin(\pi \mu)},
295 where $J_\mu(z)$ is the Bessel function of the first kind.
297 It is a solution to Bessel's equation, and linearly independent from
298 $J_\nu$.
300 Examples
301 ========
303 >>> from sympy import bessely, yn
304 >>> from sympy.abc import z, n
305 >>> b = bessely(n, z)
306 >>> b.diff(z)
307 bessely(n - 1, z)/2 - bessely(n + 1, z)/2
308 >>> b.rewrite(yn)
309 sqrt(2)*sqrt(z)*yn(n - 1/2, z)/sqrt(pi)
311 See Also
312 ========
314 besselj, besseli, besselk
316 References
317 ==========
319 .. [1] https://functions.wolfram.com/Bessel-TypeFunctions/BesselY/
321 """
323 _a = S.One
324 _b = S.One
326 @classmethod
327 def eval(cls, nu, z):
328 if z.is_zero:
329 if nu.is_zero:
330 return S.NegativeInfinity
331 elif re(nu).is_zero is False:
332 return S.ComplexInfinity
333 elif re(nu).is_zero:
334 return S.NaN
335 if z in (S.Infinity, S.NegativeInfinity):
336 return S.Zero
337 if z == I*S.Infinity:
338 return exp(I*pi*(nu + 1)/2) * S.Infinity
339 if z == I*S.NegativeInfinity:
340 return exp(-I*pi*(nu + 1)/2) * S.Infinity
342 if nu.is_integer:
343 if nu.could_extract_minus_sign():
344 return S.NegativeOne**(-nu)*bessely(-nu, z)
346 def _eval_rewrite_as_besselj(self, nu, z, **kwargs):
347 if nu.is_integer is False:
348 return csc(pi*nu)*(cos(pi*nu)*besselj(nu, z) - besselj(-nu, z))
350 def _eval_rewrite_as_besseli(self, nu, z, **kwargs):
351 aj = self._eval_rewrite_as_besselj(*self.args)
352 if aj:
353 return aj.rewrite(besseli)
355 def _eval_rewrite_as_yn(self, nu, z, **kwargs):
356 return sqrt(2*z/pi) * yn(nu - S.Half, self.argument)
358 def _eval_as_leading_term(self, x, logx=None, cdir=0):
359 nu, z = self.args
360 try:
361 arg = z.as_leading_term(x)
362 except NotImplementedError:
363 return self
364 c, e = arg.as_coeff_exponent(x)
366 if e.is_positive:
367 term_one = ((2/pi)*log(z/2)*besselj(nu, z))
368 term_two = -(z/2)**(-nu)*factorial(nu - 1)/pi if (nu).is_positive else S.Zero
369 term_three = -(z/2)**nu/(pi*factorial(nu))*(digamma(nu + 1) - S.EulerGamma)
370 arg = Add(*[term_one, term_two, term_three]).as_leading_term(x, logx=logx)
371 return arg
372 elif e.is_negative:
373 cdir = 1 if cdir == 0 else cdir
374 sign = c*cdir**e
375 if not sign.is_negative:
376 # Refer Abramowitz and Stegun 1965, p. 364 for more information on
377 # asymptotic approximation of bessely function.
378 return sqrt(2)*(-sin(pi*nu/2 - z + pi/4) + 3*cos(pi*nu/2 - z + pi/4)/(8*z))*sqrt(1/z)/sqrt(pi)
379 return self
381 return super(bessely, self)._eval_as_leading_term(x, logx, cdir)
383 def _eval_is_extended_real(self):
384 nu, z = self.args
385 if nu.is_integer and z.is_positive:
386 return True
388 def _eval_nseries(self, x, n, logx, cdir=0):
389 # Refer https://functions.wolfram.com/Bessel-TypeFunctions/BesselY/06/01/04/01/02/0008/
390 # for more information on nseries expansion of bessely function.
391 from sympy.series.order import Order
392 nu, z = self.args
394 # In case of powers less than 1, number of terms need to be computed
395 # separately to avoid repeated callings of _eval_nseries with wrong n
396 try:
397 _, exp = z.leadterm(x)
398 except (ValueError, NotImplementedError):
399 return self
401 if exp.is_positive and nu.is_integer:
402 newn = ceiling(n/exp)
403 bn = besselj(nu, z)
404 a = ((2/pi)*log(z/2)*bn)._eval_nseries(x, n, logx, cdir)
406 b, c = [], []
407 o = Order(x**n, x)
408 r = (z/2)._eval_nseries(x, n, logx, cdir).removeO()
409 if r is S.Zero:
410 return o
411 t = (_mexpand(r**2) + o).removeO()
413 if nu > S.Zero:
414 term = r**(-nu)*factorial(nu - 1)/pi
415 b.append(term)
416 for k in range(1, nu):
417 denom = (nu - k)*k
418 if denom == S.Zero:
419 term *= t/k
420 else:
421 term *= t/denom
422 term = (_mexpand(term) + o).removeO()
423 b.append(term)
425 p = r**nu/(pi*factorial(nu))
426 term = p*(digamma(nu + 1) - S.EulerGamma)
427 c.append(term)
428 for k in range(1, (newn + 1)//2):
429 p *= -t/(k*(k + nu))
430 p = (_mexpand(p) + o).removeO()
431 term = p*(digamma(k + nu + 1) + digamma(k + 1))
432 c.append(term)
433 return a - Add(*b) - Add(*c) # Order term comes from a
435 return super(bessely, self)._eval_nseries(x, n, logx, cdir)
438class besseli(BesselBase):
439 r"""
440 Modified Bessel function of the first kind.
442 Explanation
443 ===========
445 The Bessel $I$ function is a solution to the modified Bessel equation
447 .. math ::
448 z^2 \frac{\mathrm{d}^2 w}{\mathrm{d}z^2}
449 + z \frac{\mathrm{d}w}{\mathrm{d}z} + (z^2 + \nu^2)^2 w = 0.
451 It can be defined as
453 .. math ::
454 I_\nu(z) = i^{-\nu} J_\nu(iz),
456 where $J_\nu(z)$ is the Bessel function of the first kind.
458 Examples
459 ========
461 >>> from sympy import besseli
462 >>> from sympy.abc import z, n
463 >>> besseli(n, z).diff(z)
464 besseli(n - 1, z)/2 + besseli(n + 1, z)/2
466 See Also
467 ========
469 besselj, bessely, besselk
471 References
472 ==========
474 .. [1] https://functions.wolfram.com/Bessel-TypeFunctions/BesselI/
476 """
478 _a = -S.One
479 _b = S.One
481 @classmethod
482 def eval(cls, nu, z):
483 if z.is_zero:
484 if nu.is_zero:
485 return S.One
486 elif (nu.is_integer and nu.is_zero is False) or re(nu).is_positive:
487 return S.Zero
488 elif re(nu).is_negative and not (nu.is_integer is True):
489 return S.ComplexInfinity
490 elif nu.is_imaginary:
491 return S.NaN
492 if im(z) in (S.Infinity, S.NegativeInfinity):
493 return S.Zero
494 if z is S.Infinity:
495 return S.Infinity
496 if z is S.NegativeInfinity:
497 return (-1)**nu*S.Infinity
499 if z.could_extract_minus_sign():
500 return (z)**nu*(-z)**(-nu)*besseli(nu, -z)
501 if nu.is_integer:
502 if nu.could_extract_minus_sign():
503 return besseli(-nu, z)
504 newz = z.extract_multiplicatively(I)
505 if newz: # NOTE we don't want to change the function if z==0
506 return I**(-nu)*besselj(nu, -newz)
508 # branch handling:
509 if nu.is_integer:
510 newz = unpolarify(z)
511 if newz != z:
512 return besseli(nu, newz)
513 else:
514 newz, n = z.extract_branch_factor()
515 if n != 0:
516 return exp(2*n*pi*nu*I)*besseli(nu, newz)
517 nnu = unpolarify(nu)
518 if nu != nnu:
519 return besseli(nnu, z)
521 def _eval_rewrite_as_besselj(self, nu, z, **kwargs):
522 return exp(-I*pi*nu/2)*besselj(nu, polar_lift(I)*z)
524 def _eval_rewrite_as_bessely(self, nu, z, **kwargs):
525 aj = self._eval_rewrite_as_besselj(*self.args)
526 if aj:
527 return aj.rewrite(bessely)
529 def _eval_rewrite_as_jn(self, nu, z, **kwargs):
530 return self._eval_rewrite_as_besselj(*self.args).rewrite(jn)
532 def _eval_is_extended_real(self):
533 nu, z = self.args
534 if nu.is_integer and z.is_extended_real:
535 return True
537 def _eval_as_leading_term(self, x, logx=None, cdir=0):
538 nu, z = self.args
539 try:
540 arg = z.as_leading_term(x)
541 except NotImplementedError:
542 return self
543 c, e = arg.as_coeff_exponent(x)
545 if e.is_positive:
546 return arg**nu/(2**nu*gamma(nu + 1))
547 elif e.is_negative:
548 cdir = 1 if cdir == 0 else cdir
549 sign = c*cdir**e
550 if not sign.is_negative:
551 # Refer Abramowitz and Stegun 1965, p. 377 for more information on
552 # asymptotic approximation of besseli function.
553 return exp(z)/sqrt(2*pi*z)
554 return self
556 return super(besseli, self)._eval_as_leading_term(x, logx, cdir)
558 def _eval_nseries(self, x, n, logx, cdir=0):
559 # Refer https://functions.wolfram.com/Bessel-TypeFunctions/BesselI/06/01/04/01/01/0003/
560 # for more information on nseries expansion of besseli function.
561 from sympy.series.order import Order
562 nu, z = self.args
564 # In case of powers less than 1, number of terms need to be computed
565 # separately to avoid repeated callings of _eval_nseries with wrong n
566 try:
567 _, exp = z.leadterm(x)
568 except (ValueError, NotImplementedError):
569 return self
571 if exp.is_positive:
572 newn = ceiling(n/exp)
573 o = Order(x**n, x)
574 r = (z/2)._eval_nseries(x, n, logx, cdir).removeO()
575 if r is S.Zero:
576 return o
577 t = (_mexpand(r**2) + o).removeO()
579 term = r**nu/gamma(nu + 1)
580 s = [term]
581 for k in range(1, (newn + 1)//2):
582 term *= t/(k*(nu + k))
583 term = (_mexpand(term) + o).removeO()
584 s.append(term)
585 return Add(*s) + o
587 return super(besseli, self)._eval_nseries(x, n, logx, cdir)
590class besselk(BesselBase):
591 r"""
592 Modified Bessel function of the second kind.
594 Explanation
595 ===========
597 The Bessel $K$ function of order $\nu$ is defined as
599 .. math ::
600 K_\nu(z) = \lim_{\mu \to \nu} \frac{\pi}{2}
601 \frac{I_{-\mu}(z) -I_\mu(z)}{\sin(\pi \mu)},
603 where $I_\mu(z)$ is the modified Bessel function of the first kind.
605 It is a solution of the modified Bessel equation, and linearly independent
606 from $Y_\nu$.
608 Examples
609 ========
611 >>> from sympy import besselk
612 >>> from sympy.abc import z, n
613 >>> besselk(n, z).diff(z)
614 -besselk(n - 1, z)/2 - besselk(n + 1, z)/2
616 See Also
617 ========
619 besselj, besseli, bessely
621 References
622 ==========
624 .. [1] https://functions.wolfram.com/Bessel-TypeFunctions/BesselK/
626 """
628 _a = S.One
629 _b = -S.One
631 @classmethod
632 def eval(cls, nu, z):
633 if z.is_zero:
634 if nu.is_zero:
635 return S.Infinity
636 elif re(nu).is_zero is False:
637 return S.ComplexInfinity
638 elif re(nu).is_zero:
639 return S.NaN
640 if z in (S.Infinity, I*S.Infinity, I*S.NegativeInfinity):
641 return S.Zero
643 if nu.is_integer:
644 if nu.could_extract_minus_sign():
645 return besselk(-nu, z)
647 def _eval_rewrite_as_besseli(self, nu, z, **kwargs):
648 if nu.is_integer is False:
649 return pi*csc(pi*nu)*(besseli(-nu, z) - besseli(nu, z))/2
651 def _eval_rewrite_as_besselj(self, nu, z, **kwargs):
652 ai = self._eval_rewrite_as_besseli(*self.args)
653 if ai:
654 return ai.rewrite(besselj)
656 def _eval_rewrite_as_bessely(self, nu, z, **kwargs):
657 aj = self._eval_rewrite_as_besselj(*self.args)
658 if aj:
659 return aj.rewrite(bessely)
661 def _eval_rewrite_as_yn(self, nu, z, **kwargs):
662 ay = self._eval_rewrite_as_bessely(*self.args)
663 if ay:
664 return ay.rewrite(yn)
666 def _eval_is_extended_real(self):
667 nu, z = self.args
668 if nu.is_integer and z.is_positive:
669 return True
671 def _eval_as_leading_term(self, x, logx=None, cdir=0):
672 nu, z = self.args
673 try:
674 arg = z.as_leading_term(x)
675 except NotImplementedError:
676 return self
677 _, e = arg.as_coeff_exponent(x)
679 if e.is_positive:
680 term_one = ((-1)**(nu -1)*log(z/2)*besseli(nu, z))
681 term_two = (z/2)**(-nu)*factorial(nu - 1)/2 if (nu).is_positive else S.Zero
682 term_three = (-1)**nu*(z/2)**nu/(2*factorial(nu))*(digamma(nu + 1) - S.EulerGamma)
683 arg = Add(*[term_one, term_two, term_three]).as_leading_term(x, logx=logx)
684 return arg
685 elif e.is_negative:
686 # Refer Abramowitz and Stegun 1965, p. 378 for more information on
687 # asymptotic approximation of besselk function.
688 return sqrt(pi)*exp(-z)/sqrt(2*z)
690 return super(besselk, self)._eval_as_leading_term(x, logx, cdir)
692 def _eval_nseries(self, x, n, logx, cdir=0):
693 # Refer https://functions.wolfram.com/Bessel-TypeFunctions/BesselK/06/01/04/01/02/0008/
694 # for more information on nseries expansion of besselk function.
695 from sympy.series.order import Order
696 nu, z = self.args
698 # In case of powers less than 1, number of terms need to be computed
699 # separately to avoid repeated callings of _eval_nseries with wrong n
700 try:
701 _, exp = z.leadterm(x)
702 except (ValueError, NotImplementedError):
703 return self
705 if exp.is_positive and nu.is_integer:
706 newn = ceiling(n/exp)
707 bn = besseli(nu, z)
708 a = ((-1)**(nu - 1)*log(z/2)*bn)._eval_nseries(x, n, logx, cdir)
710 b, c = [], []
711 o = Order(x**n, x)
712 r = (z/2)._eval_nseries(x, n, logx, cdir).removeO()
713 if r is S.Zero:
714 return o
715 t = (_mexpand(r**2) + o).removeO()
717 if nu > S.Zero:
718 term = r**(-nu)*factorial(nu - 1)/2
719 b.append(term)
720 for k in range(1, nu):
721 denom = (k - nu)*k
722 if denom == S.Zero:
723 term *= t/k
724 else:
725 term *= t/denom
726 term = (_mexpand(term) + o).removeO()
727 b.append(term)
729 p = r**nu*(-1)**nu/(2*factorial(nu))
730 term = p*(digamma(nu + 1) - S.EulerGamma)
731 c.append(term)
732 for k in range(1, (newn + 1)//2):
733 p *= t/(k*(k + nu))
734 p = (_mexpand(p) + o).removeO()
735 term = p*(digamma(k + nu + 1) + digamma(k + 1))
736 c.append(term)
737 return a + Add(*b) + Add(*c) # Order term comes from a
739 return super(besselk, self)._eval_nseries(x, n, logx, cdir)
742class hankel1(BesselBase):
743 r"""
744 Hankel function of the first kind.
746 Explanation
747 ===========
749 This function is defined as
751 .. math ::
752 H_\nu^{(1)} = J_\nu(z) + iY_\nu(z),
754 where $J_\nu(z)$ is the Bessel function of the first kind, and
755 $Y_\nu(z)$ is the Bessel function of the second kind.
757 It is a solution to Bessel's equation.
759 Examples
760 ========
762 >>> from sympy import hankel1
763 >>> from sympy.abc import z, n
764 >>> hankel1(n, z).diff(z)
765 hankel1(n - 1, z)/2 - hankel1(n + 1, z)/2
767 See Also
768 ========
770 hankel2, besselj, bessely
772 References
773 ==========
775 .. [1] https://functions.wolfram.com/Bessel-TypeFunctions/HankelH1/
777 """
779 _a = S.One
780 _b = S.One
782 def _eval_conjugate(self):
783 z = self.argument
784 if z.is_extended_negative is False:
785 return hankel2(self.order.conjugate(), z.conjugate())
788class hankel2(BesselBase):
789 r"""
790 Hankel function of the second kind.
792 Explanation
793 ===========
795 This function is defined as
797 .. math ::
798 H_\nu^{(2)} = J_\nu(z) - iY_\nu(z),
800 where $J_\nu(z)$ is the Bessel function of the first kind, and
801 $Y_\nu(z)$ is the Bessel function of the second kind.
803 It is a solution to Bessel's equation, and linearly independent from
804 $H_\nu^{(1)}$.
806 Examples
807 ========
809 >>> from sympy import hankel2
810 >>> from sympy.abc import z, n
811 >>> hankel2(n, z).diff(z)
812 hankel2(n - 1, z)/2 - hankel2(n + 1, z)/2
814 See Also
815 ========
817 hankel1, besselj, bessely
819 References
820 ==========
822 .. [1] https://functions.wolfram.com/Bessel-TypeFunctions/HankelH2/
824 """
826 _a = S.One
827 _b = S.One
829 def _eval_conjugate(self):
830 z = self.argument
831 if z.is_extended_negative is False:
832 return hankel1(self.order.conjugate(), z.conjugate())
835def assume_integer_order(fn):
836 @wraps(fn)
837 def g(self, nu, z):
838 if nu.is_integer:
839 return fn(self, nu, z)
840 return g
843class SphericalBesselBase(BesselBase):
844 """
845 Base class for spherical Bessel functions.
847 These are thin wrappers around ordinary Bessel functions,
848 since spherical Bessel functions differ from the ordinary
849 ones just by a slight change in order.
851 To use this class, define the ``_eval_evalf()`` and ``_expand()`` methods.
853 """
855 def _expand(self, **hints):
856 """ Expand self into a polynomial. Nu is guaranteed to be Integer. """
857 raise NotImplementedError('expansion')
859 def _eval_expand_func(self, **hints):
860 if self.order.is_Integer:
861 return self._expand(**hints)
862 return self
864 def fdiff(self, argindex=2):
865 if argindex != 2:
866 raise ArgumentIndexError(self, argindex)
867 return self.__class__(self.order - 1, self.argument) - \
868 self * (self.order + 1)/self.argument
871def _jn(n, z):
872 return (spherical_bessel_fn(n, z)*sin(z) +
873 S.NegativeOne**(n + 1)*spherical_bessel_fn(-n - 1, z)*cos(z))
876def _yn(n, z):
877 # (-1)**(n + 1) * _jn(-n - 1, z)
878 return (S.NegativeOne**(n + 1) * spherical_bessel_fn(-n - 1, z)*sin(z) -
879 spherical_bessel_fn(n, z)*cos(z))
882class jn(SphericalBesselBase):
883 r"""
884 Spherical Bessel function of the first kind.
886 Explanation
887 ===========
889 This function is a solution to the spherical Bessel equation
891 .. math ::
892 z^2 \frac{\mathrm{d}^2 w}{\mathrm{d}z^2}
893 + 2z \frac{\mathrm{d}w}{\mathrm{d}z} + (z^2 - \nu(\nu + 1)) w = 0.
895 It can be defined as
897 .. math ::
898 j_\nu(z) = \sqrt{\frac{\pi}{2z}} J_{\nu + \frac{1}{2}}(z),
900 where $J_\nu(z)$ is the Bessel function of the first kind.
902 The spherical Bessel functions of integral order are
903 calculated using the formula:
905 .. math:: j_n(z) = f_n(z) \sin{z} + (-1)^{n+1} f_{-n-1}(z) \cos{z},
907 where the coefficients $f_n(z)$ are available as
908 :func:`sympy.polys.orthopolys.spherical_bessel_fn`.
910 Examples
911 ========
913 >>> from sympy import Symbol, jn, sin, cos, expand_func, besselj, bessely
914 >>> z = Symbol("z")
915 >>> nu = Symbol("nu", integer=True)
916 >>> print(expand_func(jn(0, z)))
917 sin(z)/z
918 >>> expand_func(jn(1, z)) == sin(z)/z**2 - cos(z)/z
919 True
920 >>> expand_func(jn(3, z))
921 (-6/z**2 + 15/z**4)*sin(z) + (1/z - 15/z**3)*cos(z)
922 >>> jn(nu, z).rewrite(besselj)
923 sqrt(2)*sqrt(pi)*sqrt(1/z)*besselj(nu + 1/2, z)/2
924 >>> jn(nu, z).rewrite(bessely)
925 (-1)**nu*sqrt(2)*sqrt(pi)*sqrt(1/z)*bessely(-nu - 1/2, z)/2
926 >>> jn(2, 5.2+0.3j).evalf(20)
927 0.099419756723640344491 - 0.054525080242173562897*I
929 See Also
930 ========
932 besselj, bessely, besselk, yn
934 References
935 ==========
937 .. [1] https://dlmf.nist.gov/10.47
939 """
940 @classmethod
941 def eval(cls, nu, z):
942 if z.is_zero:
943 if nu.is_zero:
944 return S.One
945 elif nu.is_integer:
946 if nu.is_positive:
947 return S.Zero
948 else:
949 return S.ComplexInfinity
950 if z in (S.NegativeInfinity, S.Infinity):
951 return S.Zero
953 def _eval_rewrite_as_besselj(self, nu, z, **kwargs):
954 return sqrt(pi/(2*z)) * besselj(nu + S.Half, z)
956 def _eval_rewrite_as_bessely(self, nu, z, **kwargs):
957 return S.NegativeOne**nu * sqrt(pi/(2*z)) * bessely(-nu - S.Half, z)
959 def _eval_rewrite_as_yn(self, nu, z, **kwargs):
960 return S.NegativeOne**(nu) * yn(-nu - 1, z)
962 def _expand(self, **hints):
963 return _jn(self.order, self.argument)
965 def _eval_evalf(self, prec):
966 if self.order.is_Integer:
967 return self.rewrite(besselj)._eval_evalf(prec)
970class yn(SphericalBesselBase):
971 r"""
972 Spherical Bessel function of the second kind.
974 Explanation
975 ===========
977 This function is another solution to the spherical Bessel equation, and
978 linearly independent from $j_n$. It can be defined as
980 .. math ::
981 y_\nu(z) = \sqrt{\frac{\pi}{2z}} Y_{\nu + \frac{1}{2}}(z),
983 where $Y_\nu(z)$ is the Bessel function of the second kind.
985 For integral orders $n$, $y_n$ is calculated using the formula:
987 .. math:: y_n(z) = (-1)^{n+1} j_{-n-1}(z)
989 Examples
990 ========
992 >>> from sympy import Symbol, yn, sin, cos, expand_func, besselj, bessely
993 >>> z = Symbol("z")
994 >>> nu = Symbol("nu", integer=True)
995 >>> print(expand_func(yn(0, z)))
996 -cos(z)/z
997 >>> expand_func(yn(1, z)) == -cos(z)/z**2-sin(z)/z
998 True
999 >>> yn(nu, z).rewrite(besselj)
1000 (-1)**(nu + 1)*sqrt(2)*sqrt(pi)*sqrt(1/z)*besselj(-nu - 1/2, z)/2
1001 >>> yn(nu, z).rewrite(bessely)
1002 sqrt(2)*sqrt(pi)*sqrt(1/z)*bessely(nu + 1/2, z)/2
1003 >>> yn(2, 5.2+0.3j).evalf(20)
1004 0.18525034196069722536 + 0.014895573969924817587*I
1006 See Also
1007 ========
1009 besselj, bessely, besselk, jn
1011 References
1012 ==========
1014 .. [1] https://dlmf.nist.gov/10.47
1016 """
1017 @assume_integer_order
1018 def _eval_rewrite_as_besselj(self, nu, z, **kwargs):
1019 return S.NegativeOne**(nu+1) * sqrt(pi/(2*z)) * besselj(-nu - S.Half, z)
1021 @assume_integer_order
1022 def _eval_rewrite_as_bessely(self, nu, z, **kwargs):
1023 return sqrt(pi/(2*z)) * bessely(nu + S.Half, z)
1025 def _eval_rewrite_as_jn(self, nu, z, **kwargs):
1026 return S.NegativeOne**(nu + 1) * jn(-nu - 1, z)
1028 def _expand(self, **hints):
1029 return _yn(self.order, self.argument)
1031 def _eval_evalf(self, prec):
1032 if self.order.is_Integer:
1033 return self.rewrite(bessely)._eval_evalf(prec)
1036class SphericalHankelBase(SphericalBesselBase):
1038 @assume_integer_order
1039 def _eval_rewrite_as_besselj(self, nu, z, **kwargs):
1040 # jn +- I*yn
1041 # jn as beeselj: sqrt(pi/(2*z)) * besselj(nu + S.Half, z)
1042 # yn as besselj: (-1)**(nu+1) * sqrt(pi/(2*z)) * besselj(-nu - S.Half, z)
1043 hks = self._hankel_kind_sign
1044 return sqrt(pi/(2*z))*(besselj(nu + S.Half, z) +
1045 hks*I*S.NegativeOne**(nu+1)*besselj(-nu - S.Half, z))
1047 @assume_integer_order
1048 def _eval_rewrite_as_bessely(self, nu, z, **kwargs):
1049 # jn +- I*yn
1050 # jn as bessely: (-1)**nu * sqrt(pi/(2*z)) * bessely(-nu - S.Half, z)
1051 # yn as bessely: sqrt(pi/(2*z)) * bessely(nu + S.Half, z)
1052 hks = self._hankel_kind_sign
1053 return sqrt(pi/(2*z))*(S.NegativeOne**nu*bessely(-nu - S.Half, z) +
1054 hks*I*bessely(nu + S.Half, z))
1056 def _eval_rewrite_as_yn(self, nu, z, **kwargs):
1057 hks = self._hankel_kind_sign
1058 return jn(nu, z).rewrite(yn) + hks*I*yn(nu, z)
1060 def _eval_rewrite_as_jn(self, nu, z, **kwargs):
1061 hks = self._hankel_kind_sign
1062 return jn(nu, z) + hks*I*yn(nu, z).rewrite(jn)
1064 def _eval_expand_func(self, **hints):
1065 if self.order.is_Integer:
1066 return self._expand(**hints)
1067 else:
1068 nu = self.order
1069 z = self.argument
1070 hks = self._hankel_kind_sign
1071 return jn(nu, z) + hks*I*yn(nu, z)
1073 def _expand(self, **hints):
1074 n = self.order
1075 z = self.argument
1076 hks = self._hankel_kind_sign
1078 # fully expanded version
1079 # return ((fn(n, z) * sin(z) +
1080 # (-1)**(n + 1) * fn(-n - 1, z) * cos(z)) + # jn
1081 # (hks * I * (-1)**(n + 1) *
1082 # (fn(-n - 1, z) * hk * I * sin(z) +
1083 # (-1)**(-n) * fn(n, z) * I * cos(z))) # +-I*yn
1084 # )
1086 return (_jn(n, z) + hks*I*_yn(n, z)).expand()
1088 def _eval_evalf(self, prec):
1089 if self.order.is_Integer:
1090 return self.rewrite(besselj)._eval_evalf(prec)
1093class hn1(SphericalHankelBase):
1094 r"""
1095 Spherical Hankel function of the first kind.
1097 Explanation
1098 ===========
1100 This function is defined as
1102 .. math:: h_\nu^(1)(z) = j_\nu(z) + i y_\nu(z),
1104 where $j_\nu(z)$ and $y_\nu(z)$ are the spherical
1105 Bessel function of the first and second kinds.
1107 For integral orders $n$, $h_n^(1)$ is calculated using the formula:
1109 .. math:: h_n^(1)(z) = j_{n}(z) + i (-1)^{n+1} j_{-n-1}(z)
1111 Examples
1112 ========
1114 >>> from sympy import Symbol, hn1, hankel1, expand_func, yn, jn
1115 >>> z = Symbol("z")
1116 >>> nu = Symbol("nu", integer=True)
1117 >>> print(expand_func(hn1(nu, z)))
1118 jn(nu, z) + I*yn(nu, z)
1119 >>> print(expand_func(hn1(0, z)))
1120 sin(z)/z - I*cos(z)/z
1121 >>> print(expand_func(hn1(1, z)))
1122 -I*sin(z)/z - cos(z)/z + sin(z)/z**2 - I*cos(z)/z**2
1123 >>> hn1(nu, z).rewrite(jn)
1124 (-1)**(nu + 1)*I*jn(-nu - 1, z) + jn(nu, z)
1125 >>> hn1(nu, z).rewrite(yn)
1126 (-1)**nu*yn(-nu - 1, z) + I*yn(nu, z)
1127 >>> hn1(nu, z).rewrite(hankel1)
1128 sqrt(2)*sqrt(pi)*sqrt(1/z)*hankel1(nu, z)/2
1130 See Also
1131 ========
1133 hn2, jn, yn, hankel1, hankel2
1135 References
1136 ==========
1138 .. [1] https://dlmf.nist.gov/10.47
1140 """
1142 _hankel_kind_sign = S.One
1144 @assume_integer_order
1145 def _eval_rewrite_as_hankel1(self, nu, z, **kwargs):
1146 return sqrt(pi/(2*z))*hankel1(nu, z)
1149class hn2(SphericalHankelBase):
1150 r"""
1151 Spherical Hankel function of the second kind.
1153 Explanation
1154 ===========
1156 This function is defined as
1158 .. math:: h_\nu^(2)(z) = j_\nu(z) - i y_\nu(z),
1160 where $j_\nu(z)$ and $y_\nu(z)$ are the spherical
1161 Bessel function of the first and second kinds.
1163 For integral orders $n$, $h_n^(2)$ is calculated using the formula:
1165 .. math:: h_n^(2)(z) = j_{n} - i (-1)^{n+1} j_{-n-1}(z)
1167 Examples
1168 ========
1170 >>> from sympy import Symbol, hn2, hankel2, expand_func, jn, yn
1171 >>> z = Symbol("z")
1172 >>> nu = Symbol("nu", integer=True)
1173 >>> print(expand_func(hn2(nu, z)))
1174 jn(nu, z) - I*yn(nu, z)
1175 >>> print(expand_func(hn2(0, z)))
1176 sin(z)/z + I*cos(z)/z
1177 >>> print(expand_func(hn2(1, z)))
1178 I*sin(z)/z - cos(z)/z + sin(z)/z**2 + I*cos(z)/z**2
1179 >>> hn2(nu, z).rewrite(hankel2)
1180 sqrt(2)*sqrt(pi)*sqrt(1/z)*hankel2(nu, z)/2
1181 >>> hn2(nu, z).rewrite(jn)
1182 -(-1)**(nu + 1)*I*jn(-nu - 1, z) + jn(nu, z)
1183 >>> hn2(nu, z).rewrite(yn)
1184 (-1)**nu*yn(-nu - 1, z) - I*yn(nu, z)
1186 See Also
1187 ========
1189 hn1, jn, yn, hankel1, hankel2
1191 References
1192 ==========
1194 .. [1] https://dlmf.nist.gov/10.47
1196 """
1198 _hankel_kind_sign = -S.One
1200 @assume_integer_order
1201 def _eval_rewrite_as_hankel2(self, nu, z, **kwargs):
1202 return sqrt(pi/(2*z))*hankel2(nu, z)
1205def jn_zeros(n, k, method="sympy", dps=15):
1206 """
1207 Zeros of the spherical Bessel function of the first kind.
1209 Explanation
1210 ===========
1212 This returns an array of zeros of $jn$ up to the $k$-th zero.
1214 * method = "sympy": uses `mpmath.besseljzero
1215 <https://mpmath.org/doc/current/functions/bessel.html#mpmath.besseljzero>`_
1216 * method = "scipy": uses the
1217 `SciPy's sph_jn <https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.jn_zeros.html>`_
1218 and
1219 `newton <https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.newton.html>`_
1220 to find all
1221 roots, which is faster than computing the zeros using a general
1222 numerical solver, but it requires SciPy and only works with low
1223 precision floating point numbers. (The function used with
1224 method="sympy" is a recent addition to mpmath; before that a general
1225 solver was used.)
1227 Examples
1228 ========
1230 >>> from sympy import jn_zeros
1231 >>> jn_zeros(2, 4, dps=5)
1232 [5.7635, 9.095, 12.323, 15.515]
1234 See Also
1235 ========
1237 jn, yn, besselj, besselk, bessely
1239 Parameters
1240 ==========
1242 n : integer
1243 order of Bessel function
1245 k : integer
1246 number of zeros to return
1249 """
1250 from math import pi as math_pi
1252 if method == "sympy":
1253 from mpmath import besseljzero
1254 from mpmath.libmp.libmpf import dps_to_prec
1255 prec = dps_to_prec(dps)
1256 return [Expr._from_mpmath(besseljzero(S(n + 0.5)._to_mpmath(prec),
1257 int(l)), prec)
1258 for l in range(1, k + 1)]
1259 elif method == "scipy":
1260 from scipy.optimize import newton
1261 try:
1262 from scipy.special import spherical_jn
1263 f = lambda x: spherical_jn(n, x)
1264 except ImportError:
1265 from scipy.special import sph_jn
1266 f = lambda x: sph_jn(n, x)[0][-1]
1267 else:
1268 raise NotImplementedError("Unknown method.")
1270 def solver(f, x):
1271 if method == "scipy":
1272 root = newton(f, x)
1273 else:
1274 raise NotImplementedError("Unknown method.")
1275 return root
1277 # we need to approximate the position of the first root:
1278 root = n + math_pi
1279 # determine the first root exactly:
1280 root = solver(f, root)
1281 roots = [root]
1282 for i in range(k - 1):
1283 # estimate the position of the next root using the last root + pi:
1284 root = solver(f, root + math_pi)
1285 roots.append(root)
1286 return roots
1289class AiryBase(Function):
1290 """
1291 Abstract base class for Airy functions.
1293 This class is meant to reduce code duplication.
1295 """
1297 def _eval_conjugate(self):
1298 return self.func(self.args[0].conjugate())
1300 def _eval_is_extended_real(self):
1301 return self.args[0].is_extended_real
1303 def as_real_imag(self, deep=True, **hints):
1304 z = self.args[0]
1305 zc = z.conjugate()
1306 f = self.func
1307 u = (f(z)+f(zc))/2
1308 v = I*(f(zc)-f(z))/2
1309 return u, v
1311 def _eval_expand_complex(self, deep=True, **hints):
1312 re_part, im_part = self.as_real_imag(deep=deep, **hints)
1313 return re_part + im_part*I
1316class airyai(AiryBase):
1317 r"""
1318 The Airy function $\operatorname{Ai}$ of the first kind.
1320 Explanation
1321 ===========
1323 The Airy function $\operatorname{Ai}(z)$ is defined to be the function
1324 satisfying Airy's differential equation
1326 .. math::
1327 \frac{\mathrm{d}^2 w(z)}{\mathrm{d}z^2} - z w(z) = 0.
1329 Equivalently, for real $z$
1331 .. math::
1332 \operatorname{Ai}(z) := \frac{1}{\pi}
1333 \int_0^\infty \cos\left(\frac{t^3}{3} + z t\right) \mathrm{d}t.
1335 Examples
1336 ========
1338 Create an Airy function object:
1340 >>> from sympy import airyai
1341 >>> from sympy.abc import z
1343 >>> airyai(z)
1344 airyai(z)
1346 Several special values are known:
1348 >>> airyai(0)
1349 3**(1/3)/(3*gamma(2/3))
1350 >>> from sympy import oo
1351 >>> airyai(oo)
1352 0
1353 >>> airyai(-oo)
1354 0
1356 The Airy function obeys the mirror symmetry:
1358 >>> from sympy import conjugate
1359 >>> conjugate(airyai(z))
1360 airyai(conjugate(z))
1362 Differentiation with respect to $z$ is supported:
1364 >>> from sympy import diff
1365 >>> diff(airyai(z), z)
1366 airyaiprime(z)
1367 >>> diff(airyai(z), z, 2)
1368 z*airyai(z)
1370 Series expansion is also supported:
1372 >>> from sympy import series
1373 >>> series(airyai(z), z, 0, 3)
1374 3**(5/6)*gamma(1/3)/(6*pi) - 3**(1/6)*z*gamma(2/3)/(2*pi) + O(z**3)
1376 We can numerically evaluate the Airy function to arbitrary precision
1377 on the whole complex plane:
1379 >>> airyai(-2).evalf(50)
1380 0.22740742820168557599192443603787379946077222541710
1382 Rewrite $\operatorname{Ai}(z)$ in terms of hypergeometric functions:
1384 >>> from sympy import hyper
1385 >>> airyai(z).rewrite(hyper)
1386 -3**(2/3)*z*hyper((), (4/3,), z**3/9)/(3*gamma(1/3)) + 3**(1/3)*hyper((), (2/3,), z**3/9)/(3*gamma(2/3))
1388 See Also
1389 ========
1391 airybi: Airy function of the second kind.
1392 airyaiprime: Derivative of the Airy function of the first kind.
1393 airybiprime: Derivative of the Airy function of the second kind.
1395 References
1396 ==========
1398 .. [1] https://en.wikipedia.org/wiki/Airy_function
1399 .. [2] https://dlmf.nist.gov/9
1400 .. [3] https://encyclopediaofmath.org/wiki/Airy_functions
1401 .. [4] https://mathworld.wolfram.com/AiryFunctions.html
1403 """
1405 nargs = 1
1406 unbranched = True
1408 @classmethod
1409 def eval(cls, arg):
1410 if arg.is_Number:
1411 if arg is S.NaN:
1412 return S.NaN
1413 elif arg is S.Infinity:
1414 return S.Zero
1415 elif arg is S.NegativeInfinity:
1416 return S.Zero
1417 elif arg.is_zero:
1418 return S.One / (3**Rational(2, 3) * gamma(Rational(2, 3)))
1419 if arg.is_zero:
1420 return S.One / (3**Rational(2, 3) * gamma(Rational(2, 3)))
1422 def fdiff(self, argindex=1):
1423 if argindex == 1:
1424 return airyaiprime(self.args[0])
1425 else:
1426 raise ArgumentIndexError(self, argindex)
1428 @staticmethod
1429 @cacheit
1430 def taylor_term(n, x, *previous_terms):
1431 if n < 0:
1432 return S.Zero
1433 else:
1434 x = sympify(x)
1435 if len(previous_terms) > 1:
1436 p = previous_terms[-1]
1437 return ((cbrt(3)*x)**(-n)*(cbrt(3)*x)**(n + 1)*sin(pi*(n*Rational(2, 3) + Rational(4, 3)))*factorial(n) *
1438 gamma(n/3 + Rational(2, 3))/(sin(pi*(n*Rational(2, 3) + Rational(2, 3)))*factorial(n + 1)*gamma(n/3 + Rational(1, 3))) * p)
1439 else:
1440 return (S.One/(3**Rational(2, 3)*pi) * gamma((n+S.One)/S(3)) * sin(Rational(2, 3)*pi*(n+S.One)) /
1441 factorial(n) * (cbrt(3)*x)**n)
1443 def _eval_rewrite_as_besselj(self, z, **kwargs):
1444 ot = Rational(1, 3)
1445 tt = Rational(2, 3)
1446 a = Pow(-z, Rational(3, 2))
1447 if re(z).is_negative:
1448 return ot*sqrt(-z) * (besselj(-ot, tt*a) + besselj(ot, tt*a))
1450 def _eval_rewrite_as_besseli(self, z, **kwargs):
1451 ot = Rational(1, 3)
1452 tt = Rational(2, 3)
1453 a = Pow(z, Rational(3, 2))
1454 if re(z).is_positive:
1455 return ot*sqrt(z) * (besseli(-ot, tt*a) - besseli(ot, tt*a))
1456 else:
1457 return ot*(Pow(a, ot)*besseli(-ot, tt*a) - z*Pow(a, -ot)*besseli(ot, tt*a))
1459 def _eval_rewrite_as_hyper(self, z, **kwargs):
1460 pf1 = S.One / (3**Rational(2, 3)*gamma(Rational(2, 3)))
1461 pf2 = z / (root(3, 3)*gamma(Rational(1, 3)))
1462 return pf1 * hyper([], [Rational(2, 3)], z**3/9) - pf2 * hyper([], [Rational(4, 3)], z**3/9)
1464 def _eval_expand_func(self, **hints):
1465 arg = self.args[0]
1466 symbs = arg.free_symbols
1468 if len(symbs) == 1:
1469 z = symbs.pop()
1470 c = Wild("c", exclude=[z])
1471 d = Wild("d", exclude=[z])
1472 m = Wild("m", exclude=[z])
1473 n = Wild("n", exclude=[z])
1474 M = arg.match(c*(d*z**n)**m)
1475 if M is not None:
1476 m = M[m]
1477 # The transformation is given by 03.05.16.0001.01
1478 # https://functions.wolfram.com/Bessel-TypeFunctions/AiryAi/16/01/01/0001/
1479 if (3*m).is_integer:
1480 c = M[c]
1481 d = M[d]
1482 n = M[n]
1483 pf = (d * z**n)**m / (d**m * z**(m*n))
1484 newarg = c * d**m * z**(m*n)
1485 return S.Half * ((pf + S.One)*airyai(newarg) - (pf - S.One)/sqrt(3)*airybi(newarg))
1488class airybi(AiryBase):
1489 r"""
1490 The Airy function $\operatorname{Bi}$ of the second kind.
1492 Explanation
1493 ===========
1495 The Airy function $\operatorname{Bi}(z)$ is defined to be the function
1496 satisfying Airy's differential equation
1498 .. math::
1499 \frac{\mathrm{d}^2 w(z)}{\mathrm{d}z^2} - z w(z) = 0.
1501 Equivalently, for real $z$
1503 .. math::
1504 \operatorname{Bi}(z) := \frac{1}{\pi}
1505 \int_0^\infty
1506 \exp\left(-\frac{t^3}{3} + z t\right)
1507 + \sin\left(\frac{t^3}{3} + z t\right) \mathrm{d}t.
1509 Examples
1510 ========
1512 Create an Airy function object:
1514 >>> from sympy import airybi
1515 >>> from sympy.abc import z
1517 >>> airybi(z)
1518 airybi(z)
1520 Several special values are known:
1522 >>> airybi(0)
1523 3**(5/6)/(3*gamma(2/3))
1524 >>> from sympy import oo
1525 >>> airybi(oo)
1526 oo
1527 >>> airybi(-oo)
1528 0
1530 The Airy function obeys the mirror symmetry:
1532 >>> from sympy import conjugate
1533 >>> conjugate(airybi(z))
1534 airybi(conjugate(z))
1536 Differentiation with respect to $z$ is supported:
1538 >>> from sympy import diff
1539 >>> diff(airybi(z), z)
1540 airybiprime(z)
1541 >>> diff(airybi(z), z, 2)
1542 z*airybi(z)
1544 Series expansion is also supported:
1546 >>> from sympy import series
1547 >>> series(airybi(z), z, 0, 3)
1548 3**(1/3)*gamma(1/3)/(2*pi) + 3**(2/3)*z*gamma(2/3)/(2*pi) + O(z**3)
1550 We can numerically evaluate the Airy function to arbitrary precision
1551 on the whole complex plane:
1553 >>> airybi(-2).evalf(50)
1554 -0.41230258795639848808323405461146104203453483447240
1556 Rewrite $\operatorname{Bi}(z)$ in terms of hypergeometric functions:
1558 >>> from sympy import hyper
1559 >>> airybi(z).rewrite(hyper)
1560 3**(1/6)*z*hyper((), (4/3,), z**3/9)/gamma(1/3) + 3**(5/6)*hyper((), (2/3,), z**3/9)/(3*gamma(2/3))
1562 See Also
1563 ========
1565 airyai: Airy function of the first kind.
1566 airyaiprime: Derivative of the Airy function of the first kind.
1567 airybiprime: Derivative of the Airy function of the second kind.
1569 References
1570 ==========
1572 .. [1] https://en.wikipedia.org/wiki/Airy_function
1573 .. [2] https://dlmf.nist.gov/9
1574 .. [3] https://encyclopediaofmath.org/wiki/Airy_functions
1575 .. [4] https://mathworld.wolfram.com/AiryFunctions.html
1577 """
1579 nargs = 1
1580 unbranched = True
1582 @classmethod
1583 def eval(cls, arg):
1584 if arg.is_Number:
1585 if arg is S.NaN:
1586 return S.NaN
1587 elif arg is S.Infinity:
1588 return S.Infinity
1589 elif arg is S.NegativeInfinity:
1590 return S.Zero
1591 elif arg.is_zero:
1592 return S.One / (3**Rational(1, 6) * gamma(Rational(2, 3)))
1594 if arg.is_zero:
1595 return S.One / (3**Rational(1, 6) * gamma(Rational(2, 3)))
1597 def fdiff(self, argindex=1):
1598 if argindex == 1:
1599 return airybiprime(self.args[0])
1600 else:
1601 raise ArgumentIndexError(self, argindex)
1603 @staticmethod
1604 @cacheit
1605 def taylor_term(n, x, *previous_terms):
1606 if n < 0:
1607 return S.Zero
1608 else:
1609 x = sympify(x)
1610 if len(previous_terms) > 1:
1611 p = previous_terms[-1]
1612 return (cbrt(3)*x * Abs(sin(Rational(2, 3)*pi*(n + S.One))) * factorial((n - S.One)/S(3)) /
1613 ((n + S.One) * Abs(cos(Rational(2, 3)*pi*(n + S.Half))) * factorial((n - 2)/S(3))) * p)
1614 else:
1615 return (S.One/(root(3, 6)*pi) * gamma((n + S.One)/S(3)) * Abs(sin(Rational(2, 3)*pi*(n + S.One))) /
1616 factorial(n) * (cbrt(3)*x)**n)
1618 def _eval_rewrite_as_besselj(self, z, **kwargs):
1619 ot = Rational(1, 3)
1620 tt = Rational(2, 3)
1621 a = Pow(-z, Rational(3, 2))
1622 if re(z).is_negative:
1623 return sqrt(-z/3) * (besselj(-ot, tt*a) - besselj(ot, tt*a))
1625 def _eval_rewrite_as_besseli(self, z, **kwargs):
1626 ot = Rational(1, 3)
1627 tt = Rational(2, 3)
1628 a = Pow(z, Rational(3, 2))
1629 if re(z).is_positive:
1630 return sqrt(z)/sqrt(3) * (besseli(-ot, tt*a) + besseli(ot, tt*a))
1631 else:
1632 b = Pow(a, ot)
1633 c = Pow(a, -ot)
1634 return sqrt(ot)*(b*besseli(-ot, tt*a) + z*c*besseli(ot, tt*a))
1636 def _eval_rewrite_as_hyper(self, z, **kwargs):
1637 pf1 = S.One / (root(3, 6)*gamma(Rational(2, 3)))
1638 pf2 = z*root(3, 6) / gamma(Rational(1, 3))
1639 return pf1 * hyper([], [Rational(2, 3)], z**3/9) + pf2 * hyper([], [Rational(4, 3)], z**3/9)
1641 def _eval_expand_func(self, **hints):
1642 arg = self.args[0]
1643 symbs = arg.free_symbols
1645 if len(symbs) == 1:
1646 z = symbs.pop()
1647 c = Wild("c", exclude=[z])
1648 d = Wild("d", exclude=[z])
1649 m = Wild("m", exclude=[z])
1650 n = Wild("n", exclude=[z])
1651 M = arg.match(c*(d*z**n)**m)
1652 if M is not None:
1653 m = M[m]
1654 # The transformation is given by 03.06.16.0001.01
1655 # https://functions.wolfram.com/Bessel-TypeFunctions/AiryBi/16/01/01/0001/
1656 if (3*m).is_integer:
1657 c = M[c]
1658 d = M[d]
1659 n = M[n]
1660 pf = (d * z**n)**m / (d**m * z**(m*n))
1661 newarg = c * d**m * z**(m*n)
1662 return S.Half * (sqrt(3)*(S.One - pf)*airyai(newarg) + (S.One + pf)*airybi(newarg))
1665class airyaiprime(AiryBase):
1666 r"""
1667 The derivative $\operatorname{Ai}^\prime$ of the Airy function of the first
1668 kind.
1670 Explanation
1671 ===========
1673 The Airy function $\operatorname{Ai}^\prime(z)$ is defined to be the
1674 function
1676 .. math::
1677 \operatorname{Ai}^\prime(z) := \frac{\mathrm{d} \operatorname{Ai}(z)}{\mathrm{d} z}.
1679 Examples
1680 ========
1682 Create an Airy function object:
1684 >>> from sympy import airyaiprime
1685 >>> from sympy.abc import z
1687 >>> airyaiprime(z)
1688 airyaiprime(z)
1690 Several special values are known:
1692 >>> airyaiprime(0)
1693 -3**(2/3)/(3*gamma(1/3))
1694 >>> from sympy import oo
1695 >>> airyaiprime(oo)
1696 0
1698 The Airy function obeys the mirror symmetry:
1700 >>> from sympy import conjugate
1701 >>> conjugate(airyaiprime(z))
1702 airyaiprime(conjugate(z))
1704 Differentiation with respect to $z$ is supported:
1706 >>> from sympy import diff
1707 >>> diff(airyaiprime(z), z)
1708 z*airyai(z)
1709 >>> diff(airyaiprime(z), z, 2)
1710 z*airyaiprime(z) + airyai(z)
1712 Series expansion is also supported:
1714 >>> from sympy import series
1715 >>> series(airyaiprime(z), z, 0, 3)
1716 -3**(2/3)/(3*gamma(1/3)) + 3**(1/3)*z**2/(6*gamma(2/3)) + O(z**3)
1718 We can numerically evaluate the Airy function to arbitrary precision
1719 on the whole complex plane:
1721 >>> airyaiprime(-2).evalf(50)
1722 0.61825902074169104140626429133247528291577794512415
1724 Rewrite $\operatorname{Ai}^\prime(z)$ in terms of hypergeometric functions:
1726 >>> from sympy import hyper
1727 >>> airyaiprime(z).rewrite(hyper)
1728 3**(1/3)*z**2*hyper((), (5/3,), z**3/9)/(6*gamma(2/3)) - 3**(2/3)*hyper((), (1/3,), z**3/9)/(3*gamma(1/3))
1730 See Also
1731 ========
1733 airyai: Airy function of the first kind.
1734 airybi: Airy function of the second kind.
1735 airybiprime: Derivative of the Airy function of the second kind.
1737 References
1738 ==========
1740 .. [1] https://en.wikipedia.org/wiki/Airy_function
1741 .. [2] https://dlmf.nist.gov/9
1742 .. [3] https://encyclopediaofmath.org/wiki/Airy_functions
1743 .. [4] https://mathworld.wolfram.com/AiryFunctions.html
1745 """
1747 nargs = 1
1748 unbranched = True
1750 @classmethod
1751 def eval(cls, arg):
1752 if arg.is_Number:
1753 if arg is S.NaN:
1754 return S.NaN
1755 elif arg is S.Infinity:
1756 return S.Zero
1758 if arg.is_zero:
1759 return S.NegativeOne / (3**Rational(1, 3) * gamma(Rational(1, 3)))
1761 def fdiff(self, argindex=1):
1762 if argindex == 1:
1763 return self.args[0]*airyai(self.args[0])
1764 else:
1765 raise ArgumentIndexError(self, argindex)
1767 def _eval_evalf(self, prec):
1768 z = self.args[0]._to_mpmath(prec)
1769 with workprec(prec):
1770 res = mp.airyai(z, derivative=1)
1771 return Expr._from_mpmath(res, prec)
1773 def _eval_rewrite_as_besselj(self, z, **kwargs):
1774 tt = Rational(2, 3)
1775 a = Pow(-z, Rational(3, 2))
1776 if re(z).is_negative:
1777 return z/3 * (besselj(-tt, tt*a) - besselj(tt, tt*a))
1779 def _eval_rewrite_as_besseli(self, z, **kwargs):
1780 ot = Rational(1, 3)
1781 tt = Rational(2, 3)
1782 a = tt * Pow(z, Rational(3, 2))
1783 if re(z).is_positive:
1784 return z/3 * (besseli(tt, a) - besseli(-tt, a))
1785 else:
1786 a = Pow(z, Rational(3, 2))
1787 b = Pow(a, tt)
1788 c = Pow(a, -tt)
1789 return ot * (z**2*c*besseli(tt, tt*a) - b*besseli(-ot, tt*a))
1791 def _eval_rewrite_as_hyper(self, z, **kwargs):
1792 pf1 = z**2 / (2*3**Rational(2, 3)*gamma(Rational(2, 3)))
1793 pf2 = 1 / (root(3, 3)*gamma(Rational(1, 3)))
1794 return pf1 * hyper([], [Rational(5, 3)], z**3/9) - pf2 * hyper([], [Rational(1, 3)], z**3/9)
1796 def _eval_expand_func(self, **hints):
1797 arg = self.args[0]
1798 symbs = arg.free_symbols
1800 if len(symbs) == 1:
1801 z = symbs.pop()
1802 c = Wild("c", exclude=[z])
1803 d = Wild("d", exclude=[z])
1804 m = Wild("m", exclude=[z])
1805 n = Wild("n", exclude=[z])
1806 M = arg.match(c*(d*z**n)**m)
1807 if M is not None:
1808 m = M[m]
1809 # The transformation is in principle
1810 # given by 03.07.16.0001.01 but note
1811 # that there is an error in this formula.
1812 # https://functions.wolfram.com/Bessel-TypeFunctions/AiryAiPrime/16/01/01/0001/
1813 if (3*m).is_integer:
1814 c = M[c]
1815 d = M[d]
1816 n = M[n]
1817 pf = (d**m * z**(n*m)) / (d * z**n)**m
1818 newarg = c * d**m * z**(n*m)
1819 return S.Half * ((pf + S.One)*airyaiprime(newarg) + (pf - S.One)/sqrt(3)*airybiprime(newarg))
1822class airybiprime(AiryBase):
1823 r"""
1824 The derivative $\operatorname{Bi}^\prime$ of the Airy function of the first
1825 kind.
1827 Explanation
1828 ===========
1830 The Airy function $\operatorname{Bi}^\prime(z)$ is defined to be the
1831 function
1833 .. math::
1834 \operatorname{Bi}^\prime(z) := \frac{\mathrm{d} \operatorname{Bi}(z)}{\mathrm{d} z}.
1836 Examples
1837 ========
1839 Create an Airy function object:
1841 >>> from sympy import airybiprime
1842 >>> from sympy.abc import z
1844 >>> airybiprime(z)
1845 airybiprime(z)
1847 Several special values are known:
1849 >>> airybiprime(0)
1850 3**(1/6)/gamma(1/3)
1851 >>> from sympy import oo
1852 >>> airybiprime(oo)
1853 oo
1854 >>> airybiprime(-oo)
1855 0
1857 The Airy function obeys the mirror symmetry:
1859 >>> from sympy import conjugate
1860 >>> conjugate(airybiprime(z))
1861 airybiprime(conjugate(z))
1863 Differentiation with respect to $z$ is supported:
1865 >>> from sympy import diff
1866 >>> diff(airybiprime(z), z)
1867 z*airybi(z)
1868 >>> diff(airybiprime(z), z, 2)
1869 z*airybiprime(z) + airybi(z)
1871 Series expansion is also supported:
1873 >>> from sympy import series
1874 >>> series(airybiprime(z), z, 0, 3)
1875 3**(1/6)/gamma(1/3) + 3**(5/6)*z**2/(6*gamma(2/3)) + O(z**3)
1877 We can numerically evaluate the Airy function to arbitrary precision
1878 on the whole complex plane:
1880 >>> airybiprime(-2).evalf(50)
1881 0.27879516692116952268509756941098324140300059345163
1883 Rewrite $\operatorname{Bi}^\prime(z)$ in terms of hypergeometric functions:
1885 >>> from sympy import hyper
1886 >>> airybiprime(z).rewrite(hyper)
1887 3**(5/6)*z**2*hyper((), (5/3,), z**3/9)/(6*gamma(2/3)) + 3**(1/6)*hyper((), (1/3,), z**3/9)/gamma(1/3)
1889 See Also
1890 ========
1892 airyai: Airy function of the first kind.
1893 airybi: Airy function of the second kind.
1894 airyaiprime: Derivative of the Airy function of the first kind.
1896 References
1897 ==========
1899 .. [1] https://en.wikipedia.org/wiki/Airy_function
1900 .. [2] https://dlmf.nist.gov/9
1901 .. [3] https://encyclopediaofmath.org/wiki/Airy_functions
1902 .. [4] https://mathworld.wolfram.com/AiryFunctions.html
1904 """
1906 nargs = 1
1907 unbranched = True
1909 @classmethod
1910 def eval(cls, arg):
1911 if arg.is_Number:
1912 if arg is S.NaN:
1913 return S.NaN
1914 elif arg is S.Infinity:
1915 return S.Infinity
1916 elif arg is S.NegativeInfinity:
1917 return S.Zero
1918 elif arg.is_zero:
1919 return 3**Rational(1, 6) / gamma(Rational(1, 3))
1921 if arg.is_zero:
1922 return 3**Rational(1, 6) / gamma(Rational(1, 3))
1925 def fdiff(self, argindex=1):
1926 if argindex == 1:
1927 return self.args[0]*airybi(self.args[0])
1928 else:
1929 raise ArgumentIndexError(self, argindex)
1931 def _eval_evalf(self, prec):
1932 z = self.args[0]._to_mpmath(prec)
1933 with workprec(prec):
1934 res = mp.airybi(z, derivative=1)
1935 return Expr._from_mpmath(res, prec)
1937 def _eval_rewrite_as_besselj(self, z, **kwargs):
1938 tt = Rational(2, 3)
1939 a = tt * Pow(-z, Rational(3, 2))
1940 if re(z).is_negative:
1941 return -z/sqrt(3) * (besselj(-tt, a) + besselj(tt, a))
1943 def _eval_rewrite_as_besseli(self, z, **kwargs):
1944 ot = Rational(1, 3)
1945 tt = Rational(2, 3)
1946 a = tt * Pow(z, Rational(3, 2))
1947 if re(z).is_positive:
1948 return z/sqrt(3) * (besseli(-tt, a) + besseli(tt, a))
1949 else:
1950 a = Pow(z, Rational(3, 2))
1951 b = Pow(a, tt)
1952 c = Pow(a, -tt)
1953 return sqrt(ot) * (b*besseli(-tt, tt*a) + z**2*c*besseli(tt, tt*a))
1955 def _eval_rewrite_as_hyper(self, z, **kwargs):
1956 pf1 = z**2 / (2*root(3, 6)*gamma(Rational(2, 3)))
1957 pf2 = root(3, 6) / gamma(Rational(1, 3))
1958 return pf1 * hyper([], [Rational(5, 3)], z**3/9) + pf2 * hyper([], [Rational(1, 3)], z**3/9)
1960 def _eval_expand_func(self, **hints):
1961 arg = self.args[0]
1962 symbs = arg.free_symbols
1964 if len(symbs) == 1:
1965 z = symbs.pop()
1966 c = Wild("c", exclude=[z])
1967 d = Wild("d", exclude=[z])
1968 m = Wild("m", exclude=[z])
1969 n = Wild("n", exclude=[z])
1970 M = arg.match(c*(d*z**n)**m)
1971 if M is not None:
1972 m = M[m]
1973 # The transformation is in principle
1974 # given by 03.08.16.0001.01 but note
1975 # that there is an error in this formula.
1976 # https://functions.wolfram.com/Bessel-TypeFunctions/AiryBiPrime/16/01/01/0001/
1977 if (3*m).is_integer:
1978 c = M[c]
1979 d = M[d]
1980 n = M[n]
1981 pf = (d**m * z**(n*m)) / (d * z**n)**m
1982 newarg = c * d**m * z**(n*m)
1983 return S.Half * (sqrt(3)*(pf - S.One)*airyaiprime(newarg) + (pf + S.One)*airybiprime(newarg))
1986class marcumq(Function):
1987 r"""
1988 The Marcum Q-function.
1990 Explanation
1991 ===========
1993 The Marcum Q-function is defined by the meromorphic continuation of
1995 .. math::
1996 Q_m(a, b) = a^{- m + 1} \int_{b}^{\infty} x^{m} e^{- \frac{a^{2}}{2} - \frac{x^{2}}{2}} I_{m - 1}\left(a x\right)\, dx
1998 Examples
1999 ========
2001 >>> from sympy import marcumq
2002 >>> from sympy.abc import m, a, b
2003 >>> marcumq(m, a, b)
2004 marcumq(m, a, b)
2006 Special values:
2008 >>> marcumq(m, 0, b)
2009 uppergamma(m, b**2/2)/gamma(m)
2010 >>> marcumq(0, 0, 0)
2011 0
2012 >>> marcumq(0, a, 0)
2013 1 - exp(-a**2/2)
2014 >>> marcumq(1, a, a)
2015 1/2 + exp(-a**2)*besseli(0, a**2)/2
2016 >>> marcumq(2, a, a)
2017 1/2 + exp(-a**2)*besseli(0, a**2)/2 + exp(-a**2)*besseli(1, a**2)
2019 Differentiation with respect to $a$ and $b$ is supported:
2021 >>> from sympy import diff
2022 >>> diff(marcumq(m, a, b), a)
2023 a*(-marcumq(m, a, b) + marcumq(m + 1, a, b))
2024 >>> diff(marcumq(m, a, b), b)
2025 -a**(1 - m)*b**m*exp(-a**2/2 - b**2/2)*besseli(m - 1, a*b)
2027 References
2028 ==========
2030 .. [1] https://en.wikipedia.org/wiki/Marcum_Q-function
2031 .. [2] https://mathworld.wolfram.com/MarcumQ-Function.html
2033 """
2035 @classmethod
2036 def eval(cls, m, a, b):
2037 if a is S.Zero:
2038 if m is S.Zero and b is S.Zero:
2039 return S.Zero
2040 return uppergamma(m, b**2 * S.Half) / gamma(m)
2042 if m is S.Zero and b is S.Zero:
2043 return 1 - 1 / exp(a**2 * S.Half)
2045 if a == b:
2046 if m is S.One:
2047 return (1 + exp(-a**2) * besseli(0, a**2))*S.Half
2048 if m == 2:
2049 return S.Half + S.Half * exp(-a**2) * besseli(0, a**2) + exp(-a**2) * besseli(1, a**2)
2051 if a.is_zero:
2052 if m.is_zero and b.is_zero:
2053 return S.Zero
2054 return uppergamma(m, b**2*S.Half) / gamma(m)
2056 if m.is_zero and b.is_zero:
2057 return 1 - 1 / exp(a**2*S.Half)
2059 def fdiff(self, argindex=2):
2060 m, a, b = self.args
2061 if argindex == 2:
2062 return a * (-marcumq(m, a, b) + marcumq(1+m, a, b))
2063 elif argindex == 3:
2064 return (-b**m / a**(m-1)) * exp(-(a**2 + b**2)/2) * besseli(m-1, a*b)
2065 else:
2066 raise ArgumentIndexError(self, argindex)
2068 def _eval_rewrite_as_Integral(self, m, a, b, **kwargs):
2069 from sympy.integrals.integrals import Integral
2070 x = kwargs.get('x', Dummy('x'))
2071 return a ** (1 - m) * \
2072 Integral(x**m * exp(-(x**2 + a**2)/2) * besseli(m-1, a*x), [x, b, S.Infinity])
2074 def _eval_rewrite_as_Sum(self, m, a, b, **kwargs):
2075 from sympy.concrete.summations import Sum
2076 k = kwargs.get('k', Dummy('k'))
2077 return exp(-(a**2 + b**2) / 2) * Sum((a/b)**k * besseli(k, a*b), [k, 1-m, S.Infinity])
2079 def _eval_rewrite_as_besseli(self, m, a, b, **kwargs):
2080 if a == b:
2081 if m == 1:
2082 return (1 + exp(-a**2) * besseli(0, a**2)) / 2
2083 if m.is_Integer and m >= 2:
2084 s = sum([besseli(i, a**2) for i in range(1, m)])
2085 return S.Half + exp(-a**2) * besseli(0, a**2) / 2 + exp(-a**2) * s
2087 def _eval_is_zero(self):
2088 if all(arg.is_zero for arg in self.args):
2089 return True