use super::{DistFn, KnownDist};
#[derive(Copy, Clone)]
pub struct SignedDist;
macro_rules! impl_signed_dist {
($($ty:ty),*) => (
$(
impl DistFn<$ty> for SignedDist {
fn dist(&self, left: &$ty, right: &$ty) -> u64 {
(left - right).abs() as u64
}
}
impl KnownDist for $ty {
type DistFn = SignedDist;
fn dist_fn() -> SignedDist { SignedDist }
}
)*
)
}
impl_signed_dist! { i8, i16, i32, i64, isize }
#[derive(Copy, Clone)]
pub struct UnsignedDist;
macro_rules! impl_unsigned_dist {
($($ty:ty),*) => (
$(
impl DistFn<$ty> for UnsignedDist {
fn dist(&self, left: &$ty, right: &$ty) -> u64 {
let dist = if left < right { left - right } else { right - left };
dist as u64
}
}
impl KnownDist for $ty {
type DistFn = UnsignedDist;
fn dist_fn() -> UnsignedDist { UnsignedDist }
}
)*
)
}
impl_unsigned_dist! { u8, u16, u32, u64, usize }
#[derive(Copy, Clone)]
pub struct FloatDist;
#[derive(Copy, Clone)]
pub struct ScaledFloatDist<T>(pub T);
macro_rules! impl_float_dist {
($($ty:ty),*) => (
$(
impl DistFn<$ty> for FloatDist {
fn dist(&self, left: &$ty, right: &$ty) -> u64 {
(left - right).abs().round() as u64
}
}
impl KnownDist for $ty {
type DistFn = FloatDist;
fn dist_fn() -> FloatDist { FloatDist }
}
impl DistFn<$ty> for ScaledFloatDist<$ty> {
fn dist(&self, left: &$ty, right: &$ty) -> u64 {
((left - right) * self.0).abs().round() as u64
}
}
)*
)
}
impl_float_dist! { f32, f64 }