Diffstat (limited to 'src/dumb.rs')
| -rw-r--r-- | src/dumb.rs | 47 |
1 files changed, 33 insertions, 14 deletions
diff --git a/src/dumb.rs b/src/dumb.rs index c406fac..6f1a800 100644 --- a/src/dumb.rs +++ b/src/dumb.rs @@ -1,27 +1,46 @@ use atools::prelude::*; -pub trait Closest { - fn closest(&self, color: [f32; 4]) -> (f32, [f32; 4], usize); +pub trait Closest<const N: usize> { + fn closest(&self, color: [f32; N]) -> (f32, [f32; N], usize); + fn best(&self, color: [f32; N]) -> [f32; N] { + self.closest(color).1 + } + fn nearest(&self, color: [f32; N]) -> usize { + self.closest(color).2 + } + fn space(&self) -> f32; } -fn euclidean_distance(f: [f32; 4], with: [f32; 4]) -> f32 { - f.asub(with).map(|x| x * x).sum() +fn euclidean_distance<const N: usize>(f: [f32; N], with: [f32; N]) -> f32 { + f.asub(with) + .map(|x| std::intrinsics::fmul_algebraic(x, x)) + .sum() } -impl Closest for &[[f32; 4]] { - fn closest(&self, color: [f32; 4]) -> (f32, [f32; 4], usize) { +impl<const N: usize> Closest<N> for &[[f32; N]] { + /// o(nn) + fn closest(&self, color: [f32; N]) -> (f32, [f32; N], usize) { self.iter() .copied() .enumerate() .map(|(i, x)| (euclidean_distance(x, color), x, i)) .min_by(|x, y| x.0.total_cmp(&y.0)) .unwrap() - // let mut best = (euclidean_distance(self[0], color), self[0], 0); - // for (&c, i) in self[1..].iter().zip(1..) { - // let d = euclidean_distance(c, color); - // if d < best.0 { - // best = (d, c, i); - // } - // } - // best + } + + /// o(nn) + fn space(&self) -> f32 { + self.iter() + .enumerate() + .map(|(i, &x)| { + self.iter() + .enumerate() + .filter(|&(j, _)| j != i) + .map(|(_, &y)| euclidean_distance(y, x)) + .min_by(|a, b| a.total_cmp(b)) + .unwrap() + .sqrt() + }) + .fold(0.0, |x, y| std::intrinsics::fadd_algebraic(x, y)) + / self.len() as f32 } } |