Skip to main content

airy_impl

Function airy_impl 

Source
pub fn airy_impl<P, E, V, const NH: usize, const NE: usize, const NO: usize, const FN: LargeInt, const FD: LargeInt, const SCALED: bool, const WANT_AI: bool, const WANT_AIP: bool, const WANT_BI: bool, const WANT_BIP: bool>(
    x: V,
    t: &LogGamma1p<E, NE, NO>,
    z: &AiryZero<E>,
    far_threshold: E,
) -> (V, V, V, V)
Expand description

$(\mathrm{Ai}(x),\; \mathrm{Ai}'(x),\; \mathrm{Bi}(x),\; \mathrm{Bi}'(x))$.

SciPy’s airy returns this tuple in this order, and so does this.

With SCALED, returns $(e^{\zeta}\mathrm{Ai},\; e^{\zeta}\mathrm{Ai}',\; e^{-\zeta}\mathrm{Bi},\; e^{-\zeta}\mathrm{Bi}')$ for $x > 0$ and the unscaled values for $x \le 0$, where they oscillate and there is nothing to scale (SciPy’s airye convention).

§The four WANT_* flags, and why the single-function entry points are not wrappers

The four outputs split across two independent Bessel evaluations: $\mathrm{Ai}$ and $\mathrm{Bi}$ come from order $1/3$, the two derivatives from order $2/3$. Nothing is shared between them, so a caller who wants one value should not pay for both passes, which is the whole reason airy_ai is its own entry point rather than airy(x).0.

Each pass is behind a const test on the flags, and on the positive axis WANT_BI / WANT_BIP additionally decide bessel_ik_real’s NEED_I: $\mathrm{Ai}$ is $K_{1/3}$ alone, so asking only for it skips the continued fraction and the asymptotic series that produce $I$. So airy_ai costs roughly a quarter of airy, not a half.

They are four separate bool parameters rather than one bitmask because a derived const cannot be a const-generic argument on stable (generic_const_exprs), and NEED_I has to be passed on. A standalone const parameter can be forwarded. WANT & BI cannot. Same wall the Bessel order parameter hit, recorded in the landmines.

Slots the flags exclude come back as zero. That is why the public entry points take one field each and the tuple ones set all four: the impl is the same function.

§Cost, and why the two branches are guarded

A packet spanning the origin runs both branches: $J/Y$ for the negative lanes, $I/K$ for the positive ones. Each is behind an any() guard, so a packet that does not straddle zero pays for one, which is the common case and worth the two branches.

Last built: 2026-09-08 21:35:55 UTC