Skip to main content

Module ik_real

Module ik_real 

Source
Expand description

Modified Bessel $I_\nu$ and $K_\nu$ at arbitrary real order.

The modified twin of bessel_nu, and built for the same reason that one was: Boost’s Airy functions reach $\mathrm{Ai}$ and $\mathrm{Bi}$ for $x > 0$ through cyl_bessel_k(1/3, p) and cyl_bessel_i(\pm 1/3, p), not through $J$. Only the $x < 0$ branch is $J_{\pm 1/3}$, which bessel_nu already covers.

Port target: Boost.Math’s temme_ik, CF1_ik and CF2_ik, assembled in its bessel_ik. Modelled first in notes/special/tools/model_bessel_ik.py, which is where the three departures below were measured rather than argued.

§One body, two arithmetics

Every function here takes the order in a real vector R and the argument in C, with C: PrimalProjection<Primal = R>. On the real line C = R and nothing changes. Over C, thermite-complex instantiates the same body with C = Complex<R>: the order stays real (as it does in Amos, whose zbknu / zwrsk / zasyi are exactly the three arms below), every z-dependent quantity becomes complex, and the nu-only quantities (Temme’s $\Gamma(1\pm\nu)$ pieces, the $(2k+1)^2 - 4\nu^2$ numerators, the recurrence coefficients) stay real and enter through C: Mul<R>, which is two real multiplies rather than a complex one. Every decision the kernel makes about z (region, domain, overflow corner) goes through BesselDetails, because on Complex the plain comparisons mean something else.

§Three regions, and one fewer than Boost has

xKI
<= 2temme_ik + upward recurrenceWronskian, from K and [cf1_i_ratio]
2 .. max(40, nu^2/3)[cf2_ik] + upward recurrencesame
above that[cf2_ik] + upward recurrenceasymptotic_series_g

Boost’s fourth arm is deleted. It takes an ascending series for $I$ whenever $x/\nu < 0.25$. Measured against the continued fraction alone over orders to 100 and $x$ to 10 (the whole region where that test can fire), the series is 0.0 to 2.8 eps and the fraction 0.5 to 5.2 eps. Both are inside the crate’s contract, so the arm buys nothing a vector packet would not pay for anyway. It also needs a powf and a tgamma, and its own prefactor overflows at order 200 where the fraction does not care.

CF2_ik’s renormalisation is deleted too. Boost rescales q, prev, current and C whenever $q < \varepsilon$, and its comment says why: “particularly an issue for types which have many digits precision but a narrow exponent range. A typical example being a double double type.” Measured in binary64 over $u \in [-1/2, 1/2]$ and $x$ from 2.001 to $10^5$, with and without: 7.72 eps either way, identical. It is dead code at this precision, and a per-lane select if kept.

§What each arm costs

$K$ gets cheaper as $x$ grows and needs no asymptotic arm at all: [cf2_ik] takes 9 iterations at $x = 100$ and 2 at $x = 10^8$, at 1 eps throughout. $I$ is the opposite: [cf1_i_ratio] grows like $\sqrt{x}$ (39 iterations at 40, 428 at 5000, and simply fails to converge by $x = 10^6$), which is what the asymptotic handover is for. Boost’s own comment calls that growth $O(x)$. Measured here it is $O(\sqrt{x})$.

§Scaling

Everything is carried in the crate’s SCALED convention, $(e^{-x}I_\nu,\; e^{x}K_\nu)$, because that is the form the algorithm natively produces: [cf2_ik] has the $e^{-x}$ as an explicit factor, and once $K$ is scaled the Wronskian returns $I$ already scaled, with no exponential anywhere. The unscaled form is the one paying for a transcendental, the reverse of the small-$x$ arm where Temme’s series is naturally unscaled.

Functions§

bessel_ik_real
$(I_\nu(z), K_\nu(z))$ at arbitrary real order, over the positive axis (or, in a complex arithmetic, the right half-plane), scaled by $(e^{-z}, e^{z})$ when SCALED.
temme_ik
$(K_\nu(x), K_{\nu+1}(x))$ unscaled, by Temme’s series, for $|x| \le 2$ and $\lvert\nu\rvert \le 1/2$.
Last built: 2026-09-08 21:35:55 UTC