rugnux: the no-crystal near-tie line prints the exact log10 tail against log10 significance

The line put the distinct-reflection count against a normal-approximation bar, which at a
handful of reflections reads the wrong way: a control the exact test rejected (5 vs 2 by
chance, tail 10^-2.70 against 10^-3) was printed 0.59 above the bar. It now prints the exact
binomial tail and the significance, both as log10, with the margin in decades and the noise as
the tail's change over one binomial standard deviation of the count. The tail is summed in logs
(ValidationEvidenceLog10Tail), so it stays finite for a real lattice; the decisions compare the
same tail in log10.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SVmAWnzCmRKAXVUCdc4iNi
This commit is contained in:
2026-10-10 09:33:34 +02:00
co-authored by Claude Opus 5.5
parent cd20c2c378
commit 5984bf467f
4 changed files with 38 additions and 12 deletions
+8
View File
@@ -158,3 +158,11 @@ TEST_CASE("ValidationEvidenceBeatsChance_NoCrystalSignificance", "[RotationScale
// A weak real lattice on a few frames is still tens of decades past it.
CHECK(ValidationEvidenceBeatsChance({.reflections = 115, .reflections_by_chance = 4}, NO_CRYSTAL_SIGNIFICANCE));
}
TEST_CASE("ValidationEvidenceLog10Tail_Exact", "[RotationScale]") {
CHECK(ValidationEvidenceLog10Tail({.reflections = 4, .reflections_by_chance = 2}) == Catch::Approx(-2.0604).margin(1e-4));
CHECK(ValidationEvidenceLog10Tail({.reflections = 5, .reflections_by_chance = 2}) == Catch::Approx(-2.6981).margin(1e-4));
// Far below the smallest double, still finite.
CHECK(ValidationEvidenceLog10Tail({.reflections = 1354, .reflections_by_chance = 777}) == Catch::Approx(-509.691).margin(1e-3));
CHECK(ValidationEvidenceLog10Tail({}) == 0.0);
}