Skip to content

test(ddx-core): gate the finite-difference oracle on a measured noise floor (closes #67) - #94

Merged
alxmrs merged 1 commit into
mainfrom
fix/fd-oracle-noise
Oct 3, 2026
Merged

alxmrs merged 1 commit into
mainfrom
fix/fd-oracle-noise

Conversation

@alxmrs

@alxmrs alxmrs commented Sep 29, 2026

Copy link
Copy Markdown
Member

Closes #67. First of four small ddx-core fixes from the soaks, stacked: #67's oracle gate (this PR) ← #87's integer casts ← the quotient rule ← the power rule. The M3/M4 stack (#70–#83) and the v2 soak PRs (#89–#93) now sit on top of them.

The false positive

The nightly ddx-core soak reported d/dy CAST(power(3, power((((y + x) + abs(2.5)) - y), 2)) AS DOUBLE) = 0 as wrong, with a finite difference of 5e-5. The derivative is right, because f doesn't depend on y. What goes wrong is rounding: (y + x) - y rounds differently for each y, and the outer 3^(b²) multiplies that ulp of jitter by ∂f/∂b ≈ 7e6. So the difference quotient reads noise above the absolute tolerance (1e-5). The Richardson gate doesn't see it, because fd(h) and fd(h/2) carry noise of the same size.

The gate

test_utils::fd_noise_floor measures the noise floor rather than modelling it. It moves the variable by a few ulps, sees how far f moves beyond its slope, and divides by h. fd_failure then skips any point where four times the floor isn't under the tolerance. noise_gate_skips_only_rounding_dominated_points checks both directions:

The bounded suites pass. #67's DDX_SOAK_BASE=5820328895 replays clean, and a 3-minute soak (158k cases) found nothing.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CvszJhH8pn8H9G69wEPMU2

… floor

Closes #67. The nightly soak reported d/dy of
CAST(power(3, power((((y + x) + abs(2.5)) - y), 2)) AS DOUBLE) = 0 as
wrong, with a finite difference of 5e-5. The derivative is right: f does
not depend on y. But (y + x) - y rounds differently for each y, and the
outer 3^(b²) scales that ulp of jitter by ∂f/∂b ≈ 7e6, so the difference
quotient reads noise above the absolute tolerance. The Richardson gate
misses it because fd(h) and fd(h/2) carry noise of the same size.

test_utils::fd_noise_floor measures the floor instead of modelling it:
move the variable by a few ulps, see how far f moves beyond its slope, and
divide by h. fd_failure skips a point whose floor is not a quarter of the
tolerance or less. noise_gate_skips_only_rounding_dominated_points pins
both sides: #67's expression is gated and no longer reported at its seed,
well-conditioned expressions keep a floor far under the tolerance, and a
wrong derivative is still caught.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CvszJhH8pn8H9G69wEPMU2

@alxmrs alxmrs left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, good fix.

@alxmrs
alxmrs merged commit e44ea38 into main Oct 3, 2026
14 checks passed
@github-actions github-actions Bot mentioned this pull request Oct 3, 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.

Nightly fuzz: 1 property failure(s) in ddx-core simulation soak

1 participant