#[cfg(not(feature = "std"))]
#[allow(unused_imports)]
use num_traits::Float;
#[must_use]
pub fn score_seen(depth: usize, mass: u64) -> f64 {
if mass == 0 {
return 0.0;
}
#[allow(clippy::cast_precision_loss)]
let denom = depth as f64 + (mass as f64).log2();
if denom > 0.0 { 1.0 / denom } else { 0.0 }
}
#[must_use]
pub fn score_unseen(depth: usize, mass: u64) -> f64 {
if mass == 0 {
return 0.0;
}
#[allow(clippy::cast_precision_loss)]
let v = depth as f64 + (mass as f64).log2();
v.max(0.0)
}
#[must_use]
pub fn damp(mass: u64, total_mass: u64) -> f64 {
if total_mass <= 1 || mass == 0 {
return 1.0;
}
#[allow(clippy::cast_precision_loss)]
let ln_total = (total_mass as f64).ln();
if ln_total <= 0.0 {
return 1.0;
}
#[allow(clippy::cast_precision_loss)]
let ratio = (mass as f64).ln() / ln_total;
1.0 / (1.0 + ratio)
}
#[must_use]
pub fn normalizer(total_mass: u64) -> f64 {
if total_mass <= 1 {
return 0.0;
}
#[allow(clippy::cast_precision_loss)]
{
(total_mass as f64).log2()
}
}
#[cfg(test)]
#[allow(clippy::float_cmp)] mod tests {
use super::*;
#[test]
fn score_seen_handles_zero_mass() {
assert_eq!(score_seen(0, 0), 0.0);
assert_eq!(score_seen(7, 0), 0.0);
}
#[test]
fn score_seen_handles_degenerate_root() {
assert_eq!(score_seen(0, 1), 0.0);
}
#[test]
fn score_seen_returns_inverse() {
assert!((score_seen(2, 4) - 0.25).abs() < 1e-12);
}
#[test]
fn score_unseen_handles_zero_mass() {
assert_eq!(score_unseen(0, 0), 0.0);
}
#[test]
fn score_unseen_returns_sum() {
assert!((score_unseen(3, 8) - 6.0).abs() < 1e-12);
}
#[test]
fn damp_clamps_for_total_one() {
assert_eq!(damp(1, 1), 1.0);
assert_eq!(damp(0, 5), 1.0);
assert_eq!(damp(0, 0), 1.0);
}
#[test]
fn damp_value_at_mass_equal_total() {
assert!((damp(4, 4) - 0.5).abs() < 1e-12);
}
#[test]
fn damp_value_for_small_mass() {
let d = damp(2, 4);
assert!((d - (1.0 / 1.5)).abs() < 1e-9);
}
#[test]
fn normalizer_zero_for_small_total() {
assert_eq!(normalizer(0), 0.0);
assert_eq!(normalizer(1), 0.0);
}
#[test]
fn normalizer_log2_otherwise() {
assert!((normalizer(4) - 2.0).abs() < 1e-12);
assert!((normalizer(256) - 8.0).abs() < 1e-12);
}
}