Skip to content
This repository was archived by the owner on Aug 20, 2026. It is now read-only.

test: check the RLS field operator reduces to the unweighted one at w == 1 - #59

Merged
balbasty merged 1 commit into
mainfrom
claude/40-membrane-rls-half-strength-test
Aug 1, 2026
Merged

test: check the RLS field operator reduces to the unweighted one at w == 1#59
balbasty merged 1 commit into
mainfrom
claude/40-membrane-rls-half-strength-test

Conversation

@balbasty

Copy link
Copy Markdown
Contributor

Companion test for fastfields/fastfields-kernels#64 (fastfields-kernels#40).

Why the bug got through

The reg_field RLS/JRLS tests only asserted self-adjointness
(<L(w)x, y> == <x, L(w)y>). That oracle is blind to the magnitude of the
penalty coefficients — a term computed at the wrong strength stays perfectly
symmetric, so a pure scaling bug passes the suite unnoticed.

That is exactly what happened in fastfields-kernels#40, where
make_kernel_bending_rls rescaled its whole kernel table by 0.25 — correct
for the second-order (bending) coefficients, wrong for the first-order entries,
which also carry a membrane contribution wanting 0.5. The membrane penalty ran
at half strength whenever the bending-order kernel was constructed, and every
existing test still passed.

What this adds

run_2d_matvec_rls_unit_weight, which pins magnitude with an independent
oracle: with a uniform weight map w ≡ 1, the weighted operator must reduce
exactly to the plain unweighted field_matvec at the same order, since
w ≡ 1 is the identity case of the RLS generalisation.

Restricted to the boundary conditions whose implicit extension maps a constant
weight map to itself — DCT2 (reflects) and DFT (wraps). Zero would extend the
weight map by 0 and DST2 by -w, so neither is an identity case for the
weighted operator and neither belongs in this check.

Covers the absolute, membrane and bending orders, for both RLS (wc=1) and
JRLS (wc=C).

Verification

The same oracle evaluated directly against the kernel templates gives
max |matvec_bending − matvec_bending_rls(w≡1)|:

case (2D)before kernels fixafter
absolute-only0.000e+000.000e+00
bending-only1.066e-141.066e-14
membrane-only1.837e+004.441e-16
combined1.837e+001.421e-14

i.e. the symptom reported in fastfields-kernels#40 and its resolution. The
absolute-only and bending-only rows are bit-for-bit unchanged.

Depends on fastfields/fastfields-kernels#64 — the new rows fail without that
fix (which is the point). Merge that first, or this PR's CI will be red until
the kernels submodule pointer picks it up.

Workstream: claude-jitfields-to-fastfields

🤖 Generated with Claude Code


Generated by Claude Code

… == 1
The reg_field RLS/JRLS tests only asserted self-adjointness
(`<L(w)x, y> == <x, L(w)y>`). That oracle is blind to the *magnitude* of the
penalty coefficients: a term computed at the wrong strength stays perfectly
symmetric, so a scaling bug passes the suite unnoticed.
That is exactly what happened in fastfields-kernels#40, where
`make_kernel_bending_rls` rescaled its whole kernel table by 0.25 -- right for
the second-order (bending) coefficients, wrong for the first-order entries,
which also carry a membrane contribution wanting 0.5. The membrane penalty ran
at half strength whenever the bending-order kernel was constructed, and every
existing test still passed.
Add `run_2d_matvec_rls_unit_weight`, which pins magnitude with an independent
oracle: with a uniform weight map `w == 1` the weighted operator must reduce
*exactly* to the plain unweighted `field_matvec` at the same order, since
w == 1 is the identity case of the RLS generalisation.
Restricted to the boundary conditions whose implicit extension maps a constant
weight map to itself -- DCT2 (reflects) and DFT (wraps). Zero would extend the
weight map by 0 and DST2 by -w, so neither is an identity case for the weighted
operator and neither belongs in this check.
Covers absolute, membrane and bending orders, RLS (wc=1) and JRLS (wc=C).
The same oracle, evaluated directly against the kernel templates, gives
max |matvec_bending - matvec_bending_rls(w=1)| = 1.837e+00 before the kernels
fix and 4.441e-16 after it (2D, membrane-only, bending-order kernel), while the
absolute-only and bending-only cases are bit-for-bit unchanged at 0.0 and
1.066e-14 -- the symptom reported in fastfields-kernels#40 and its resolution.
Requires the kernels fix (fastfields-kernels#64); these rows fail without it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016AjQcY78NgbagPSbPJRr6Z
balbasty added a commit that referenced this pull request Aug 1, 2026
Picks up fastfields-cpu-impl's kernels-pin bump (fastfields-kernels#40's
membrane-in-bending-RLS scale fix, and kernels#52's OOB wget guard),
plus the C++ lint/format gate.
impl: b6eae48 -> 655abb9
Unblocks #59 (the regression test for the membrane-RLS fix), which
needs this pin so `field_matvec_rls` actually routes through the
corrected kernel construction.
Claude-Session: https://claude.ai/code/session_016AjQcY78NgbagPSbPJRr6Z
Co-authored-by: Claude <noreply@anthropic.com>
@balbasty
balbasty merged commit d07e987 into mainAug 1, 2026
1 of 5 checks passed
@balbasty
balbasty deleted the claude/40-membrane-rls-half-strength-test branch August 1, 2026 20:54
balbasty added a commit that referenced this pull request Aug 2, 2026
Pulls in fastfields-cpu-impl#48, which forces the RLS weight-channel
stride (wsc) to 0 in matvec/diag/relax_rls for absolute/membrane/
bending instead of deriving it from the wgt tensor's real (size-1)
last-dim stride -- the latter let wgt[wsc*c] walk off the wc=1
buffer into the next spatial voxel's weight for field channels c>0,
which is what run_2d_matvec_rls_unit_weight (added in #59, the
regression test for kernels#40) was catching as 29 mismatched
elements in test_reg_field.
Verified: `make -C . test CXX=clang++` -- all 12 suites pass, 0
failures. test_reg_field: 8440 checks, 0 failures (was 29 failing).
test_reg_flow: 11415 checks, 0 failures (flow's RLS path was never
affected -- see fastfields-cpu-impl#48 for why).
Closes#62
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@balbasty@claude