Skip to content

SO2onDisk: default to the Nyquist band-limit so the DHT is well conditioned - #54

Merged
johmathe merged 2 commits into
mainfrom
johmathe/fix-disk-basis-conditioning
Oct 14, 2026
Merged

johmathe merged 2 commits into
mainfrom
johmathe/fix-disk-basis-conditioning

Conversation

@johmathe

Copy link
Copy Markdown
Collaborator

Stacked on #53 (needs the accurate Bessel roots). Merge #53 first, then retarget this to main.

Problem

The default truncation copied fle_2d's coefficient count ne = ⌊πL²/4⌋, which makes the analysis matrix Φ nearly square on an L×L grid: cond(Φ) ≈ 1e16. pinv(rcond=1e-10) then silently truncated, and the tests tolerated rel_err < 1.5 to pass.

Fix

  • default_bandlimit(L) = π·L/2 (grid Nyquist) is the new default; cond(Φ) ≈ 2 for L = 8…64.
  • Removed the ne truncation branch and the conjugate-pair-completion hack from _build_truncated_indices. Explicit bandlimit still works.
  • Docstrings explain why the fle_2d count is ill-conditioned on a Cartesian grid.

Breaking

Default output_size / feature layout changes (L=16: 105 → 76). README table updated.

Tests

cond(Φ) < 10 (L = 16, 32, 64); full-rank basis; DHT roundtrip 0.5 → 1e-12; invert exact coefficients (all, 1e-9) and bispectrum roundtrip 0.5 → 1e-10; rot90 invariance 1e-12; spatial rotation invariance on band-limited inputs; new Nyquist coefficient-count test.

Part of the v0.4.0 stack (B).

torch.special.bessel_j0/j1 are only ~5e-7 accurate in float64 on
x in [2.8, 14.5] (torch 2.11, arm64). bessel_jn used them as base
cases for n = 0, 1 and as seeds of the forward recurrence, so every
order, every root and the whole disk-harmonic basis inherited the
error (root j_{0,5} was off by 1e-6; J_n at roots was ~1e-7, not 0).

Evaluate all orders with Miller's backward recurrence, started above
max(n, ceil(max|x|)) so it is stable in both the x < n and the
oscillatory regime. A single pass now returns several orders
(_bessel_jn_multi), which the Newton root finders use to get
J_{n-1}, J_n, J_{n+1} in one evaluation.

Also fix a convergence pathology in the bracketed Newton solvers: once
Newton had converged (3 iterations) the iterate sat on a bracket
endpoint, the next step fell outside by rounding, and the solver fell
back to ~45 bisection iterations. A converged Newton step now pins
the bracket. Net effect: J_n accurate to 1e-15 on [0, 160] for
n <= 60, roots to 1e-14, and compute_all_bessel_roots is 3x faster.

Tests: mpmath-referenced J_n values (atol 1e-14) for n in
{0, 1, 2, 5, 20} on x up to 150, roots to 1e-13, J_0(0) = 1,
root residuals < 1e-13; the two tests that asserted equality with
torch.special are replaced.
…tioned

The default truncation followed fle_2d: ne = floor(pi L^2 / 4) basis
functions, one per disk pixel. That makes the real basis matrix Phi
nearly square and admits radial frequencies ~25% above the grid
Nyquist rate, so cond(Phi) ~ 1e16 at every L. pinv(rcond=1e-10) then
silently discarded directions: DHT roundtrips, inversion and even
exact 90-degree pixel rotations were only accurate to O(1), which the
tests tolerated (rel_err < 1.5, < 0.5, 85% of coefficients within 20%).

Default bandlimit is now pi * L / 2 (new public helper
default_bandlimit). cond(Phi) is ~2 for L = 8..64; DHT roundtrip,
coefficient inversion and bispectrum roundtrip are exact to 1e-14, and
rot90 invariance to 1e-14. The ne-truncation branch and its
conjugate-pair patch are removed; an explicit bandlimit still works.

Coefficient counts change (L=16: 144 DH coefficients, 76 selective
bispectrum entries instead of 105). README table updated.

Tests: cond(Phi) < 10 for L in {16, 32, 64}; exact rank; roundtrip
tolerances tightened to 1e-9..1e-12; new rot90 test; the arbitrary-angle
spatial test now uses band-limited content and bicubic interpolation
(its 0.1 tolerance is interpolation-bound, measured ~2e-2).
@johmathe
johmathe changed the base branch from johmathe/fix-bessel-j0-j1-accuracy to main October 14, 2026 16:41
@johmathe
johmathe merged commit 6a0d563 into main Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant