scirs2_spatial/distance/
types.rs1use scirs2_core::ndarray::{Array2, ArrayView1};
6use scirs2_core::numeric::Float;
7use scirs2_core::simd_ops::SimdUnifiedOps;
8use std::marker::PhantomData;
9
10#[repr(align(64))]
11#[repr(C)]
12#[derive(Debug, Clone)]
13pub struct CacheAlignedBuffer<T> {
14 data: Vec<T>,
15}
16impl<T> CacheAlignedBuffer<T> {
17 #[inline(always)]
18 #[must_use]
19 pub fn new_with_capacity(capacity: usize) -> Self {
20 Self {
21 data: Vec::with_capacity(capacity),
22 }
23 }
24 #[inline(always)]
25 #[must_use]
26 pub fn as_slice(&self) -> &[T] {
27 &self.data
28 }
29 #[inline(always)]
30 #[must_use]
31 pub fn as_mut_slice(&mut self) -> &mut [T] {
32 &mut self.data
33 }
34 #[inline(always)]
35 pub fn push(&mut self, value: T) {
36 self.data.push(value);
37 }
38 #[inline(always)]
39 #[must_use]
40 pub fn len(&self) -> usize {
41 self.data.len()
42 }
43 #[inline(always)]
44 pub fn resize(&mut self, new_len: usize, value: T)
45 where
46 T: Clone,
47 {
48 self.data.resize(new_len, value);
49 }
50}
51#[derive(Clone, Debug)]
53pub struct ManhattanDistance<T: Float>(PhantomData<T>);
54impl<T: Float> ManhattanDistance<T> {
55 pub fn new() -> Self {
57 ManhattanDistance(PhantomData)
58 }
59 #[inline]
61 pub(super) fn try_simd_f64(a: &[T], b: &[T]) -> Option<T> {
62 if std::mem::size_of::<T>() != std::mem::size_of::<f64>() {
63 return None;
64 }
65 unsafe {
66 let a_ptr = a.as_ptr() as *const f64;
67 let b_ptr = b.as_ptr() as *const f64;
68 let len = a.len();
69 let a_slice = std::slice::from_raw_parts(a_ptr, len);
70 let b_slice = std::slice::from_raw_parts(b_ptr, len);
71 let a_view = ArrayView1::from(a_slice);
72 let b_view = ArrayView1::from(b_slice);
73 let result = f64::simd_distance_manhattan(&a_view, &b_view);
74 let result_ptr = &result as *const f64 as *const T;
75 Some(*result_ptr)
76 }
77 }
78 #[inline]
80 pub(super) fn try_simd_f32(a: &[T], b: &[T]) -> Option<T> {
81 if std::mem::size_of::<T>() != std::mem::size_of::<f32>() {
82 return None;
83 }
84 unsafe {
85 let a_ptr = a.as_ptr() as *const f32;
86 let b_ptr = b.as_ptr() as *const f32;
87 let len = a.len();
88 let a_slice = std::slice::from_raw_parts(a_ptr, len);
89 let b_slice = std::slice::from_raw_parts(b_ptr, len);
90 let a_view = ArrayView1::from(a_slice);
91 let b_view = ArrayView1::from(b_slice);
92 let result = f32::simd_distance_manhattan(&a_view, &b_view);
93 let result_ptr = &result as *const f32 as *const T;
94 Some(*result_ptr)
95 }
96 }
97}
98#[derive(Clone, Debug)]
100pub struct MinkowskiDistance<T: Float> {
101 pub(super) p: T,
102 phantom: PhantomData<T>,
103}
104impl<T: Float> MinkowskiDistance<T> {
105 pub fn new(p: T) -> Self {
115 MinkowskiDistance {
116 p,
117 phantom: PhantomData,
118 }
119 }
120}
121#[derive(Clone, Debug)]
123pub struct EuclideanDistance<T: Float>(PhantomData<T>);
124impl<T: Float> EuclideanDistance<T> {
125 pub fn new() -> Self {
127 EuclideanDistance(PhantomData)
128 }
129 #[inline]
131 pub(super) fn try_simd_f64(a: &[T], b: &[T]) -> Option<T> {
132 if std::mem::size_of::<T>() != std::mem::size_of::<f64>() {
133 return None;
134 }
135 unsafe {
136 let a_ptr = a.as_ptr() as *const f64;
137 let b_ptr = b.as_ptr() as *const f64;
138 let len = a.len();
139 let a_slice = std::slice::from_raw_parts(a_ptr, len);
140 let b_slice = std::slice::from_raw_parts(b_ptr, len);
141 let a_view = ArrayView1::from(a_slice);
142 let b_view = ArrayView1::from(b_slice);
143 let result = f64::simd_distance_euclidean(&a_view, &b_view);
144 let result_ptr = &result as *const f64 as *const T;
145 Some(*result_ptr)
146 }
147 }
148 #[inline]
150 pub(super) fn try_simd_f32(a: &[T], b: &[T]) -> Option<T> {
151 if std::mem::size_of::<T>() != std::mem::size_of::<f32>() {
152 return None;
153 }
154 unsafe {
155 let a_ptr = a.as_ptr() as *const f32;
156 let b_ptr = b.as_ptr() as *const f32;
157 let len = a.len();
158 let a_slice = std::slice::from_raw_parts(a_ptr, len);
159 let b_slice = std::slice::from_raw_parts(b_ptr, len);
160 let a_view = ArrayView1::from(a_slice);
161 let b_view = ArrayView1::from(b_slice);
162 let result = f32::simd_distance_euclidean(&a_view, &b_view);
163 let result_ptr = &result as *const f32 as *const T;
164 Some(*result_ptr)
165 }
166 }
167}
168#[derive(Clone, Debug)]
170pub struct ChebyshevDistance<T: Float>(PhantomData<T>);
171impl<T: Float> ChebyshevDistance<T> {
172 pub fn new() -> Self {
174 ChebyshevDistance(PhantomData)
175 }
176 #[inline]
178 pub(super) fn try_simd_f64(a: &[T], b: &[T]) -> Option<T> {
179 if std::mem::size_of::<T>() != std::mem::size_of::<f64>() {
180 return None;
181 }
182 unsafe {
183 let a_ptr = a.as_ptr() as *const f64;
184 let b_ptr = b.as_ptr() as *const f64;
185 let len = a.len();
186 let a_slice = std::slice::from_raw_parts(a_ptr, len);
187 let b_slice = std::slice::from_raw_parts(b_ptr, len);
188 let a_view = ArrayView1::from(a_slice);
189 let b_view = ArrayView1::from(b_slice);
190 let result = f64::simd_distance_chebyshev(&a_view, &b_view);
191 let result_ptr = &result as *const f64 as *const T;
192 Some(*result_ptr)
193 }
194 }
195 #[inline]
197 pub(super) fn try_simd_f32(a: &[T], b: &[T]) -> Option<T> {
198 if std::mem::size_of::<T>() != std::mem::size_of::<f32>() {
199 return None;
200 }
201 unsafe {
202 let a_ptr = a.as_ptr() as *const f32;
203 let b_ptr = b.as_ptr() as *const f32;
204 let len = a.len();
205 let a_slice = std::slice::from_raw_parts(a_ptr, len);
206 let b_slice = std::slice::from_raw_parts(b_ptr, len);
207 let a_view = ArrayView1::from(a_slice);
208 let b_view = ArrayView1::from(b_slice);
209 let result = f32::simd_distance_chebyshev(&a_view, &b_view);
210 let result_ptr = &result as *const f32 as *const T;
211 Some(*result_ptr)
212 }
213 }
214}