use std::ops::{Sub, Div, DivAssign}; use {Num}; pub trait Distance { type Output: Num; fn distance(&self, other: &Self) -> Self::Output; } pub trait Norm: Sized { type Output: Num; fn norm(&self) -> ::Output; } pub fn normalize + DivAssign, R: Num>(v: &mut T) { *v /= v.norm(); } pub fn normalized + Div, R: Num>(v: T) -> T { let norm = v.norm(); v / norm } impl> Distance for T{ type Output = ::Output; fn distance(&self, other: &Self) -> ::Output { (*self - *other).norm() } } macro_rules! norm_impl_self { ($($t:ty)*) => ($( impl Norm for $t { type Output = Self; fn norm(&self) -> ::Output { *self } } )*) } macro_rules! norm_impl_abs { ($($t:ty)*) => ($( impl Norm for $t { type Output = Self; fn norm(&self) -> ::Output { self.abs() } } )*) } macro_rules! norm_impl_unsigned_output { ($($t:ty, $out:ty);*) => ($( impl Norm for $t { type Output = $out; fn norm(&self) -> ::Output { self.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); #[cfg(has_i128)] norm_impl_unsigned_output!(i128, u128); #[cfg(has_u128)] norm_impl_self!(u128);