From d30c8b9dd7524ad34892352617fd81ba4f8d10d6 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 24 Jun 2020 11:03:31 -0400 Subject: lp: Implement general L^p spaces --- src/lib.rs | 1 + src/lp.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/lp.rs diff --git a/src/lib.rs b/src/lib.rs index 0bbd835..43d9bf1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,6 +97,7 @@ pub mod euclid; pub mod exhaustive; pub mod hamming; pub mod kd; +pub mod lp; pub mod taxi; pub mod vp; diff --git a/src/lp.rs b/src/lp.rs new file mode 100644 index 0000000..cf65944 --- /dev/null +++ b/src/lp.rs @@ -0,0 +1,58 @@ +//! Lp spaces. + +use crate::coords::Coordinates; + +use num_traits::real::Real; +use num_traits::zero; + +/// A point in L1 space. +pub use crate::taxi::Taxicab as L1; + +/// Compute the L1 distance between two points. +pub use crate::taxi::taxicab_distance as l1_distance; + +/// A point in L2 space. +pub use crate::euclid::Euclidean as L2; +/// An L2 distance. +pub use crate::euclid::EuclideanDistance as L2Distance; + +/// Compute the L2 distance between two points. +pub use crate::euclid::euclidean_distance as l2_distance; + +/// A point in L space. +pub use crate::chebyshev::Chebyshev as Linf; + +/// Compute the L distance between two points. +pub use crate::chebyshev::chebyshev_distance as linf_distance; + +/// Compute the [Lp distance] between two points. +/// +/// [Lp distance]: https://en.wikipedia.org/wiki/Lp_space +pub fn lp_distance(p: T::Value, x: T, y: U) -> T::Value +where + T: Coordinates, + U: Coordinates, + T::Value: Real, +{ + debug_assert!(x.dims() == y.dims()); + + let mut sum: T::Value = zero(); + for i in 0..x.dims() { + sum += (x.coord(i) - y.coord(i)).abs().powf(p); + } + + sum.powf(p.recip()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_lp_distance() { + assert_eq!(l1_distance(&[0.0, 0.0], &[3.0, 4.0]), 7.0); + assert_eq!(l2_distance(&[0.0, 0.0], &[3.0, 4.0]), 5.0); + assert!(lp_distance(3.0, &[0.0, 0.0], &[3.0, 4.0]) < 5.0); + assert_eq!(linf_distance(&[0.0, 0.0], &[3.0, 4.0]), 4.0); + } +} -- cgit v1.2.3