Expand description
Modified Bessel functions of the first kind, orders 0 and 1, scaled and unscaled.
§Two regions, not four
$I_0$ and $I_1$ split at x = 7.75 and nowhere else: an ascending series in
$a = x^2/4$ below, and $e^{x} P(1/x)/\sqrt{x}$ above. That is the whole shape.
The obvious reference for a SIMD Bessel is fdlibm, and fdlibm is the wrong model. Its
j0f splits the asymptotic envelope alone into four sub-intervals with a rational
apiece, which is optimal when a branch picks one and skips the rest, and pathological
here. A vector unit evaluates all four and discards three.
The tables underneath this kernel take Boost’s route instead: fewer regions, higher
degree in each. Same trade the Faddeeva kernel makes for the same reason.
The scalar sources carry a third region near the top of the range. It is not an accuracy
region. It exists so $e^x$ cannot overflow before $/\sqrt{x}$ brings the product back
down, and is reached here only under [thermite::unlikely], so the common path pays one
compare.
f32 $I_0$ is the one exception, and there the far fit is genuine: its large minimax
is fitted over [7.75, 50] and its constant term is wrong in the seventh digit, so
extending it to infinity costs about 16 ulp. See [crate::tables::bessel].
§The scaled forms are the cheaper ones
$e^{-x} I_n(x)$ is not a wrapper that multiplies an exponential back out. Above 7.75
the tables are the scaled value, so the scaled entry points skip the exponential
entirely and the unscaled ones pay for it. Below 7.75 the relationship inverts. Each form
therefore costs one transcendental in exactly one of its two arms, and neither is built
from the other. That is the relationship zetac has to zeta, for the same reason
($I_0(800)$ overflows f64 while $e^{-800}I_0(800)$ is a perfectly ordinary 0.0141).
Functions§
- asymptotic_
series_ g asymptotic_series_vover a general arithmetic: the argumentzinC, the order in its real primalR, and the far mask supplied by the caller.- bessel_
i0_ impl $I_0(x)$, or$e^{-|x|} I_0(x)$whenSCALED.- bessel_
i1_ impl $I_1(x)$, or$e^{-|x|} I_1(x)$whenSCALED.- bessel_
in_ impl $I_N(x)$forN >= 2, or$e^{-|x|} I_N(x)$whenSCALED.- bessel_
in_ pair_ impl I_N(x)forN >= 2, ore^{-|x|} I_N(x)whenSCALED, by downward recurrence on the ratios rather than on the values.- bessel_
iv_ impl I_n(x)with a per-lane order, ore^{-|x|} I_n(x)whenSCALED.- bessel_
k0_ impl $K_0(x)$, or$e^{x} K_0(x)$whenSCALED.- bessel_
k1_ impl $K_1(x)$, or$e^{x} K_1(x)$whenSCALED.- bessel_
kn_ recur $K_N(x)$forN >= 2from$K_0$and$K_1$, by upward recurrence.- bessel_
kv_ impl K_n(x)with a per-lane order, ore^{x} K_n(x)whenSCALED.- unscale_
i_ pair_ masked unscale_i_pairwith the far mask supplied, for an arithmetic where “far” is not a plain comparison: over C it isRe z >= threshold, andzitself is the exponent.