Skip to content

Commit aeda1f4

Browse files
committed
hdr: full u32 range — wide sqrt, wide k·σ, overflow-safe kurtosis
Codex P2 on #328: - variance of u32 values reaches 2^62; take its square root in u128 (isqrt_u128) instead of narrowing to u32 first, which clamped σ at 65 535 (calibrate(&[0, u32::MAX]) now gives σ = 2 147 483 647). - form k·σ in u128 before the saturating subtraction. - kurtosis: exact when Σd⁴ and ·100 fit u128; otherwise a 16.16 fixed-point (d/σ)² path within one unit of the exact form, saturating only where the true value is astronomically large. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019HnekoM1EidTwQLS3oFVFm
1 parent 525055e commit aeda1f4

1 file changed

Lines changed: 117 additions & 22 deletions

File tree

‎src/hpc/rolling_floor.rs‎

Lines changed: 117 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,31 @@ pub fn isqrt_u32(n: u32) -> u32 {
8585
}
8686
}
8787

88+
/// Floor of `√n` for any `u128`, integer Newton iteration.
89+
///
90+
/// # Example
91+
///
92+
/// ```
93+
/// use ndarray::hpc::rolling_floor::isqrt_u128;
94+
/// assert_eq!(isqrt_u128(1 << 64), 1 << 32);
95+
/// assert_eq!(isqrt_u128(u128::MAX), u128::from(u64::MAX));
96+
/// ```
97+
pub fn isqrt_u128(n: u128) -> u128 {
98+
if n == 0 {
99+
return 0;
100+
}
101+
// Start >= floor(√n) so Newton descends monotonically; x ≤ 2^64 and
102+
// n / x ≤ 2^64, so x + n / x cannot overflow.
103+
let mut x = 1u128 << ((129 - n.leading_zeros()) / 2);
104+
loop {
105+
let x1 = (x + n / x) / 2;
106+
if x1 >= x {
107+
return x;
108+
}
109+
x = x1;
110+
}
111+
}
112+
88113
/// Rank `⌊per_10000 · len / 10000⌋`, clamped to the last index. `0` for an
89114
/// empty sample. The integer rank rule for every empirical lookup.
90115
///
@@ -227,19 +252,7 @@ impl ReservoirU32 {
227252
if sigma == 0 || self.samples.len() < 4 {
228253
return 300;
229254
}
230-
let n = self.samples.len() as u128;
231-
// u128: a fourth power of a u32 difference is below 2^128.
232-
let m4: u128 = self
233-
.samples
234-
.iter()
235-
.map(|&d| {
236-
let diff = u128::from(d.abs_diff(mu));
237-
diff * diff * diff * diff
238-
})
239-
.sum::<u128>()
240-
/ n;
241-
let s4 = u128::from(sigma).pow(4);
242-
u32::try_from(m4 * 100 / s4).unwrap_or(u32::MAX)
255+
kurtosis_x100_exact(&self.samples, mu, sigma).unwrap_or_else(|| kurtosis_x100_scaled(&self.samples, mu, sigma))
243256
}
244257

245258
/// Deterministic splitmix64-style hash that drives replacement.
@@ -352,7 +365,7 @@ impl EmpiricalShape {
352365
let m = moments_u32(&sorted);
353366
Some(Self {
354367
mu: saturate_u32(m.sum / u128::from(m.n)),
355-
sigma: isqrt_u32(saturate_u32(variance_floor(&m))),
368+
sigma: sqrt_u32(variance_floor(&m)),
356369
sorted,
357370
})
358371
}
@@ -498,7 +511,7 @@ impl RollingFloor {
498511
assert!(sample.len() > 1, "need at least 2 samples to calibrate");
499512
let moments = moments_u32(sample);
500513
let mu = saturate_u32(moments.sum / u128::from(moments.n));
501-
let sigma = isqrt_u32(saturate_u32(centred_on_floor_mean(&moments) / u128::from(moments.n))).max(1);
514+
let sigma = sqrt_u32(centred_on_floor_mean(&moments) / u128::from(moments.n)).max(1);
502515
let mut floor = Self::from_params_and_moments(mu, sigma, moments);
503516
for &d in sample {
504517
floor.reservoir.observe(d);
@@ -564,7 +577,7 @@ impl RollingFloor {
564577
/// The periodic path: drift first; the shape only when there is none.
565578
fn checkpoint(&mut self) -> Option<FloorShift> {
566579
let run_mu = saturate_u32(self.moments.sum / u128::from(self.moments.n));
567-
let run_sigma = isqrt_u32(saturate_u32(variance_floor(&self.moments))).max(1);
580+
let run_sigma = sqrt_u32(variance_floor(&self.moments)).max(1);
568581

569582
let mu_drift = run_mu.abs_diff(self.anchor_mu);
570583
let sigma_drift = run_sigma.abs_diff(self.anchor_sigma);
@@ -606,10 +619,7 @@ impl RollingFloor {
606619
if self.moments.n == 0 {
607620
return None;
608621
}
609-
Some((
610-
saturate_u32(self.moments.sum / u128::from(self.moments.n)),
611-
isqrt_u32(saturate_u32(variance_floor(&self.moments))),
612-
))
622+
Some((saturate_u32(self.moments.sum / u128::from(self.moments.n)), sqrt_u32(variance_floor(&self.moments))))
613623
}
614624

615625
/// The coordinates a threshold is located in: the running ones, or the
@@ -621,7 +631,9 @@ impl RollingFloor {
621631

622632
fn locate(&self, level: SigmaLevel, mu: u32, sigma: u32) -> u32 {
623633
match &self.shape {
624-
Shape::Gaussian => mu.saturating_sub(level.quarters() * sigma / 4),
634+
Shape::Gaussian => {
635+
saturate_u32(u128::from(mu).saturating_sub(u128::from(level.quarters()) * u128::from(sigma) / 4))
636+
}
625637
Shape::Empirical(e) => e.locate(level, mu, sigma),
626638
}
627639
}
@@ -692,6 +704,43 @@ impl RollingFloor {
692704
}
693705
}
694706

707+
/// `⌊100 · E[(X − μ)⁴] / σ⁴⌋` exactly, or `None` when an intermediate
708+
/// leaves `u128` (only for spreads far beyond any popcount width).
709+
fn kurtosis_x100_exact(samples: &[u32], mu: u32, sigma: u32) -> Option<u32> {
710+
let mut sum: u128 = 0;
711+
for &d in samples {
712+
let diff = u128::from(d.abs_diff(mu));
713+
sum = sum.checked_add((diff * diff).checked_mul(diff * diff)?)?;
714+
}
715+
let m4 = sum / samples.len() as u128;
716+
Some(u32::try_from(m4.checked_mul(100)? / u128::from(sigma).pow(4)).unwrap_or(u32::MAX))
717+
}
718+
719+
/// The same ratio from per-sample `(d/σ)²` in 16.16 fixed point, used only
720+
/// when the exact form overflows. Where it would overflow too the kurtosis is
721+
/// astronomically large and saturates at `u32::MAX`. Agrees with the exact
722+
/// form to within one unit where both fit.
723+
fn kurtosis_x100_scaled(samples: &[u32], mu: u32, sigma: u32) -> u32 {
724+
let s2 = u128::from(sigma) * u128::from(sigma);
725+
let mut sum: u128 = 0;
726+
for &d in samples {
727+
let diff = u128::from(d.abs_diff(mu));
728+
let r = ((diff * diff) << 16) / s2; // (d/σ)², 16 fractional bits
729+
match r.checked_mul(r).and_then(|t| sum.checked_add(t)) {
730+
Some(v) => sum = v,
731+
None => return u32::MAX,
732+
}
733+
}
734+
let m4 = sum / samples.len() as u128; // 32 fractional bits
735+
u32::try_from(m4.saturating_mul(100) >> 32).unwrap_or(u32::MAX)
736+
}
737+
738+
/// `⌊√n⌋` for a variance of `u32` values. That variance is below `2^62`, so
739+
/// the root fits `u32`.
740+
fn sqrt_u32(n: u128) -> u32 {
741+
saturate_u32(isqrt_u128(n))
742+
}
743+
695744
fn saturate_u32(x: u128) -> u32 {
696745
u32::try_from(x).unwrap_or(u32::MAX)
697746
}
@@ -919,6 +968,52 @@ mod tests {
919968
}
920969
}
921970

971+
/// The full `u32` range: σ above 65 535, `k·σ` above `u32`, fourth-power
972+
/// sums above `u128` — none may clamp, wrap or panic.
973+
#[test]
974+
fn full_u32_range_does_not_clamp_or_overflow() {
975+
const Q: u32 = u32::MAX / 2; // 2 147 483 647
976+
// Variance of {0, MAX} is Q² + Q (floor); its root is Q, not 65 535.
977+
let f = RollingFloor::calibrate(&[0, u32::MAX]);
978+
assert_eq!((f.mu(), f.sigma()), (Q, Q));
979+
assert_eq!(f.coordinates(), Some((Q, Q)));
980+
let e = EmpiricalShape::from_sample(&[0, u32::MAX]).unwrap();
981+
assert_eq!((e.mu(), e.sigma()), (Q, Q));
982+
983+
// k·σ is formed wide: 4 · 1.5e9 does not fit u32.
984+
let g = RollingFloor::from_params(u32::MAX, 1_500_000_000);
985+
assert_eq!(g.threshold(SigmaLevel(4)), u32::MAX - 1_500_000_000);
986+
assert_eq!(g.threshold(SigmaLevel(12)), 0, "saturates, never wraps");
987+
988+
// A two-point distribution has kurtosis exactly 1, i.e. 100.
989+
let mut r = ReservoirU32::new(1000);
990+
(0..1000u32).for_each(|i| r.observe(if i % 2 == 0 { 0 } else { u32::MAX }));
991+
assert!((99..=101).contains(&r.kurtosis(Q, Q)), "{}", r.kurtosis(Q, Q));
992+
}
993+
994+
/// Where the exact kurtosis fits, the overflow-safe path agrees with it
995+
/// to within one unit of the ×100 scale.
996+
#[test]
997+
fn kurtosis_fallback_matches_the_exact_path() {
998+
for (mu, sigma, seed) in [(8192, 64, 1), (5000, 3, 2), (100_000, 900, 3)] {
999+
let xs = normalish(1000, mu, sigma, seed);
1000+
let mut r = ReservoirU32::new(1000);
1001+
xs.iter().for_each(|&d| r.observe(d));
1002+
let exact = kurtosis_x100_exact(r.samples(), mu, sigma).expect("fits");
1003+
let scaled = kurtosis_x100_scaled(r.samples(), mu, sigma);
1004+
assert!(exact.abs_diff(scaled) <= 1, "exact {exact} scaled {scaled}");
1005+
}
1006+
}
1007+
1008+
#[test]
1009+
fn isqrt_u128_is_floor_sqrt() {
1010+
for n in (0..100_000u128).chain([u128::MAX, u128::MAX - 1, (1 << 64) - 1, 1 << 64, (1 << 126) + 12345]) {
1011+
let r = isqrt_u128(n);
1012+
assert!(r.checked_mul(r).is_some_and(|sq| sq <= n), "n {n}");
1013+
assert!((r + 1).checked_mul(r + 1).is_none_or(|sq| sq > n), "n {n}");
1014+
}
1015+
}
1016+
9221017
#[test]
9231018
fn scalar_equals_singleton_batch() {
9241019
let xs = stream(5000, 8000, 300, 11);
@@ -1298,7 +1393,7 @@ mod tests {
12981393
m.observe(d);
12991394
if let Some((lmu, lsig)) = legacy.observe(d) {
13001395
let emu = saturate_u32(m.sum / u128::from(m.n));
1301-
let esig = isqrt_u32(saturate_u32(variance_floor(&m))).max(1);
1396+
let esig = sqrt_u32(variance_floor(&m)).max(1);
13021397
assert_eq!((emu, esig), (lmu, lsig), "mu {mu} sigma {sigma} n {}", m.n);
13031398
checked += 1;
13041399
}

0 commit comments

Comments
 (0)