use crate::{Input, Node, Output, Register};
use rand::distributions::{Distribution, Standard};
use rand::rngs::ThreadRng;
use rand::Rng;
pub struct SampleAndHold<R, D, T> {
rng: R,
dist: D,
resample: Input<bool>,
output: Output<T>,
}
impl<T> Default for SampleAndHold<ThreadRng, Standard, T> {
fn default() -> Self {
Self::new()
}
}
impl<R, D, T> SampleAndHold<R, D, T> {
pub fn with_rng_dist(rng: R, dist: D) -> Self {
Self {
rng,
dist,
resample: Input::default(),
output: Output::default(),
}
}
}
impl<R, T> SampleAndHold<R, Standard, T> {
pub fn with_rng(rng: R) -> Self {
Self::with_rng_dist(rng, Standard)
}
}
impl<D, T> SampleAndHold<ThreadRng, D, T> {
pub fn with_dist(dist: D) -> Self {
Self::with_rng_dist(ThreadRng::default(), dist)
}
}
impl<T> SampleAndHold<ThreadRng, Standard, T> {
pub fn new() -> Self {
Self::with_rng(ThreadRng::default())
}
}
impl<R, D, T> Node for SampleAndHold<R, D, T>
where
R: Rng,
D: Distribution<T>,
T: 'static,
{
fn register(&self, r: &mut Register) {
r.input("resample", &self.resample);
r.output("output", &self.output);
}
fn process(&mut self) {
if self.output.is_used() {
if self.resample.get().unwrap_or_default() {
self.output.set(self.dist.sample(&mut self.rng));
}
}
}
fn reset(&mut self) {}
}