use std::fmt::Debug;
#[derive(Debug)]
pub struct Log2Map {
min: f64,
max: f64,
min_log2: f64,
range_log2: f64,
range_log2_inv: f64,
}
impl Log2Map {
pub fn new(min: f64, max: f64) -> Self {
assert!(min > 0.0);
assert!(max > 0.0);
let min_log2 = min.log2();
let range_log2 = max.log2() - min_log2;
let range_log2_inv = if range_log2 <= 0.0 {
0.0
} else {
1.0 / range_log2
};
Self {
min,
max,
min_log2,
range_log2,
range_log2_inv,
}
}
pub fn normalize(&self, value: f64) -> f64 {
self.normalize_generic(value)
}
#[inline(always)]
fn normalize_generic(&self, value: f64) -> f64 {
if value <= self.min {
return 0.0;
};
if value >= self.max {
return 1.0;
};
(value.log2() - self.min_log2) * self.range_log2_inv
}
pub fn normalize_array(&self, in_values: &[f64], out_normalized: &mut [f64]) {
let min_len = std::cmp::min(in_values.len(), out_normalized.len());
let input = &in_values[..min_len];
let output = &mut out_normalized[..min_len];
for i in 0..min_len {
output[i] = self.normalize_generic(input[i]);
}
}
pub fn denormalize(&self, normalized: f64) -> f64 {
self.denormalize_generic(normalized)
}
#[inline(always)]
fn denormalize_generic(&self, normalized: f64) -> f64 {
if normalized <= 0.0 {
return self.min;
}
if normalized >= 1.0 {
return self.max;
}
2.0f64.powf((normalized * self.range_log2) + self.min_log2)
}
pub fn denormalize_array(&self, in_normalized: &[f64], out_values: &mut [f64]) {
let min_len = std::cmp::min(in_normalized.len(), out_values.len());
let input = &in_normalized[..min_len];
let output = &mut out_values[..min_len];
for i in 0..min_len {
output[i] = self.denormalize_generic(input[i]);
}
}
}