use crate::prelude::Random;
use std::sync::Arc;
#[derive(Clone)]
pub struct Noise {
probability: f64,
range: (f64, f64),
is_addition: bool,
random: Arc<dyn Random + Send + Sync>,
}
impl Noise {
pub fn new_with_addition(probability: f64, range: (f64, f64), random: Arc<dyn Random + Send + Sync>) -> Self {
Self { probability, range, is_addition: true, random }
}
pub fn new_with_ratio(probability: f64, range: (f64, f64), random: Arc<dyn Random + Send + Sync>) -> Self {
Self { probability, range, is_addition: false, random }
}
pub fn generate_multi<'a, Iter: Iterator<Item = f64> + 'a>(
&'a self,
values: Iter,
) -> impl Iterator<Item = f64> + 'a {
values.map(|value| value + self.generate(value))
}
pub fn generate(&self, value: f64) -> f64 {
if self.random.is_hit(self.probability) {
if value == 0. {
self.random.uniform_real(self.range.0, self.range.1)
} else {
value * self.random.uniform_real(self.range.0, self.range.1) + if self.is_addition { value } else { 0. }
}
} else {
value
}
}
pub fn random(&self) -> &(dyn Random + Send + Sync) {
self.random.as_ref()
}
}