use cova_algebra::tensors::SVector;
use crate::{
definitions::{MetricSpace, NormedSpace},
set::Collection,
};
#[derive(Debug, Clone)]
pub struct Cloud<const N: usize> {
points: Vec<SVector<f64, N>>,
}
impl<const N: usize> Cloud<N> {
pub const fn new(points: Vec<SVector<f64, N>>) -> Self { Self { points } }
pub const fn points_ref(&self) -> &Vec<SVector<f64, N>> { &self.points }
}
impl<const N: usize> Collection for Cloud<N> {
type Item = SVector<f64, N>;
fn contains(&self, point: &Self::Item) -> bool { self.points.contains(point) }
fn is_empty(&self) -> bool { self.points.is_empty() }
}
impl<const N: usize> MetricSpace for Cloud<N> {
type Distance = f64;
fn distance(point_a: Self::Item, point_b: Self::Item) -> Self::Distance {
<Self as NormedSpace>::norm(point_a - point_b)
}
}
impl<const N: usize> NormedSpace for Cloud<N> {
type Norm = f64;
fn norm(point: Self::Item) -> Self::Norm { point.iter().map(|p| *p * *p).sum::<f64>().sqrt() }
}
#[cfg(test)]
mod tests {
#![allow(clippy::float_cmp)]
use super::*;
fn create_test_vector1() -> SVector<f64, 2> { SVector::from([1.0, 2.0]) }
fn create_test_vector2() -> SVector<f64, 2> { SVector::from([3.0, 4.0]) }
#[test]
fn test_new_cloud() {
let points = vec![create_test_vector1()];
let cloud = Cloud::new(points.clone());
assert_eq!(cloud.points, points);
}
#[test]
fn test_contains_point() {
let points = vec![create_test_vector1()];
let cloud = Cloud::new(points);
assert!(cloud.contains(&create_test_vector1()));
assert!(!cloud.contains(&create_test_vector2()));
}
#[test]
fn test_is_empty() {
let points: Vec<SVector<f64, 2>> = Vec::new();
let cloud = Cloud::new(points);
assert!(cloud.is_empty());
let points_non_empty = vec![create_test_vector1()];
let cloud_non_empty = Cloud::new(points_non_empty);
assert!(!cloud_non_empty.is_empty());
}
#[test]
fn test_norm() {
let v1 = create_test_vector1(); assert_eq!(Cloud::<2>::norm(v1), 5.0_f64.sqrt());
let v2 = create_test_vector2(); assert_eq!(Cloud::<2>::norm(v2), 25.0_f64.sqrt());
}
#[test]
fn test_distance() {
let v1 = create_test_vector1(); let v2 = create_test_vector2(); assert_eq!(Cloud::<2>::distance(v1, v2), 8.0_f64.sqrt());
}
}