scirs2_spatial/distance/
euclideandistance_traits.rs1use scirs2_core::numeric::Float;
13
14use super::functions::prefetch_read;
15use super::functions::Distance;
16use super::types::EuclideanDistance;
17
18impl<T: Float> Default for EuclideanDistance<T> {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23
24impl<T: Float + Send + Sync> Distance<T> for EuclideanDistance<T> {
25 fn distance(&self, a: &[T], b: &[T]) -> T {
26 if a.len() != b.len() {
27 return T::nan();
28 }
29 if let Some(result) = Self::try_simd_f64(a, b) {
30 return result;
31 }
32 if let Some(result) = Self::try_simd_f32(a, b) {
33 return result;
34 }
35 let len = a.len();
36 let mut sum = T::zero();
37 let chunks = len / 4;
38 #[allow(clippy::needless_range_loop)]
39 for i in 0..chunks {
40 let base = i * 4;
41 if base + 8 < len {
42 let end_idx = (base + 8).min(len);
43 prefetch_read(&a[base + 4..end_idx]);
44 prefetch_read(&b[base + 4..end_idx]);
45 if base + 16 < len {
46 let far_end = (base + 16).min(len);
47 prefetch_read(&a[base + 8..far_end]);
48 prefetch_read(&b[base + 8..far_end]);
49 }
50 }
51 let diff0 = a[base] - b[base];
52 let diff1 = a[base + 1] - b[base + 1];
53 let diff2 = a[base + 2] - b[base + 2];
54 let diff3 = a[base + 3] - b[base + 3];
55 let sq0 = diff0 * diff0;
56 let sq1 = diff1 * diff1;
57 let sq2 = diff2 * diff2;
58 let sq3 = diff3 * diff3;
59 let pair_sum0 = sq0 + sq1;
60 let pair_sum1 = sq2 + sq3;
61 let chunk_sum = pair_sum0 + pair_sum1;
62 sum = sum + chunk_sum;
63 }
64 for i in (chunks * 4)..len {
65 let diff = a[i] - b[i];
66 sum = sum + diff * diff;
67 }
68 sum.sqrt()
69 }
70 fn min_distance_point_rectangle(&self, point: &[T], mins: &[T], maxes: &[T]) -> T {
71 let mut sum = T::zero();
72 for i in 0..point.len() {
73 let coord = point[i];
74 let min_val = mins[i];
75 let max_val = maxes[i];
76 let clamped = coord.max(min_val).min(max_val);
77 let diff = coord - clamped;
78 sum = sum + diff * diff;
79 }
80 sum.sqrt()
81 }
82}