Diffstat (limited to 'src/dumb.rs')
| -rw-r--r-- | src/dumb.rs | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/src/dumb.rs b/src/dumb.rs index da5e64d..8391042 100644 --- a/src/dumb.rs +++ b/src/dumb.rs @@ -1,4 +1,5 @@ use atools::prelude::*; +use lower::algebraic::math; pub trait Closest<const N: usize> { fn closest(&self, color: [f32; N]) -> (f32, [f32; N], u32); fn best(&self, color: [f32; N]) -> [f32; N] { @@ -10,42 +11,54 @@ pub trait Closest<const N: usize> { fn space(&self) -> f32; } +#[inline(always)] 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() + math! { + f.asub(with) + .map(|x| x*x) + .into_iter() + .fold(0.0, |acc, x| acc + x) + } } -#[no_mangle] -fn closeer(x: [f32; 4], p: &[[f32; 4]]) -> [f32; 4] { - p.best(x) +#[inline(always)] +fn minwby<T: Copy, U: PartialOrd>(max: T, x: impl Iterator<Item = T>, extractor: fn(T) -> U) -> T { + x.fold(max, |acc, x| { + if extractor(acc) > extractor(x) { + x + } else { + acc + } + }) } -impl<const N: usize> Closest<N> for &[[f32; N]] { +impl<'a, const N: usize> Closest<N> for super::pal<'a, N> { /// o(nn) - #[inline] fn closest(&self, color: [f32; N]) -> (f32, [f32; N], u32) { - (0..) - .zip(*self) - .map(|(i, &x)| (euclidean_distance(x, color), x, i)) - .min_by(|x, y| x.0.total_cmp(&y.0)) - .unwrap() + minwby( + (f32::MAX, [0.0; N], 0), + (0..) + .zip(&**self) + .map(|(i, &x)| (euclidean_distance(x, color), x, i)), + |x| x.0, + ) } /// o(nn) + #[cold] fn space(&self) -> f32 { + math! { self.iter() .enumerate() .map(|(i, &x)| { - self.iter() + minwby(f32::MAX, self.iter() .enumerate() .filter(|&(j, _)| j != i) - .map(|(_, &y)| euclidean_distance(y, x)) - .min_by(|a, b| a.total_cmp(b)) - .unwrap() - .sqrt() + .map(|(_, &y)| euclidean_distance(y, x)), + std::convert::identity).sqrt() }) - .fold(0.0, |x, y| std::intrinsics::fadd_algebraic(x, y)) + .fold(0.0, |x, y| x + y) / self.len() as f32 + } } } |