Skip to content

Commit 98d8515

Browse files
committed
examples/codec_mode_histogram: measure shipped codec mode split + RD curve
Drives the shipped hpc::codec rdo_select over synthetic fields across a coherence sweep (raster scan, causal N/W neighbours), reporting the actual %skip/merge/delta/escape histogram, bytes/cell, and mean distortion; plus a λ rate-distortion sweep on the weather-like field. Measured (256×256, 16-basin codebook): - coherent (exact basin) → 100% skip → 2.00 B/cell → 4.0× lossless - weather-like (smooth) → 85% delta / 13% merge → 2.98 B/cell → 2.68× lossless - incoherent in-range → 98% delta → 2.98 B/cell → 2.68× lossless - incoherent out-of-range→ 73% escape → 11.05 B/cell → 0.72× (regression) - λ sweep: 2.68× lossless (λ≥4) → 4.0× at meanDist 16.5 (λ=0 quantizes to basin) Findings: (1) continuous fields are Delta-floored at ~2.68×, not the 3.3× skip-dominant target, because smooth data lands NEAR basins not ON them; (2) Merge=3B=Delta=3B, so neighbour-coherence buys zero bytes — only Skip (2B) saves; (3) "no regression vs dense" fails when the codebook doesn't span the data. Read-before-write example; std/codec feature only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MLBnPuScZy6w9di2QEjsXM
1 parent ffb12fd commit 98d8515

1 file changed

Lines changed: 169 additions & 0 deletions

File tree

examples/codec_mode_histogram.rs

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
//! Codec mode-histogram probe — drives the SHIPPED `hpc::codec` RDO
2+
//! selector over synthetic fields of varying coherence and reports the
3+
//! actual %skip/merge/delta/escape mode histogram + bytes/cell.
4+
//!
5+
//! The point: HEVC-family compression is entirely a function of the
6+
//! DATA's coherence. This measures where different data lands, so the
7+
//! "3.3× / 10-50×" design targets can be read against a real mode split
8+
//! instead of assumed. Raster scan with causal N/W neighbours — exactly
9+
//! how a real encoder feeds Merge (E/S aren't decided yet).
10+
//!
11+
//! Run: `cargo run --release --example codec_mode_histogram --features codec`
12+
13+
use ndarray::hpc::codec::rdo::{rdo_select, RdoConfig, RdoContext};
14+
use ndarray::hpc::codec::{packed_byte_len, CellMode, LeafCu};
15+
16+
const W: usize = 256;
17+
const H: usize = 256;
18+
const N: usize = W * H;
19+
const NBASINS: i64 = 16;
20+
const STEP: i64 = 64; // basin values 0, 64, .. 960 — codebook spans [0, 960]
21+
22+
/// SplitMix64 — deterministic, dependency-free.
23+
struct Sm(u64);
24+
impl Sm {
25+
fn new(s: u64) -> Self {
26+
Self(s)
27+
}
28+
fn next(&mut self) -> u64 {
29+
self.0 = self.0.wrapping_add(0x9E37_79B9_7F4A_7C15);
30+
let mut z = self.0;
31+
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
32+
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
33+
z ^ (z >> 31)
34+
}
35+
fn range(&mut self, n: i64) -> i64 {
36+
(self.next() % n as u64) as i64
37+
}
38+
}
39+
40+
/// Nearest basin: index + its value. Codebook spans [0, (NBASINS-1)*STEP].
41+
fn basin_of(v: i64) -> (u16, i64) {
42+
let idx = ((v + STEP / 2).div_euclid(STEP)).clamp(0, NBASINS - 1);
43+
(idx as u16, idx * STEP)
44+
}
45+
46+
struct Report {
47+
hist: [usize; 4], // skip, merge, delta, escape
48+
total_bytes: usize,
49+
mean_distortion: f64, // reconstruction error, u8-quant units
50+
}
51+
52+
/// Encode `values` through the shipped RDO selector, raster order, causal
53+
/// N/W neighbours. Escape feasible (cursor supplied) so out-of-range δ is
54+
/// lossless. Bytes = leaf wire size + 8-byte escape payload per escape.
55+
fn encode(values: &[i64], cfg: &RdoConfig) -> Report {
56+
let mut leaves: Vec<LeafCu> = Vec::with_capacity(N);
57+
let mut hist = [0usize; 4];
58+
let mut bytes = 0usize;
59+
let mut dist_sum = 0u64;
60+
let mut escape_cursor = 0u32;
61+
62+
for y in 0..H {
63+
for x in 0..W {
64+
let v = values[y * W + x];
65+
let (basin_idx, basin_val) = basin_of(v);
66+
let delta = (v - basin_val) as i32;
67+
let north = if y > 0 { Some(&leaves[(y - 1) * W + x]) } else { None };
68+
let west = if x > 0 { Some(&leaves[y * W + (x - 1)]) } else { None };
69+
let ctx = RdoContext {
70+
basin_idx,
71+
delta_i32: delta,
72+
// [North, East, West, South] — E/S undecided in raster order
73+
neighbours: [north, None, west, None],
74+
};
75+
let choice = rdo_select(&ctx, cfg, Some(&mut escape_cursor));
76+
let m = choice.leaf.mode;
77+
hist[m as usize] += 1;
78+
bytes += packed_byte_len(m);
79+
if m == CellMode::Escape {
80+
bytes += 8; // full 64-bit value in the escape vector
81+
}
82+
dist_sum += choice.distortion as u64;
83+
leaves.push(choice.leaf);
84+
}
85+
}
86+
Report {
87+
hist,
88+
total_bytes: bytes,
89+
mean_distortion: dist_sum as f64 / N as f64,
90+
}
91+
}
92+
93+
fn print_row(name: &str, r: &Report) {
94+
let pct = |k: usize| 100.0 * r.hist[k] as f64 / N as f64;
95+
let bpc = r.total_bytes as f64 / N as f64;
96+
println!(
97+
" {name:<22} skip={:5.1}% merge={:5.1}% delta={:5.1}% escape={:5.1}% | {:.2} B/cell {:.2}× vs 8B meanDist={:.2}",
98+
pct(0),
99+
pct(1),
100+
pct(2),
101+
pct(3),
102+
bpc,
103+
8.0 / bpc,
104+
r.mean_distortion,
105+
);
106+
}
107+
108+
fn main() {
109+
let cfg = RdoConfig::default(); // λ = 16, fidelity-biased (design's realistic setting)
110+
println!("Shipped hpc::codec RDO selector — {W}×{H} = {N} cells, λ=16 (default), 16-basin codebook\n");
111+
112+
// (1) Coherent: flat 16×16 tiles, each tile sits exactly on a basin → δ=0.
113+
let mut a = vec![0i64; N];
114+
for y in 0..H {
115+
for x in 0..W {
116+
let tile = ((y / 16) * (W / 16) + (x / 16)) as i64;
117+
a[y * W + x] = (tile % NBASINS) * STEP; // exact basin value
118+
}
119+
}
120+
print_row("coherent (flat tiles)", &encode(&a, &cfg));
121+
122+
// (2) Weather-like: smooth low-frequency field, neighbours nearly equal,
123+
// small residuals off the nearest basin. The realistic estimate for
124+
// a correlated physical field (the whole point of the thread).
125+
let mut b = vec![0i64; N];
126+
for y in 0..H {
127+
for x in 0..W {
128+
let f = 480.0
129+
+ 400.0 * (x as f64 * 0.018).sin() * (y as f64 * 0.018).cos()
130+
+ 60.0 * (x as f64 * 0.09).sin();
131+
b[y * W + x] = f.round().clamp(0.0, 1023.0) as i64;
132+
}
133+
}
134+
print_row("weather-like (smooth)", &encode(&b, &cfg));
135+
136+
// (3) Incoherent, in codebook range: random in [0, 1024). No spatial
137+
// coherence, but δ always ≤ STEP/2 so Delta covers it (no escape).
138+
let mut rng = Sm::new(0xC0FFEE);
139+
let c: Vec<i64> = (0..N).map(|_| rng.range(1024)).collect();
140+
print_row("incoherent in-range", &encode(&c, &cfg));
141+
142+
// (4) Incoherent, OUT of codebook range: random in [0, 4096). Nearest
143+
// basin is often > i8 away → Escape → worst case (should exceed 8B,
144+
// the honest "codebook doesn't fit the data" failure mode).
145+
let mut rng2 = Sm::new(0xBADF00D);
146+
let d: Vec<i64> = (0..N).map(|_| rng2.range(4096)).collect();
147+
print_row("incoherent out-of-range", &encode(&d, &cfg));
148+
149+
println!(
150+
"\nDense baseline = 8 B/cell (raw u64). Skip=2 Merge=3 Delta=3 Escape=6+8payload bytes.\n\
151+
Read: the compression is exactly as large as the data is coherent; escape only\n\
152+
bites when the codebook doesn't span the data (row 4)."
153+
);
154+
155+
// λ sweep on the weather-like field — the rate-distortion curve. λ=0
156+
// accepts quantization-to-basin (Skip, 2B) for distortion; high λ keeps
157+
// it lossless (Delta, 3B). THIS is the actual "optimize" lever: how much
158+
// compression you buy past the lossless Delta floor for how much error.
159+
println!("\nλ sweep on weather-like field (rate-distortion curve — the tuning lever):");
160+
for (label, cfg) in [
161+
("λ=0 (rate-only)", RdoConfig::RATE_ONLY),
162+
("λ=1", RdoConfig::from_lambda_q8(1 << 8)),
163+
("λ=4", RdoConfig::from_lambda_q8(4 << 8)),
164+
("λ=16 (default)", RdoConfig::default()),
165+
("λ=∞ (lossless)", RdoConfig::LOSSLESS),
166+
] {
167+
print_row(label, &encode(&b, &cfg));
168+
}
169+
}

0 commit comments

Comments
 (0)