use std::collections::HashMap;
use std::hash::Hash;
const BUCKETS_PER_DOUBLING: f32 = 2.0;
pub(crate) const RESORT_DISTANCE: f32 = 8.0;
pub(crate) fn order_holds(sorted_at: [f32; 3], eye: [f32; 3]) -> bool {
let squared: f32 = (0..3)
.map(|axis| (eye[axis] - sorted_at[axis]).powi(2))
.sum();
squared < RESORT_DISTANCE * RESORT_DISTANCE
}
pub(crate) fn distance_buckets<K: Eq + Hash + Copy>(
items: &[(K, f32)],
) -> Vec<u32> {
let mut nearest = HashMap::<K, f32>::new();
for &(key, distance) in items {
let entry = nearest.entry(key).or_insert(distance);
*entry = entry.min(distance);
}
items
.iter()
.map(|(key, _)| {
(nearest[key].max(1.0).log2() * BUCKETS_PER_DOUBLING) as u32
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn batches_sort_by_their_nearest_member_and_stay_together() {
let items = [(7, 40.0), (3, 12.5), (7, 2.2), (9, f32::NAN)];
let buckets = distance_buckets(&items);
assert_eq!(buckets, [2, 7, 2, 0]);
let mut order = [0, 1, 2, 3];
order.sort_by_key(|&index| (buckets[index], items[index].0));
assert_eq!(order, [3, 0, 2, 1]);
}
}