use crate::distance::{Distance, Value};
pub trait Coordinates {
type Value: Value;
fn dims(&self) -> usize;
fn coord(&self, i: usize) -> Self::Value;
fn as_vec(&self) -> Vec<Self::Value> {
let len = self.dims();
let mut vec = Vec::with_capacity(len);
for i in 0..len {
vec.push(self.coord(i));
}
vec
}
}
impl<T: Value> Coordinates for [T] {
type Value = T;
fn dims(&self) -> usize {
self.len()
}
fn coord(&self, i: usize) -> T {
self[i]
}
}
macro_rules! array_coordinates {
($n:expr) => {
impl<T: Value> 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);
impl<T: Value> Coordinates for Vec<T> {
type Value = T;
fn dims(&self) -> usize {
self.len()
}
fn coord(&self, i: usize) -> T {
self[i]
}
}
impl<T: ?Sized + Coordinates> Coordinates for &T {
type Value = T::Value;
fn dims(&self) -> usize {
(*self).dims()
}
fn coord(&self, i: usize) -> Self::Value {
(*self).coord(i)
}
}
pub trait CoordinateProximity<T> {
type Distance: Distance;
fn distance_to_coords(&self, coords: &[T]) -> Self::Distance;
}
impl<T: CoordinateProximity<U>, U> CoordinateProximity<U> for &T {
type Distance = T::Distance;
fn distance_to_coords(&self, coords: &[U]) -> Self::Distance {
(*self).distance_to_coords(coords)
}
}
pub trait CoordinateMetric<T>: CoordinateProximity<T> {}
impl<T: CoordinateMetric<U>, U> CoordinateMetric<U> for &T {}