diff --git a/src/dist.rs b/src/dist.rs new file mode 100644 index 0000000..516b754 --- /dev/null +++ b/src/dist.rs @@ -0,0 +1,73 @@ +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); \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 172e714..60a139a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,6 +48,7 @@ mod macros; pub mod bounds; pub mod cast; +pub mod dist; pub mod float; pub mod identities; pub mod int;