kdtree/
util.rs

1use num_traits::Float;
2
3pub fn distance_to_space<F, T>(p1: &[T], min_bounds: &[T], max_bounds: &[T], distance: &F) -> T
4where
5    F: Fn(&[T], &[T]) -> T,
6    T: Float,
7{
8    let mut p2 = vec![T::nan(); p1.len()];
9    for i in 0..p1.len() {
10        if p1[i] > max_bounds[i] {
11            p2[i] = max_bounds[i];
12        } else if p1[i] < min_bounds[i] {
13            p2[i] = min_bounds[i];
14        } else {
15            p2[i] = p1[i];
16        }
17    }
18    distance(p1, &p2[..])
19}
20
21#[cfg(test)]
22mod tests {
23    use super::distance_to_space;
24    use crate::distance::squared_euclidean;
25    use std::f64::{INFINITY, NEG_INFINITY};
26
27    #[test]
28    fn test_normal_distance_to_space() {
29        let dis = distance_to_space(&[0.0, 0.0], &[1.0, 1.0], &[2.0, 2.0], &squared_euclidean);
30        assert_eq!(dis, 2.0);
31    }
32
33    #[test]
34    fn test_distance_outside_inf() {
35        let dis = distance_to_space(&[0.0, 0.0], &[1.0, 1.0], &[INFINITY, INFINITY], &squared_euclidean);
36        assert_eq!(dis, 2.0);
37    }
38
39    #[test]
40    fn test_distance_inside_inf() {
41        let dis = distance_to_space(
42            &[2.0, 2.0],
43            &[NEG_INFINITY, NEG_INFINITY],
44            &[INFINITY, INFINITY],
45            &squared_euclidean,
46        );
47        assert_eq!(dis, 0.0);
48    }
49
50    #[test]
51    fn test_distance_inside_normal() {
52        let dis = distance_to_space(&[2.0, 2.0], &[0.0, 0.0], &[3.0, 3.0], &squared_euclidean);
53        assert_eq!(dis, 0.0);
54    }
55
56    #[test]
57    fn distance_to_half_space() {
58        let dis = distance_to_space(
59            &[-2.0, 0.0],
60            &[0.0, NEG_INFINITY],
61            &[INFINITY, INFINITY],
62            &squared_euclidean,
63        );
64        assert_eq!(dis, 4.0);
65    }
66}