From 82df66b852fd2e16f3ab5cc0b4bbf32034ee49db Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 28 May 2020 14:41:22 -0400 Subject: coords: Implement coordinate spaces --- src/coords.rs | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ 2 files changed, 115 insertions(+) create mode 100644 src/coords.rs (limited to 'src') diff --git a/src/coords.rs b/src/coords.rs new file mode 100644 index 0000000..c43b7e9 --- /dev/null +++ b/src/coords.rs @@ -0,0 +1,113 @@ +//! Coordinate spaces. + +use crate::distance::{Distance, Value}; + +/// A coordinate space. +pub trait Coordinates { + /// The type of individual coordinates. + type Value: Value; + + /// Get the number of dims this point has. + fn dims(&self) -> usize; + + /// Get the `i`th coordinate of this point. + fn coord(&self, i: usize) -> Self::Value; + + /// Create a vector with this point's coordinates as values. + fn as_vec(&self) -> Vec { + let len = self.dims(); + let mut vec = Vec::with_capacity(len); + for i in 0..len { + vec.push(self.coord(i)); + } + vec + } +} + +/// [Coordinates] implementation for slices. +impl Coordinates for [T] { + type Value = T; + + fn dims(&self) -> usize { + self.len() + } + + fn coord(&self, i: usize) -> T { + self[i] + } +} + +/// [Coordinates] implementation for arrays. +macro_rules! array_coordinates { + ($n:expr) => ( + impl Coordinates for [T; $n] { + type Value = T; + + fn dims(&self) -> usize { + $n + } + + fn coord(&self, i: usize) -> T { + self[i] + } + } + ); +} + +array_coordinates!(1); +array_coordinates!(2); +array_coordinates!(3); +array_coordinates!(4); +array_coordinates!(5); +array_coordinates!(6); +array_coordinates!(7); +array_coordinates!(8); + +/// [Coordinates] implemention for vectors. +impl Coordinates for Vec { + type Value = T; + + fn dims(&self) -> usize { + self.len() + } + + fn coord(&self, i: usize) -> T { + self[i] + } +} + +/// Blanket [Coordinates] implementation for references. +impl Coordinates for &T { + type Value = T::Value; + + fn dims(&self) -> usize { + (*self).dims() + } + + fn coord(&self, i: usize) -> Self::Value { + (*self).coord(i) + } +} + +/// Types that support computing distances to raw slices of coordinates. +pub trait CoordinateProximity { + type Distance: Distance; + + /// Compute the distance to a point specified by its coordinates. + fn distance_to_coords(&self, coords: &[T]) -> Self::Distance; +} + +/// Blanket [CoordinateProximity] implementation for references. +impl, U> CoordinateProximity for &T { + type Distance = T::Distance; + + fn distance_to_coords(&self, coords: &[U]) -> Self::Distance { + (*self).distance_to_coords(coords) + } +} + +/// Marker trait for coordinate proximities that are [metrics][crate::distance::Metric]. +pub trait CoordinateMetric: CoordinateProximity {} + +/// Blanket [CoordinateMetric] implementation for references. +impl, U> CoordinateMetric for &T {} diff --git a/src/lib.rs b/src/lib.rs index 8b0c32b..1532211 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,8 @@ //! //! [nearest neighbor search]: https://en.wikipedia.org/wiki/Nearest_neighbor_search +pub mod coords; pub mod distance; +pub use coords::Coordinates; pub use distance::{Distance, Metric, Proximity}; -- cgit v1.2.3