1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
//! See the [Crates.io page](https://crates.io/crates/space) for the README.
doctest!;
extern crate alloc;
pub use *;
use Zero;
use ;
/// This trait is implemented for metrics that form a metric space.
/// It is primarily used for keys in nearest neighbor searches.
/// When implementing this trait, it is recommended to choose the smallest unsigned integer that
/// represents your metric space, but you may also use a float so long as you wrap it in
/// a newtype that enforces the `Ord + Zero + Copy` trait bounds.
/// It is recommended to use
/// [`NoisyFloat`](https://docs.rs/noisy_float/0.2.0/noisy_float/struct.NoisyFloat.html)
/// for this purpose, as it implements the trait bound.
///
/// It is important that all metrics that implement this trait satisfy
/// the [triangle inequality](https://en.wikipedia.org/wiki/Triangle_inequality).
/// This requirement basically means that the sum of distances that start
/// at a point A and end at a point B can never be less than the distance
/// from A to B directly. Note that the metric is required to be an unsigned integer,
/// as distances can only be positive and must be fully ordered.
/// It is also required that two overlapping points (the same point in space) must return
/// a distance of [`Zero::zero`].
///
/// Floating point numbers can be converted to integer metrics by being interpreted as integers by design,
/// although some special patterns (like NaN) do not fit into this model. To be interpreted as an unsigned
/// integer, the float must be positive zero, subnormal, normal, or positive infinity. Any NaN needs
/// to be dealt with before converting into a metric, as they do NOT satisfy the triangle inequality,
/// and will lead to errors. You may want to check for positive infinity as well depending on your use case.
/// You must remove NaNs if you convert to integers, but you must also remove NaNs if you use an ordered
/// wrapper like [`NoisyFloat`](https://docs.rs/noisy_float/0.2.0/noisy_float/struct.NoisyFloat.html).
/// Be careful if you use a wrapper like
/// [`FloatOrd`](https://docs.rs/float-ord/0.3.2/float_ord/struct.FloatOrd.html) which does not
/// force you to remove NaNs. When implementing a metric, you must be sure that NaNs are not allowed, because
/// they may cause nearest neighbor algorithms to panic.
///
/// ## Example
///
/// ```
/// use pgat::ReferenceProxy;
///
/// #[derive(Copy, Clone, Default)]
/// struct AbsDiff;
///
/// impl space::Metric<ReferenceProxy<f64>> for AbsDiff {
/// type Unit = u64;
///
/// fn distance(&self, &a: &f64, &b: &f64) -> Self::Unit {
/// let delta = (a - b).abs();
/// debug_assert!(!delta.is_nan());
/// delta.to_bits()
/// }
/// }
/// ```
pub type MetricUnit<M, P> = Unit;
/// Implement this trait on data structures (or wrappers) which perform spatial searches.
///
/// Note that [`ApproximateSpace`] encompasses both exact and approximate searches.
/// Approximate searches may not always return the actual nearest neighbors or the entire set of neighbors in a region.
/// Returning the exact set of neighbors that belong in the query results is also known as 100% recall.
/// The amount of recall you get depends on the exact data structure and algorithm used to perform the search.
/// If you need exact nearest neighbor search (guaranteed 100% recall), instead depend on the [`ExactSpace`] trait.
/// This marker trait indicates that the methods provided by search algorithms are exact.
/// It has no further functionality at this time. Implement this on search data structures
/// that guarantee exact nearest neighbor search.
///
/// In this context, exact doesn't mean equidistant neighbors will always be returned, nor does it mean
/// that the same query will always return the same neighbors. However, it does mean that closer neighbors
/// will always be returned before farther neighbors under the ordering of the metric used.
/// Implement this trait on data structures (or wrappers) which perform KNN searches.
/// The data structure should maintain a key-value mapping between neighbour points and data
/// values. It must be able to output the distance between the query point and the neighbours,
/// which is included in the results.
///
/// Note that [`Knn`] encompasses both exact and approximate nearest neighbor searches.
/// Depend on the [`ExactSpace`] trait to ensure all searches are exact. See [`ExactSpace`] for more details.
/// Implement this trait on data structures (or wrappers) which perform n-sphere range queries.
/// The data structure should maintain a key-value mapping between neighbour points and data
/// values. It must be able to output the distance between the query point and the neighbours,
/// which is included in the results.
///
/// Note that [`NSphereRangeQuery`] encompasses both exact and approximate n-sphere searches.
/// Depend on the [`ExactSpace`] trait to ensure all searches are exact. See [`ExactSpace`] for more details.
/// Implement this trait on spatial containers that map points to values.
/// This function performs exact linear nearest neighbor search.
///
/// This may be useful specifically when implementing spatial containers
/// where you need to abstract over ProxyView types.