pub mod sz;
pub mod zfp;
pub use self::{
sz::{SzCodec, SzConfig, SzMode},
zfp::{ZfpCodec, ZfpConfig, ZfpMode},
};
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FpMode {
FixedRate(usize),
FixedPrecision(usize),
FixedAccuracy(f64),
Reversible,
}
#[derive(Debug, Clone)]
pub struct FpStats {
pub min_value: f64,
pub max_value: f64,
pub mean: f64,
pub std_dev: f64,
pub compression_ratio: f64,
pub max_error: f64,
pub rmse: f64,
pub psnr: f64,
}
impl FpStats {
pub fn new() -> Self {
Self {
min_value: 0.0,
max_value: 0.0,
mean: 0.0,
std_dev: 0.0,
compression_ratio: 1.0,
max_error: 0.0,
rmse: 0.0,
psnr: 0.0,
}
}
pub fn compute(original: &[f64], decompressed: &[f64]) -> Self {
let mut stats = Self::new();
if original.is_empty() {
return stats;
}
stats.min_value = original[0];
stats.max_value = original[0];
let mut sum = 0.0;
for &val in original {
stats.min_value = stats.min_value.min(val);
stats.max_value = stats.max_value.max(val);
sum += val;
}
stats.mean = sum / original.len() as f64;
let mut var_sum = 0.0;
for &val in original {
let diff = val - stats.mean;
var_sum += diff * diff;
}
stats.std_dev = (var_sum / original.len() as f64).sqrt();
if original.len() == decompressed.len() {
let mut max_err: f64 = 0.0;
let mut mse: f64 = 0.0;
for (orig, decomp) in original.iter().zip(decompressed.iter()) {
let err = (orig - decomp).abs();
max_err = max_err.max(err);
mse += err * err;
}
stats.max_error = max_err;
stats.rmse = (mse / original.len() as f64).sqrt();
let range = stats.max_value - stats.min_value;
if mse > 0.0 && range > 0.0 {
stats.psnr = 20.0 * (range / stats.rmse).log10();
}
}
stats
}
}
impl Default for FpStats {
fn default() -> Self {
Self::new()
}
}