Diffstat (limited to 'src/dumb.rs')
-rw-r--r--src/dumb.rs47
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
}
}