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