Skip to main content

Module jy_real

Module jy_real 

Source
Expand description

Bessel functions at arbitrary real order, starting with the large-x Hankel arm.

Separate from bessel_jy, which is the integer-order family and is built from fitted minimax rationals. Nothing here uses a coefficient table at any order: every term comes from a running ratio, which is what makes an arbitrary $\nu$ possible.

§The Hankel expansion, and why it needs no convergence test

J_\nu(x) \sim \sqrt{\frac{2}{\pi x}}\left(P(\nu,x)\cos\omega - Q(\nu,x)\sin\omega\right),
\qquad \omega = x - \left(\tfrac{\nu}{2} + \tfrac{1}{4}\right)\pi

with $P$ the even and $Q$ the odd part of $\sum_k a_k(\nu)/x^k$, and

\frac{a_k}{a_{k-1}} = \frac{\mu - (2k-1)^2}{8kx}, \qquad \mu = 4\nu^2

This series diverges. The ratio is about $k/2x$, so terms shrink while $k < 2x$ and grow forever after, and the least term (the floor on achievable accuracy) sits at $k^{*} = x + \sqrt{x^2 + \nu^2}$ with magnitude around $e^{-2x}$.

So there is nothing to converge to, and the stopping point is an index rather than a tolerance: the Counted discipline from iterate, not a convergence test.

It does not use sum_counted, though, and the reason is worth recording. Producing $Y_\nu$ as well as $J_\nu$ needs $P$ and $Q$ kept apart, which is two accumulators, and every driver in iterate carries one. An earlier $J$-only version did fold the two into a single sum by rotating the trig factor through $\cos, -\sin, -\cos, \sin$, and that worked, but it cannot produce $Y$. Running the ratio chain twice to get both is worse than carrying one extra accumulator.

That makes four places wanting a paired-accumulator driver: thermite-compensated’s sin_cos, this, cf2_pq below, and sum_counted’s now-vacant slot.

Boost instead tries the series and returns a bool (hankel_PQ), bailing when consecutive terms stop halving, which happens at $k \approx x$, only halfway to the least term. Measured, that costs it about two units of $x$ at small order and makes the arm unreachable entirely for $\nu \ge 8$, where its guard trips on the very first term. A try-and-fail arm is also the one shape a packet cannot do cheaply, since every lane would have to agree on whether the attempt worked.

§Where it is usable, measured rather than assumed

Smallest $x$ reaching 1 eps under optimal truncation, from notes/special/tools/model_hankel_divergence.py:

$\nu$01/31/2135812
binary6417.016.51.017.017.017.018.025.0
binary326.56.51.06.57.57.511.024.5

Flat in $\nu$ up to about 5, then rising roughly $1.75\nu$ (see hankel_usable_from). $\nu = 1/2$ is exact at any $x$ because $\mu = (2\nu)^2$ with $2\nu$ an odd integer makes $\mu - (2k-1)^2$ vanish at $k = \nu - 1/2$ and the series terminates. That is the same fact as “half-integer order is elementary”, seen from the asymptotic side.

§Term counts

Terms needed to reach tolerance, worst case at the gate and falling from there, since the stop is at tolerance rather than at the floor:

$x$172030603001000
binary642920141075
binary32554432

N is a const generic so the loop unrolls, and the caller picks it from that table. Carrying the worst case everywhere costs terms at large $x$ that are already below epsilon. Harmless numerically, and an open optimization rather than a correctness question.

Functions§

bessel_jy_real
$(J_\nu(x), Y_\nu(x))$ at arbitrary real order, over the whole positive axis.
hankel_jy_nu
$J_\nu(x)$ by the Hankel expansion, at arbitrary real order, for x past hankel_usable_from.
hankel_usable_from
The smallest x at which the Hankel arm reaches full precision for order nu.
series_j_nu
$J_\nu(x)$ by its ascending series, at arbitrary real order, for small x.
steed_jy_nu
$(J_\nu, Y_u, Y_{u+1})$ by Steed’s method at the reduced order $u = \nu - n$, $\lvert u\rvert \le 1/2$, for the band between the two other arms.
temme_y_nu
$(Y_\nu(x), Y_{\nu+1}(x))$ by Temme’s series, for small x and $\lvert\nu\rvert \le 1/2$.
Last built: 2026-09-08 21:35:55 UTC