<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://charlesreid1.com/w/index.php?action=history&amp;feed=atom&amp;title=Numerics%2FSpecial_Functions</id>
	<title>Numerics/Special Functions - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://charlesreid1.com/w/index.php?action=history&amp;feed=atom&amp;title=Numerics%2FSpecial_Functions"/>
	<link rel="alternate" type="text/html" href="https://charlesreid1.com/w/index.php?title=Numerics/Special_Functions&amp;action=history"/>
	<updated>2026-06-22T19:52:21Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.12</generator>
	<entry>
		<id>https://charlesreid1.com/w/index.php?title=Numerics/Special_Functions&amp;diff=30747&amp;oldid=prev</id>
		<title>Admin: Create Numerics/Special Functions: opinionated Python-centric guide to scipy.special, covering gamma, error, Bessel, Legendre, elliptic functions with usage patterns and edge cases. (via create-page on MediaWiki MCP Server)</title>
		<link rel="alternate" type="text/html" href="https://charlesreid1.com/w/index.php?title=Numerics/Special_Functions&amp;diff=30747&amp;oldid=prev"/>
		<updated>2026-06-22T04:46:17Z</updated>

		<summary type="html">&lt;p&gt;Create Numerics/Special Functions: opinionated Python-centric guide to scipy.special, covering gamma, error, Bessel, Legendre, elliptic functions with usage patterns and edge cases. (via create-page on MediaWiki MCP Server)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Special functions&amp;#039;&amp;#039;&amp;#039; are the workhorses of applied mathematics — they appear wherever the elementary functions (polynomials, exponentials, sines) fall short. This page is Python-centric and opinionated: if you need special functions, your first stop is always &amp;lt;code&amp;gt;scipy.special&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Why Special Functions Matter==&lt;br /&gt;
&lt;br /&gt;
Special functions arise from separating variables in PDEs, evaluating integrals that resist elementary treatment, and solving ODEs of second order with non-constant coefficients. They are not &amp;quot;special&amp;quot; because they&amp;#039;re obscure — they&amp;#039;re special because they&amp;#039;re the &amp;#039;&amp;#039;next&amp;#039;&amp;#039; functions you need after &amp;lt;code&amp;gt;exp&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sin&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;log&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In numerical work, the critical insight is: &amp;#039;&amp;#039;&amp;#039;never implement a special function yourself unless you have no other choice.&amp;#039;&amp;#039;&amp;#039; The reference implementations in &amp;lt;code&amp;gt;scipy.special&amp;lt;/code&amp;gt; are battle-tested, often wrapping C/Fortran libraries (Cephes, SLATEC, SPECFUN, AMOS) that have accumulated decades of corner-case fixes. A hand-rolled gamma function &amp;#039;&amp;#039;will&amp;#039;&amp;#039; lose precision near the negative integers. A hand-rolled Bessel function &amp;#039;&amp;#039;will&amp;#039;&amp;#039; be slow and inaccurate in asymptotic regimes.&lt;br /&gt;
&lt;br /&gt;
==The Python Toolbox: &amp;lt;code&amp;gt;scipy.special&amp;lt;/code&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;scipy.special&amp;lt;/code&amp;gt; (imported as &amp;lt;code&amp;gt;from scipy import special&amp;lt;/code&amp;gt;) is one of the oldest and most stable SciPy modules. It exposes roughly 500+ functions organized into families. Every function is vectorized (accepts NumPy arrays) and most support complex arguments.&lt;br /&gt;
&lt;br /&gt;
Core families and their canonical names:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Family !! &amp;lt;code&amp;gt;scipy.special&amp;lt;/code&amp;gt; entry points&lt;br /&gt;
|-&lt;br /&gt;
| Gamma &amp;amp;amp; related || &amp;lt;code&amp;gt;gamma&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;gammaln&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;digamma&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;polygamma&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;poch&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;beta&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;betaln&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Error functions || &amp;lt;code&amp;gt;erf&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;erfc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;erfcx&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;erfinv&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;wofz&amp;lt;/code&amp;gt; (Faddeeva)&lt;br /&gt;
|-&lt;br /&gt;
| Bessel functions || &amp;lt;code&amp;gt;jv&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;yv&amp;lt;/code&amp;gt; (1st/2nd kind), &amp;lt;code&amp;gt;iv&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;kv&amp;lt;/code&amp;gt; (modified), &amp;lt;code&amp;gt;jn&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;yn&amp;lt;/code&amp;gt; (integer order), &amp;lt;code&amp;gt;j0&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;y0&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;j1&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;y1&amp;lt;/code&amp;gt; (common real)&lt;br /&gt;
|-&lt;br /&gt;
| Spherical Bessel || &amp;lt;code&amp;gt;spherical_jn&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;spherical_yn&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;spherical_in&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;spherical_kn&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Airy functions || &amp;lt;code&amp;gt;airy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;airy_ai&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;airy_bi&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Legendre functions || &amp;lt;code&amp;gt;lpmv&amp;lt;/code&amp;gt; (associated), &amp;lt;code&amp;gt;legendre&amp;lt;/code&amp;gt; (integer order), &amp;lt;code&amp;gt;sph_harm&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Orthogonal polynomials || &amp;lt;code&amp;gt;eval_hermite&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;eval_chebyt&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;eval_chebyu&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;eval_legendre&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;eval_laguerre&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;eval_genlaguerre&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Elliptic integrals || &amp;lt;code&amp;gt;ellipk&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ellipe&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ellipkm1&amp;lt;/code&amp;gt; (complete); &amp;lt;code&amp;gt;ellipkinc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ellipeinc&amp;lt;/code&amp;gt; (incomplete)&lt;br /&gt;
|-&lt;br /&gt;
| Exponential/log integrals || &amp;lt;code&amp;gt;exp1&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;expi&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;exprel&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;loggamma&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Fresnel integrals || &amp;lt;code&amp;gt;fresnel&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;fresnel_zeros&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Struve &amp;amp;amp; Kelvin || &amp;lt;code&amp;gt;struve&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;kelvin&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ber&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;bei&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;ker&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;kei&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Opinionated Usage: Do This, Not That==&lt;br /&gt;
&lt;br /&gt;
===1. Always work in log-space with gamma ratios===&lt;br /&gt;
&lt;br /&gt;
The naive expression &amp;lt;code&amp;gt;gamma(n+1) / gamma(n-k+1)&amp;lt;/code&amp;gt; overflows for modest n. Use &amp;lt;code&amp;gt;gammaln&amp;lt;/code&amp;gt; instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
from scipy.special import gammaln, poch&lt;br /&gt;
&lt;br /&gt;
# BAD: overflows around n=171&lt;br /&gt;
# ratio = gamma(n+1) / gamma(n-k+1)&lt;br /&gt;
&lt;br /&gt;
# GOOD: log-space&lt;br /&gt;
log_ratio = gammaln(n+1) - gammaln(n-k+1)&lt;br /&gt;
ratio = np.exp(log_ratio)&lt;br /&gt;
&lt;br /&gt;
# BEST: use the rising factorial (Pochhammer symbol)&lt;br /&gt;
ratio = poch(n - k + 1, k)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;scipy.special&amp;lt;/code&amp;gt; provides &amp;lt;code&amp;gt;poch(a, n)&amp;lt;/code&amp;gt; precisely to compute &amp;lt;math&amp;gt;\Gamma(a+n)/\Gamma(a)&amp;lt;/math&amp;gt; without cancellation error. Use it.&lt;br /&gt;
&lt;br /&gt;
===2. Prefer &amp;lt;code&amp;gt;erfcx&amp;lt;/code&amp;gt; for large-x tails===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\operatorname{erfc}(x) \sim e^{-x^2}/(x\sqrt{\pi})&amp;lt;/math&amp;gt; underflows to zero for &amp;lt;math&amp;gt;x \gtrsim 26&amp;lt;/math&amp;gt; while the &amp;#039;&amp;#039;scaled&amp;#039;&amp;#039; complementary error function &amp;lt;math&amp;gt;\operatorname{erfcx}(x) = e^{x^2} \operatorname{erfc}(x)&amp;lt;/math&amp;gt; remains &amp;lt;math&amp;gt;O(1/x)&amp;lt;/math&amp;gt;. If you later multiply by &amp;lt;math&amp;gt;e^{x^2}&amp;lt;/math&amp;gt; — common in Gaussian integrals — use &amp;lt;code&amp;gt;erfcx&amp;lt;/code&amp;gt; directly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.special import erfc, erfcx&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
x = np.array([20.0, 25.0, 30.0])&lt;br /&gt;
&lt;br /&gt;
# BAD: underflows&lt;br /&gt;
# y = np.exp(x**2) * erfc(x)   # -&amp;gt; [0. 0. 0.]&lt;br /&gt;
&lt;br /&gt;
# GOOD:&lt;br /&gt;
y = erfcx(x)  # -&amp;gt; [0.028..., 0.023..., 0.019...]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===3. Use &amp;lt;code&amp;gt;loggamma&amp;lt;/code&amp;gt;, not &amp;lt;code&amp;gt;log(gamma(...))&amp;lt;/code&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gamma(x)&amp;lt;/code&amp;gt; overflows for &amp;lt;math&amp;gt;x \gtrsim 171.624&amp;lt;/math&amp;gt;. &amp;lt;code&amp;gt;loggamma&amp;lt;/code&amp;gt; handles this correctly and also gives the correct complex branch for negative arguments. Always prefer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.special import loggamma, gamma&lt;br /&gt;
&lt;br /&gt;
# BAD: overflow, and loss of sign for negative x&lt;br /&gt;
# log_g = np.log(gamma(x))&lt;br /&gt;
&lt;br /&gt;
# GOOD:&lt;br /&gt;
log_g = loggamma(x)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===4. Bessel: know when to use which kind===&lt;br /&gt;
&lt;br /&gt;
For real arguments, &amp;lt;code&amp;gt;jv(order, x)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;yv(order, x)&amp;lt;/code&amp;gt; are the workhorses. But for purely imaginary arguments (common in cylindrical harmonics with exponential decay/growth), the modified Bessel functions &amp;lt;code&amp;gt;iv&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;kv&amp;lt;/code&amp;gt; avoid complex arithmetic entirely and are exponentially faster:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.special import jv, iv&lt;br /&gt;
&lt;br /&gt;
# If x is purely imaginary: x = 1j * xi&lt;br /&gt;
# SLOW: jv(nu, 1j*xi) — complex arithmetic&lt;br /&gt;
# FAST: iv(nu, xi) — real arithmetic only&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===5. Orthogonal polynomials: use the &amp;lt;code&amp;gt;eval_*&amp;lt;/code&amp;gt; family, not recurrence relations===&lt;br /&gt;
&lt;br /&gt;
The temptation to write a three-term recurrence for Chebyshev or Hermite polynomials is strong. Resist it. &amp;lt;code&amp;gt;scipy.special.eval_chebyt(n, x)&amp;lt;/code&amp;gt; and friends use Clenshaw&amp;#039;s recurrence internally and avoid the catastrophic cancellation that naive recurrences suffer at high order:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from scipy.special import eval_chebyt, eval_hermite&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-1, 1, 1000)&lt;br /&gt;
T10 = eval_chebyt(10, x)   # Chebyshev T of order 10, stable&lt;br /&gt;
H20 = eval_hermite(20, x)  # Hermite of order 20, stable&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Key Mathematical Background==&lt;br /&gt;
&lt;br /&gt;
===Gamma Function===&lt;br /&gt;
&lt;br /&gt;
The gamma function extends the factorial to real and complex arguments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\Gamma(z) = \int_0^\infty t^{z-1} e^{-t} \, dt \qquad \Re(z) &amp;gt; 0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The reflection formula &amp;lt;math&amp;gt;\Gamma(z)\Gamma(1-z) = \pi/\sin(\pi z)&amp;lt;/math&amp;gt; and the duplication formula &amp;lt;math&amp;gt;\Gamma(2z) = \pi^{-1/2} 2^{2z-1} \Gamma(z) \Gamma(z+1/2)&amp;lt;/math&amp;gt; are useful analytically but rarely needed numerically — &amp;lt;code&amp;gt;scipy.special.gamma&amp;lt;/code&amp;gt; handles the full complex plane.&lt;br /&gt;
&lt;br /&gt;
The digamma &amp;lt;math&amp;gt;\psi(z) = \Gamma&amp;#039;(z)/\Gamma(z)&amp;lt;/math&amp;gt; and polygamma &amp;lt;math&amp;gt;\psi^{(n)}(z)&amp;lt;/math&amp;gt; are the logarithmic derivatives — they appear in maximum likelihood estimation for gamma, beta, and Dirichlet distributions.&lt;br /&gt;
&lt;br /&gt;
===Error Function===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\operatorname{erf}(x) = \frac{2}{\sqrt{\pi}} \int_0^x e^{-t^2} \, dt&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The complementary error function &amp;lt;math&amp;gt;\operatorname{erfc}(x) = 1 - \operatorname{erf}(x)&amp;lt;/math&amp;gt; is numerically essential: for large x, &amp;lt;math&amp;gt;1 - \operatorname{erf}(x)&amp;lt;/math&amp;gt; suffers catastrophic cancellation, while &amp;lt;code&amp;gt;erfc&amp;lt;/code&amp;gt; computes it directly via asymptotic expansions.&lt;br /&gt;
&lt;br /&gt;
The Faddeeva function &amp;lt;math&amp;gt;w(z) = e^{-z^2} \operatorname{erfc}(-iz)&amp;lt;/math&amp;gt; (available as &amp;lt;code&amp;gt;wofz&amp;lt;/code&amp;gt;) is the complex extension and the computational engine behind Voigt profiles in spectroscopy.&lt;br /&gt;
&lt;br /&gt;
===Bessel Functions===&lt;br /&gt;
&lt;br /&gt;
Bessel&amp;#039;s differential equation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x^2 \frac{d^2 y}{dx^2} + x \frac{dy}{dx} + (x^2 - \nu^2) y = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Its two linearly independent solutions are &amp;lt;math&amp;gt;J_\nu(x)&amp;lt;/math&amp;gt; (Bessel of the first kind, regular at the origin) and &amp;lt;math&amp;gt;Y_\nu(x)&amp;lt;/math&amp;gt; (Bessel of the second kind, singular at the origin). The modified Bessel functions &amp;lt;math&amp;gt;I_\nu(x) = i^{-\nu} J_\nu(ix)&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;K_\nu(x)&amp;lt;/math&amp;gt; solve the modified equation &amp;lt;math&amp;gt;x^2 y&amp;#039;&amp;#039; + x y&amp;#039; - (x^2 + \nu^2) y = 0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For integer order n, &amp;lt;code&amp;gt;jn(n, x)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;yn(n, x)&amp;lt;/code&amp;gt; are optimized paths that are significantly faster than the general &amp;lt;code&amp;gt;jv(nu, x)&amp;lt;/code&amp;gt; with float nu.&lt;br /&gt;
&lt;br /&gt;
===Legendre and Associated Legendre Functions===&lt;br /&gt;
&lt;br /&gt;
The associated Legendre functions &amp;lt;math&amp;gt;P_\ell^m(x)&amp;lt;/math&amp;gt; solve:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;(1-x^2) \frac{d^2}{dx^2} P_\ell^m - 2x \frac{d}{dx} P_\ell^m + \left[ \ell(\ell+1) - \frac{m^2}{1-x^2} \right] P_\ell^m = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
They are the angular part of the spherical harmonic &amp;lt;math&amp;gt;Y_\ell^m(\theta, \phi) \propto P_\ell^m(\cos\theta) e^{im\phi}&amp;lt;/math&amp;gt;. Use &amp;lt;code&amp;gt;sph_harm(m, n, theta, phi)&amp;lt;/code&amp;gt; to compute spherical harmonics directly — it normalizes correctly and handles the Condon-Shortley phase.&lt;br /&gt;
&lt;br /&gt;
===Elliptic Integrals===&lt;br /&gt;
&lt;br /&gt;
These cannot be expressed in terms of elementary functions and arise in pendulum problems, meridian arc lengths, and conformal mapping:&lt;br /&gt;
&lt;br /&gt;
Complete elliptic integral of the first kind: &amp;lt;math&amp;gt;K(k) = \int_0^{\pi/2} \frac{d\theta}{\sqrt{1-k^2\sin^2\theta}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Complete elliptic integral of the second kind: &amp;lt;math&amp;gt;E(k) = \int_0^{\pi/2} \sqrt{1-k^2\sin^2\theta} \, d\theta&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SciPy uses the &amp;#039;&amp;#039;parameter&amp;#039;&amp;#039; &amp;lt;math&amp;gt;m = k^2&amp;lt;/math&amp;gt; as input to &amp;lt;code&amp;gt;ellipk(m)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ellipe(m)&amp;lt;/code&amp;gt;. &amp;#039;&amp;#039;&amp;#039;This is the single most common bug with elliptic integrals in SciPy&amp;#039;&amp;#039;&amp;#039;: confusing the modulus &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; with the parameter &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Always double-check which convention your source uses.&lt;br /&gt;
&lt;br /&gt;
==Asymptotics and Edge Cases==&lt;br /&gt;
&lt;br /&gt;
Special functions often have distinct asymptotic regimes (small argument, large argument, near singular points), and no single algorithm works well everywhere. &amp;lt;code&amp;gt;scipy.special&amp;lt;/code&amp;gt; switches between Taylor series, asymptotic expansions, continued fractions, and recurrence relations automatically — but you should still be aware of the regimes:&lt;br /&gt;
&lt;br /&gt;
===Where Things Go Wrong===&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Negative integer gamma&amp;#039;&amp;#039;&amp;#039;: &amp;lt;math&amp;gt;\Gamma(-n)&amp;lt;/math&amp;gt; has a pole. &amp;lt;code&amp;gt;gamma(-2.0)&amp;lt;/code&amp;gt; returns &amp;lt;code&amp;gt;inf&amp;lt;/code&amp;gt; — this is correct behavior, not a bug.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Bessel at high order&amp;#039;&amp;#039;&amp;#039;: When &amp;lt;math&amp;gt;\nu \gg x&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;J_\nu(x)&amp;lt;/math&amp;gt; underflows. Use &amp;lt;code&amp;gt;ive&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;kve&amp;lt;/code&amp;gt; (exponentially scaled) for these regimes.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Associated Legendre near &amp;lt;math&amp;gt;x = \pm 1&amp;lt;/math&amp;gt;&amp;#039;&amp;#039;&amp;#039;: &amp;lt;math&amp;gt;P_\ell^m(x)&amp;lt;/math&amp;gt; involves factors of &amp;lt;math&amp;gt;(1-x^2)^{m/2}&amp;lt;/math&amp;gt; that vanish at the endpoints for &amp;lt;math&amp;gt;m &amp;gt; 0&amp;lt;/math&amp;gt;. This is analytic, not numerical, behavior.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Elliptic integrals near &amp;lt;math&amp;gt;m=1&amp;lt;/math&amp;gt;&amp;#039;&amp;#039;&amp;#039;: &amp;lt;math&amp;gt;K(m)&amp;lt;/math&amp;gt; diverges logarithmically as &amp;lt;math&amp;gt;m \to 1^{-}&amp;lt;/math&amp;gt;. Use &amp;lt;code&amp;gt;ellipkm1(x)&amp;lt;/code&amp;gt; which computes &amp;lt;math&amp;gt;K(1-x)&amp;lt;/math&amp;gt; accurately for small &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Performance Notes==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;scipy.special&amp;lt;/code&amp;gt; functions are compiled C/Fortran under the hood but callable from Python with negligible overhead for vectorized inputs. A few rules:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Vectorize, don&amp;#039;t loop.&amp;#039;&amp;#039;&amp;#039; Calling &amp;lt;code&amp;gt;gamma(np.array([1,2,3,4,5]))&amp;lt;/code&amp;gt; is orders of magnitude faster than &amp;lt;code&amp;gt;[gamma(i) for i in [1,2,3,4,5]]&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Use the integer-order paths when order is integer.&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;jn(3, x)&amp;lt;/code&amp;gt; is faster than &amp;lt;code&amp;gt;jv(3.0, x)&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;For repeated evaluation at the same order with different arguments&amp;#039;&amp;#039;&amp;#039;, consider &amp;lt;code&amp;gt;jvp&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;ivp&amp;lt;/code&amp;gt; (Bessel with pre-computed order scaling): these save initialization cost.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;gammaln&amp;lt;/code&amp;gt; is one of the most heavily optimised functions in SciPy.&amp;#039;&amp;#039;&amp;#039; Use it liberally — it is rarely the bottleneck.&lt;br /&gt;
&lt;br /&gt;
==Relationship to Other Numerics Topics==&lt;br /&gt;
&lt;br /&gt;
* Integration of functions that involve special functions: use [[Numerics/Integration of Functions|quadrature rules]] with adaptive scheme — &amp;lt;code&amp;gt;scipy.integrate.quad&amp;lt;/code&amp;gt; handles integrable singularities.&lt;br /&gt;
* Root-finding with special functions: [[Numerics/Root Finding|bracket-and-bisect]] is safest when the function has poles (e.g., Bessel zeros).&lt;br /&gt;
* Fourier transforms involving Bessel functions: these are Hankel transforms — see [[Numerics/Fast Fourier Transform]].&lt;br /&gt;
* Orthogonal polynomials arise naturally in [[Numerics/Interpolation Extrapolation|spectral methods and interpolation]].&lt;br /&gt;
&lt;br /&gt;
==Further Reading==&lt;br /&gt;
&lt;br /&gt;
* F. W. J. Olver et al., &amp;#039;&amp;#039;NIST Handbook of Mathematical Functions&amp;#039;&amp;#039; (Cambridge, 2010) — the successor to Abramowitz &amp;amp;amp; Stegun, and the primary reference for &amp;lt;code&amp;gt;scipy.special&amp;lt;/code&amp;gt; implementations. Also freely available as the [https://dlmf.nist.gov/ DLMF].&lt;br /&gt;
* M. Abramowitz &amp;amp;amp; I. A. Stegun, &amp;#039;&amp;#039;Handbook of Mathematical Functions&amp;#039;&amp;#039; (Dover, 1964) — still useful for its tables and formula density.&lt;br /&gt;
* SciPy special function [https://docs.scipy.org/doc/scipy/reference/special.html documentation] — always check which convention (modulus vs. parameter, type-1 vs. type-2 normalization) a function uses.&lt;br /&gt;
* Zhang &amp;amp;amp; Jin, &amp;#039;&amp;#039;Computation of Special Functions&amp;#039;&amp;#039; (Wiley, 1996) — contains the Fortran routines that underpin many &amp;lt;code&amp;gt;scipy.special&amp;lt;/code&amp;gt; functions.&lt;br /&gt;
&lt;br /&gt;
[[Category:Numerics]]&lt;br /&gt;
[[Category:Numerical Recipes]]&lt;br /&gt;
[[Category:Python]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>