diff --git a/packages/cultmath/README.md b/packages/cultmath/README.md
index 24662be7..1a26571b 100644
--- a/packages/cultmath/README.md
+++ b/packages/cultmath/README.md
@@ -78,6 +78,15 @@ shader semantics.
then `CultMath.Phacelle.glsl` only if it calls `cultmath_phacelle` and
`CultMath.Cycles.glsl` only if it calls a `cultmath_cycles_` function, then its
own shader source.
+- Span primitives (`math.Span.cs`, `cultmath_*` in HLSL and GLSL): `snoise_hessian`,
+ the analytic Hessian of `snoise(float3)` on the same lattice, hash and tie order as
+ `snoise_grad` (a symmetric `float3x3`; GLSL `mat3`), and `integral_clamp_linear(a,
+ b, lo, hi, t0, t1)`, the closed-form integral over `[t0, t1]` of `clamp(a + b t,
+ lo, hi)`. Three measured bounds describe `snoise`: `SNOISE_LIPSCHITZ` (gradient
+ length, `NoiseBoundTests.MeasureLipschitz`), `SNOISE_HESSIAN` (Hessian spectral
+ norm, `MeasureHessian`) and `SNOISE_THIRD` (third-derivative operator norm,
+ `MeasureThird`); each is 1.10 times a seeded maximum refined by ascent, and a
+ fast test pins it. They are empirical with a margin, not proofs.
- `Voronoi.SampleTones`, a C# batch surface that calls the Rust
`cultmath-core` native kernel when `cultmath_core` is available and falls back
to the managed parity path otherwise.
diff --git a/packages/cultmath/shaders/CultMath.Affine.hlsl b/packages/cultmath/shaders/CultMath.Affine.hlsl
index 8727081e..09616940 100644
--- a/packages/cultmath/shaders/CultMath.Affine.hlsl
+++ b/packages/cultmath/shaders/CultMath.Affine.hlsl
@@ -10,11 +10,11 @@
// An upper bound on the spectral norm of the Hessian of cultmath_snoise(float3); provenance in
// math.Affine.cs (SNOISE_HESSIAN).
-static const float CULTMATH_SNOISE_HESSIAN = 56.050385;
+static const float CULTMATH_SNOISE_HESSIAN = 55.642143;
// An upper bound on the operator norm of the third-derivative tensor of cultmath_snoise(float3), the
// next order after CULTMATH_SNOISE_HESSIAN; provenance in math.Span.cs (SNOISE_THIRD).
-static const float CULTMATH_SNOISE_THIRD = 1.0;
+static const float CULTMATH_SNOISE_THIRD = 536.9152;
float3 cultmath_af_point(float value) { return float3(value, 0.0, 0.0); }
float3 cultmath_af_symbol(float x0, float a) { return float3(x0, a, 0.0); }
diff --git a/packages/cultmath/src/CultMath/math.Affine.cs b/packages/cultmath/src/CultMath/math.Affine.cs
index 8c4ce94a..acb73251 100644
--- a/packages/cultmath/src/CultMath/math.Affine.cs
+++ b/packages/cultmath/src/CultMath/math.Affine.cs
@@ -21,9 +21,10 @@ public static partial class math
// plain function of float values, so it mirrors into the HLSL common subset.
// An upper bound on the spectral norm of the Hessian of snoise(float3). Provenance:
- // NoiseBoundTests.MeasureHessian (slow, explicit) takes the largest Hessian norm (central
- // differences of snoise_grad, largest absolute eigenvalue) over 1e6 seeded points, refines the 1e4
- // largest by ascent, and multiplies the refined maximum by 1.10;
+ // NoiseBoundTests.MeasureHessian (slow, explicit) takes the largest Hessian norm (snoise_hessian,
+ // largest absolute eigenvalue) over 1e6 seeded points, refines the 1e4 largest by ascent, and
+ // multiplies the refined maximum by 1.10 (50.5838 measured, 55.642143 pinned; the central
+ // differences of snoise_grad it replaced read 50.955 here, their roundoff at h = 1e-3);
// NoiseBoundTests.HessianConstantPinsSampledCurvature pins this value against a fast re-measure and
// the ascent from MeasureHessian's witness. Empirical with a margin, not a proof. Random balls
// cannot see a constant 20% low, so the defence is those two curvature tests plus
@@ -32,7 +33,7 @@ public static partial class math
// whole 289^3 hash period found a realised maximum of 50.58, and bounding each corner's gradient
// independently over every hash configuration gives 52.22 (Soul pass s1). A change to the snoise
// kernel must re-run MeasureHessian and re-pin it. SNOISE_THIRD (math.Span.cs) is the next-order pin.
- public const float SNOISE_HESSIAN = 56.050385f;
+ public const float SNOISE_HESSIAN = 55.642143f;
/// The point form (x, 0, 0): the value x at every eps. Exact.
public static float3 af_point(float value) => new(value, 0.0f, 0.0f);
diff --git a/packages/cultmath/src/CultMath/math.Span.cs b/packages/cultmath/src/CultMath/math.Span.cs
index 4adc1139..364bd04b 100644
--- a/packages/cultmath/src/CultMath/math.Span.cs
+++ b/packages/cultmath/src/CultMath/math.Span.cs
@@ -10,9 +10,10 @@ public static partial class math
// refines the 1e4 largest by ascent over the point, and multiplies the maximum by 1.10; it prints
// the witness start. NoiseBoundTests.ThirdConstantPinsSampled pins the value against a fast
// re-measure and the ascent from that witness. Measured on the tied kernel (snoise_grad's order),
- // not on any pre-tie splice. Empirical with a margin, not a proof. A change to the snoise kernel
+ // not on any pre-tie splice. Measured 488.1047 (a dense sweep of 20,000 directions at the witness
+ // found 99.9998% of the tensor norm there). Empirical with a margin, not a proof. A change to the snoise kernel
// must re-run MeasureThird and re-pin it.
- public const float SNOISE_THIRD = 1.0f;
+ public const float SNOISE_THIRD = 536.9152f;
// Analytic Hessian of snoise(float3): the symmetric matrix of second partial derivatives, same
// lattice, hash and tie order as snoise_grad, whose kernel it differentiates once more. Every local
diff --git a/packages/cultmath/tests/CultMath.Tests/NoiseBoundTests.cs b/packages/cultmath/tests/CultMath.Tests/NoiseBoundTests.cs
index f0e6d084..312770ba 100644
--- a/packages/cultmath/tests/CultMath.Tests/NoiseBoundTests.cs
+++ b/packages/cultmath/tests/CultMath.Tests/NoiseBoundTests.cs
@@ -605,7 +605,7 @@ public sealed class NoiseBoundTests
}
// The start MeasureHessian printed as its witness.
- private static readonly float3 HessianWitness = new(-245.19885f, -53.01323f, -91.47363f);
+ private static readonly float3 HessianWitness = new(-13.7920685f, -9.672134f, 61.563934f);
///
/// Pins SNOISE_HESSIAN: no Hessian norm over 1e5 seeded points exceeds it, and the ascent from
@@ -780,7 +780,7 @@ public sealed class NoiseBoundTests
}
// The start MeasureThird printed as its witness.
- private static readonly float3 ThirdWitness = new(0.0f, 0.0f, 0.0f);
+ private static readonly float3 ThirdWitness = new(-168.3755f, -3.8205261f, -109.16948f);
///
/// Pins SNOISE_THIRD: no third-derivative norm over 1e5 seeded points exceeds it, and the ascent from
diff --git a/packages/cultmath/unity/org.gamecult.cultmath/Shaders/CultMath.Affine.hlsl b/packages/cultmath/unity/org.gamecult.cultmath/Shaders/CultMath.Affine.hlsl
index 8727081e..09616940 100644
--- a/packages/cultmath/unity/org.gamecult.cultmath/Shaders/CultMath.Affine.hlsl
+++ b/packages/cultmath/unity/org.gamecult.cultmath/Shaders/CultMath.Affine.hlsl
@@ -10,11 +10,11 @@
// An upper bound on the spectral norm of the Hessian of cultmath_snoise(float3); provenance in
// math.Affine.cs (SNOISE_HESSIAN).
-static const float CULTMATH_SNOISE_HESSIAN = 56.050385;
+static const float CULTMATH_SNOISE_HESSIAN = 55.642143;
// An upper bound on the operator norm of the third-derivative tensor of cultmath_snoise(float3), the
// next order after CULTMATH_SNOISE_HESSIAN; provenance in math.Span.cs (SNOISE_THIRD).
-static const float CULTMATH_SNOISE_THIRD = 1.0;
+static const float CULTMATH_SNOISE_THIRD = 536.9152;
float3 cultmath_af_point(float value) { return float3(value, 0.0, 0.0); }
float3 cultmath_af_symbol(float x0, float a) { return float3(x0, a, 0.0); }