use std::iter::Sum;
use harness_algebra::{rings::Field, tensors::fixed::FixedVector};
use crate::{
definitions::{MetricSpace, NormedSpace},
set::Collection,
};
#[derive(Debug, Clone)]
pub struct Cloud<const N: usize, F: Field> {
points: Vec<FixedVector<N, F>>,
}
impl<F: Field, const N: usize> Cloud<N, F> {
pub const fn new(points: Vec<FixedVector<N, F>>) -> Self { Self { points } }
pub const fn points_ref(&self) -> &Vec<FixedVector<N, F>> { &self.points }
}
impl<const N: usize, F: Field + Copy + Sum<F>> Collection for Cloud<N, F> {
type Item = FixedVector<N, F>;
fn contains(&self, point: &Self::Item) -> bool { self.points.contains(point) }
fn is_empty(&self) -> bool { self.points.is_empty() }
}
impl<const N: usize, F: Field + Copy + Sum<F>> MetricSpace for Cloud<N, F> {
type Distance = F;
fn distance(point_a: Self::Item, point_b: Self::Item) -> Self::Distance {
<Self as NormedSpace>::norm(point_a - point_b)
}
}
impl<const N: usize, F: Field + Copy + Sum<F>> NormedSpace for Cloud<N, F> {
type Norm = F;
fn norm(point: Self::Item) -> Self::Norm { point.0.iter().map(|p| *p * *p).sum() }
}
#[cfg(test)]
mod tests {
#![allow(clippy::float_cmp)]
use super::*;
fn create_test_vector1() -> FixedVector<2, f64> { FixedVector([1.0, 2.0]) }
fn create_test_vector2() -> FixedVector<2, f64> { FixedVector([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<FixedVector<2, f64>> = 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, f64>::norm(v1), 5.0);
let v2 = create_test_vector2(); assert_eq!(Cloud::<2, f64>::norm(v2), 25.0);
}
#[test]
fn test_distance() {
let v1 = create_test_vector1(); let v2 = create_test_vector2(); assert_eq!(Cloud::<2, f64>::distance(v1, v2), 8.0);
}
}