use crate::desc::Abs;
use crate::{Norm, Distance};
macro_rules! norm_impl_self {
($($t:ty)*) => ($(
impl Norm<Abs> for $t {
type Output = Self;
fn norm(&self, _desc: Abs) -> <Self as Norm<Abs>>::Output {
*self
}
}
impl Distance<Abs> for $t {
type Output = Self;
fn distance(&self, other: &Self, _desc: Abs) -> <Self as Distance<Abs>>::Output {
if self > other {
self - other
} else {
other - self
}
}
}
)*)
}
macro_rules! norm_impl_abs {
($($t:ty)*) => ($(
impl Norm<Abs> for $t {
type Output = Self;
fn norm(&self, _desc: Abs) -> <Self as Norm<Abs>>::Output {
self.abs()
}
}
impl Distance<Abs> for $t {
type Output = Self;
fn distance(&self, other: &Self, _desc: Abs) -> <Self as Distance<Abs>>::Output {
(self - other).abs()
}
}
)*)
}
macro_rules! norm_impl_unsigned_output {
($($t:ty, $out:ty);*) => ($(
impl Norm<Abs> for $t {
type Output = $out;
fn norm(&self, _desc: Abs) -> <Self as Norm<Abs>>::Output {
self.abs() as $out
}
}
impl Distance<Abs> for $t {
type Output = $out;
fn distance(&self, other: &Self, _desc: Abs) -> <Self as Distance<Abs>>::Output {
(self - other).abs() as $out
}
}
)*)
}
norm_impl_abs!(f32 f64);
norm_impl_unsigned_output!(i8, u8; i16, u16; i32, u32; i64, u64; isize, usize);
norm_impl_self!(u8 u16 u32 u64 usize);
norm_impl_unsigned_output!(i128, u128);
norm_impl_self!(u128);
#[cfg(test)]
mod tests {
use crate::desc::Abs;
use crate::{Distance, Norm};
#[test]
fn norm_floating_point() {
assert_eq!((-2.0f32).norm(Abs::new()), 2.0);
assert_eq!((-3.0f64).norm(Abs::new()), 3.0);
}
#[test]
fn distance_floating_point() {
assert_eq!((5.0f32).distance(&3.0, Abs::new()), 2.0);
assert_eq!((2.0f32).distance(&-3.0, Abs::new()), 5.0);
assert_eq!((1.0f64).distance(&4.0, Abs::new()), 3.0);
}
#[test]
fn norm_unsigned_integer() {
assert_eq!(2u8.norm(Abs::new()), 2);
assert_eq!(3u16.norm(Abs::new()), 3);
assert_eq!(4u32.norm(Abs::new()), 4);
assert_eq!(5u64.norm(Abs::new()), 5);
assert_eq!(6u128.norm(Abs::new()), 6);
assert_eq!(7usize.norm(Abs::new()), 7);
}
#[test]
fn distance_unsigned_integer() {
assert_eq!(2u8.distance(&4, Abs::new()), 2);
assert_eq!(3u16.distance(&4, Abs::new()), 1);
assert_eq!(4u32.distance(&4, Abs::new()), 0);
assert_eq!(5u64.distance(&4, Abs::new()), 1);
assert_eq!(6u128.distance(&4, Abs::new()), 2);
assert_eq!(7usize.distance(&4, Abs::new()), 3);
}
#[test]
fn norm_signed_integer() {
assert_eq!((-2i8).norm(Abs::new()), 2);
assert_eq!((3i16).norm(Abs::new()), 3);
assert_eq!((-4i32).norm(Abs::new()), 4);
assert_eq!((5i64).norm(Abs::new()), 5);
assert_eq!((-5i128).norm(Abs::new()), 5);
assert_eq!((6isize).norm(Abs::new()), 6);
}
#[test]
fn distance_signed_integer() {
assert_eq!(2i8.distance(&4, Abs::new()), 2);
assert_eq!(3i16.distance(&-4, Abs::new()), 7);
assert_eq!((-4i32).distance(&4, Abs::new()), 8);
assert_eq!((-5i64).distance(&-4, Abs::new()), 1);
assert_eq!(6i128.distance(&4, Abs::new()), 2);
assert_eq!(7isize.distance(&4, Abs::new()), 3);
}
}