Skip to main content

roundtrip/
roundtrip.rs

1//! Encode a synthetic 2D field under each error-bound mode, decode it and
2//! check the bound.
3//!
4//! ```text
5//! cargo run --release -p cram-codec --example roundtrip
6//! ```
7use cram_codec::{decode, encode_f32, Config, Decoded, ErrorBound};
8
9fn main() {
10    let (h, w) = (128, 128);
11    let x: Vec<f32> = (0..h * w)
12        .map(|k| {
13            let (i, j) = ((k / w) as f32, (k % w) as f32);
14            (i * 0.05).sin() * (j * 0.03).cos() + 0.1 * (i * j * 1e-3).sin()
15        })
16        .collect();
17
18    for bound in [
19        ErrorBound::MaxAbs(1e-3),
20        ErrorBound::Rmse(1e-4),
21        ErrorBound::Psnr(60.0),
22    ] {
23        let (bytes, stats) = encode_f32(&x, &[h, w], &Config::new(bound));
24        let Decoded::F32 { data, .. } = decode(&bytes).expect("decode") else {
25            unreachable!("encoded f32")
26        };
27        let max_abs = x
28            .iter()
29            .zip(&data)
30            .map(|(a, b)| (a - b).abs() as f64)
31            .fold(0.0, f64::max);
32        let rmse = (x
33            .iter()
34            .zip(&data)
35            .map(|(a, b)| ((a - b) as f64).powi(2))
36            .sum::<f64>()
37            / x.len() as f64)
38            .sqrt();
39        println!(
40            "{bound:?}: {} bytes ({:.3} bits/value, ratio {:.1}x), max|err| {max_abs:.2e}, rmse {rmse:.2e}",
41            stats.bytes,
42            stats.bits_per_value,
43            32.0 / stats.bits_per_value
44        );
45        if let ErrorBound::MaxAbs(e) = bound {
46            assert!(max_abs <= e);
47        }
48    }
49}