cultmath tests: snoise second-difference check tolerates kernel-edge points by a stated fraction
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
276484e15b
commit
00a477e387
1 changed files with 12 additions and 3 deletions
|
|
@ -144,6 +144,7 @@ public sealed class SpanPrimitiveTests
|
|||
var random = new System.Random(0x5A12);
|
||||
double worst = 0.0, largest = 0.0;
|
||||
var compared = 0;
|
||||
var outside = 0;
|
||||
for (var k = 0; k < 4000; k++)
|
||||
{
|
||||
var p = LatticePoint(random);
|
||||
|
|
@ -154,7 +155,11 @@ public sealed class SpanPrimitiveTests
|
|||
// Richardson on the O(h^2) second difference: (4 S(h/2) - S(h)) / 3 is O(h^4). Two such
|
||||
// extrapolations, from (h, h/2) and from (h/2, h/4), differ by about fifteen times the
|
||||
// error of the finer one, so the comparison is against the finer and its tolerance is
|
||||
// four times that gap, plus the roundoff of snoise (a few ulp) over (h/4)^2.
|
||||
// four times that gap, plus the roundoff of snoise (a few ulp) over (h/4)^2. Near a
|
||||
// kernel's edge (m = 0) snoise's fourth derivative jumps and the extrapolation loses its
|
||||
// order: such an entry may exceed the tight tolerance, but never by more than the gap
|
||||
// between the last two second differences (an error that shrinks at least linearly in h
|
||||
// is at most that gap), and the tight tolerance must hold for all but a fraction.
|
||||
const float h = 1.0f / 16.0f;
|
||||
var s0 = SecondDifference(p, i, j, h);
|
||||
var s1 = SecondDifference(p, i, j, h / 2.0f);
|
||||
|
|
@ -162,16 +167,20 @@ public sealed class SpanPrimitiveTests
|
|||
var coarseExtrapolation = (4.0 * s1 - s0) / 3.0;
|
||||
var extrapolated = (4.0 * s2 - s1) / 3.0;
|
||||
var tolerance = 4.0 * Math.Abs(extrapolated - coarseExtrapolation) + 64.0 * Unit / ((h / 4.0) * (h / 4.0));
|
||||
var loose = tolerance + 2.0 * Math.Abs(s1 - s2);
|
||||
var error = Math.Abs(hessian[i][j] - extrapolated);
|
||||
worst = Math.Max(worst, error / tolerance);
|
||||
largest = Math.Max(largest, Math.Abs(hessian[i][j]));
|
||||
compared++;
|
||||
Assert.True(error <= tolerance, $"snoise_hessian({p})[{i}][{j}] = {hessian[i][j]:R} differs from the extrapolated second difference of snoise {extrapolated:R} by {error:R}, over the measured tolerance {tolerance:R}");
|
||||
if (error > tolerance)
|
||||
outside++;
|
||||
Assert.True(error <= loose, $"snoise_hessian({p})[{i}][{j}] = {hessian[i][j]:R} differs from the extrapolated second difference of snoise {extrapolated:R} by {error:R}, over the measured tolerance {loose:R}");
|
||||
}
|
||||
}
|
||||
|
||||
output.WriteLine($"snoise_hessian vs Richardson second differences of snoise over 4000 seeded points: {compared} entries, worst error {worst:F3} of its tolerance, largest |H| {largest:R}");
|
||||
output.WriteLine($"snoise_hessian vs Richardson second differences of snoise over 4000 seeded points: {compared} entries, {outside} over the tight tolerance, worst error {worst:F3} of it, largest |H| {largest:R}");
|
||||
Assert.True(largest > 10.0, $"the sample never meets curvature above 10 (largest {largest:R})");
|
||||
Assert.True(outside <= compared / 200, $"{outside} of {compared} entries are over the tight Richardson tolerance, more than 0.5%");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
Loading…
Reference in a new issue