use rand::Rng;
pub struct DifferentialPrivacyEngine;
impl DifferentialPrivacyEngine {
pub fn laplace_sample(scale: f64) -> f64 {
let mut rng = rand::thread_rng();
let u: f64 = rng.gen_range(-0.4999..0.4999);
let sgn: f64 = if u < 0.0 { -1.0 } else { 1.0 };
let abs_u: f64 = u.abs();
let term: f64 = (1.0 - 2.0 * abs_u).max(1e-10);
-scale * sgn * term.ln()
}
pub fn sanitize_metric(value: f64, epsilon: f64, sensitivity: f64) -> f64 {
if epsilon <= 0.0 {
return value;
}
let scale = sensitivity / epsilon;
let noise = Self::laplace_sample(scale);
(value + noise).max(0.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_differential_privacy_engine() {
let original_val = 100.0;
let epsilon = 1.0;
let sensitivity = 1.0;
let sanitized = DifferentialPrivacyEngine::sanitize_metric(original_val, epsilon, sensitivity);
assert!(sanitized >= 0.0);
assert!((sanitized - original_val).abs() < 25.0);
}
}