Skip to main content

Module bessel

Module bessel 

Source
Expand description

The runtime Bessel order, and the cost class it selects.

The const-order Bessel entry point (bessel_n) takes a whole-number order known at compile time. The runtime form (bessel) takes BesselOrder instead of a bare order value, because “what order is this?” and “what does that order cost?” are different questions and only the caller can answer the second one cheaply.

The family markers (J, Y, I, K, Scaled, and the Airy selectors) live in this module too. See BesselFamily.

§Why a tagged order rather than a plain $\nu$

$J_\nu$ at whole-number $\nu$ is a table lookup plus a recurrence. At half-integer $\nu$ it is elementary: sines and cosines. At arbitrary real $\nu$ it is Steed’s method: two continued fractions and a Temme series, one of which needs $O(x)$ iterations. Those are three genuinely different algorithms with costs an order of magnitude apart, and under SIMD the whole packet pays for whichever is selected. A per-lane choice would make every lane pay every arm.

So the class is carried as a scalar tag and the order values as a vector. One packet runs one algorithm, and the caller can see in the type which one they asked for.

§Exact by construction

Each variant stores a numerator, not a rounded $\nu$: HalfInteger(k) means $\nu = k/2$ and Thirds(k) means $\nu = k/3$. This is not decoration. 1/3 is not representable in binary, so a design that stored $\nu$ as a float and tagged it separately could not distinguish Thirds(1) from a nearby real order, and the tag would be a promise the caller could break. Here the tag cannot disagree with the payload.

§Downgrading

simplify narrows a value to the cheapest variant its data actually needs, so a caller who reaches for Real and happens to pass whole numbers gets the fast path anyway. The runtime forms call it themselves. It’s public so a caller with a hot loop can hoist it out and pay the check once.

The checks run in cost order and cost proportionally to how general the claim was, so Integer checks nothing at all. Downgrading requires the condition to hold in every lane. One odd lane keeps the whole packet on the general path. A caller with a genuinely mixed packet can recover the fast path with group_by_value, which turns a divergent packet into uniform sub-packets.

§Real does not downgrade to Thirds, deliberately

Real -> Integer and Real -> HalfInteger are exact: whole numbers and halves are both representable, so the downgrade cannot change which function is evaluated.

Real -> Thirds would not be. fl(1.0/3.0) is not $1/3$, so snapping it to Thirds(1) would silently evaluate a different function than the caller asked for. Close, but wrong, and wrong in a way no test of Thirds itself would catch. A caller who wants an exact third writes Thirds(1), which is the whole reason the variant carries a numerator.

Structs§

Ai
$\mathrm{Ai}(x)$.
AiPrime
$\mathrm{Ai}'(x)$.
Bi
$\mathrm{Bi}(x)$.
BiPrime
$\mathrm{Bi}'(x)$.
I
Modified Bessel function of the first kind, $I_\nu$. Grows like $e^x$.
J
Bessel function of the first kind, $J_\nu$. The oscillating minimal solution.
K
Modified Bessel function of the second kind, $K_\nu$. Decays like $e^{-x}$.
Scaled
The exponentially scaled form of a family or Airy function.
Y
Bessel function of the second kind, $Y_\nu$ (Neumann). The oscillating dominant solution.

Enums§

BesselOrder
The order $\nu$ for the runtime-order Bessel functions, tagged with the class of order it carries. See the module documentation for why the class is part of the value.

Traits§

AiryFn
An Airy selector: Ai, AiPrime, Bi, BiPrime, or one of them under Scaled. Each asks the kernel for exactly its own output, so the cost is one Bessel pass, the same as the long-form single entries.
BesselFamily
A Bessel family marker: J, Y, I, K, or one of them under Scaled.
BesselRatioFamily
A family with a ratio kernel $F_\nu / F_{\nu-1}$ and its inverse, for bessel_ratio and its three companions. Only I today (the von Mises-Fisher quantities). A K ratio would be the next member.
Last built: 2026-09-08 21:35:55 UTC