use num::Float;
use rand::prelude::*;
use rand_distr::{uniform::SampleUniform, Uniform};
use core::fmt::Debug;
pub type Custom<'a, F, R> = Box<dyn Fn(F, F, &Uniform<F>, &mut R) -> bool + 'a>;
pub enum APF<'a, F, R>
where
F: Float + SampleUniform,
R: Rng,
{
Metropolis,
Custom {
f: Custom<'a, F, R>,
},
}
impl<'a, F, R> APF<'a, F, R>
where
F: Float + SampleUniform + Debug,
R: Rng,
{
#[allow(clippy::arithmetic_side_effects)]
pub fn accept(&self, diff: F, t: F, uni: &Uniform<F>, rng: &mut R) -> bool {
match *self {
APF::Metropolis => {
diff <= F::zero() || uni.sample(rng) < F::min(F::exp(-diff / t), F::one())
}
APF::Custom { ref f } => f(diff, t, uni, rng),
}
}
}