1use core::{iter::Map, slice};
2
3use alloc::vec::{self, Vec};
4use pgat::{ProxyView, ReferenceProxy, View};
5
6use crate::{ApproximateSpace, ExactSpace, Knn, Metric, SpatialContainer, linear_nn};
7
8pub fn linear_knn<'a, 'b, M, P, V>(
13 metric: M,
14 dataset: impl Iterator<Item = (View<'a, P>, View<'a, V>)>,
15 query: View<'b, P>,
16 num: usize,
17) -> Vec<(M::Unit, View<'a, P>, View<'a, V>)>
18where
19 M: Metric<P>,
20 P: ProxyView,
21 V: ProxyView,
22{
23 let mut dataset = dataset.map(|(pt, val)| (metric.distance(pt, query), pt, val));
24
25 let mut neighbors = Vec::with_capacity(num);
27
28 neighbors.extend((&mut dataset).take(num));
30 neighbors.sort_unstable_by_key(|n| n.0);
32
33 for point in dataset {
35 let position = neighbors.partition_point(|n| n.0 <= point.0);
37 if position != num {
40 neighbors.pop();
41 neighbors.insert(position, point);
42 }
43 }
44
45 neighbors
46}
47
48pub struct LinearSearch<'a, M, P, V, PP = ReferenceProxy<P>, VP = ReferenceProxy<V>> {
54 pub metric: M,
55 pub data: &'a [(P, V)],
56 pub _phantom: core::marker::PhantomData<(PP, VP)>,
57}
58
59impl<'a, M, P, V, PP, VP> LinearSearch<'a, M, P, V, PP, VP>
60where
61 M: Metric<PP>,
62 PP: ProxyView<Owned = P>,
63 VP: ProxyView<Owned = V>,
64{
65 pub fn new(metric: M, data: &'a [(P, V)]) -> Self {
66 Self {
67 metric,
68 data,
69 _phantom: core::marker::PhantomData,
70 }
71 }
72}
73
74impl<'a, M, P, V, PP, VP> ApproximateSpace for LinearSearch<'a, M, P, V, PP, VP>
75where
76 M: Metric<PP>,
77 PP: ProxyView<Owned = P>,
78 VP: ProxyView<Owned = V>,
79{
80 type PointProxy = PP;
81 type ValueProxy = VP;
82 type Metric = M;
83}
84
85impl<'a, M, P, V, PP, VP> ExactSpace for LinearSearch<'a, M, P, V, PP, VP>
87where
88 M: Metric<PP>,
89 PP: ProxyView<Owned = P>,
90 VP: ProxyView<Owned = V>,
91{
92}
93
94impl<'c, M, P, V, PP, VP> Knn for LinearSearch<'c, M, P, V, PP, VP>
95where
96 M: Metric<PP>,
97 PP: ProxyView<Owned = P>,
98 VP: ProxyView<Owned = V>,
99{
100 type KnnIter<'a>
101 = vec::IntoIter<(M::Unit, View<'a, PP>, View<'a, VP>)>
102 where
103 Self: 'a;
104
105 fn knn<'a, 'b>(&'a self, query: View<'b, Self::PointProxy>, num: usize) -> Self::KnnIter<'a> {
106 linear_knn::<M, PP, VP>(
107 self.metric,
108 self.data
109 .iter()
110 .map(|(pt, val)| (PP::view(pt), VP::view(val))),
111 query,
112 num,
113 )
114 .into_iter()
115 }
116
117 fn nn<'a, 'b>(
118 &'a self,
119 query: View<'b, Self::PointProxy>,
120 ) -> Option<(M::Unit, View<'a, PP>, View<'a, VP>)> {
121 linear_nn::<M, PP, VP>(
122 self.metric,
123 self.data
124 .iter()
125 .map(|(pt, val)| (PP::view(pt), VP::view(val))),
126 query,
127 )
128 }
129}
130
131pub struct LinearContainer<M, P, V, PP = ReferenceProxy<P>, VP = ReferenceProxy<V>> {
132 pub metric: M,
133 pub data: Vec<(P, V)>,
134 pub _phantom: core::marker::PhantomData<(PP, VP)>,
135}
136
137impl<M, P, V, PP, VP> ApproximateSpace for LinearContainer<M, P, V, PP, VP>
138where
139 M: Metric<PP>,
140 PP: ProxyView<Owned = P>,
141 VP: ProxyView<Owned = V>,
142{
143 type PointProxy = PP;
144 type ValueProxy = VP;
145 type Metric = M;
146}
147
148impl<M, P, V, PP, VP> ExactSpace for LinearContainer<M, P, V, PP, VP>
150where
151 M: Metric<PP>,
152 PP: ProxyView<Owned = P>,
153 VP: ProxyView<Owned = V>,
154{
155}
156
157impl<M, P, V, PP, VP> SpatialContainer for LinearContainer<M, P, V, PP, VP>
158where
159 M: Metric<PP>,
160 PP: ProxyView<Owned = P>,
161 VP: ProxyView<Owned = V>,
162{
163 type SpatialIter<'a>
164 = Map<slice::Iter<'a, (P, V)>, fn(&'a (P, V)) -> (View<'a, PP>, View<'a, VP>)>
165 where
166 Self: 'a;
167
168 fn with_metric(metric: Self::Metric) -> Self {
169 Self {
170 metric,
171 data: Vec::new(),
172 _phantom: core::marker::PhantomData,
173 }
174 }
175
176 fn insert(&mut self, point: P, value: V) {
177 self.data.push((point, value));
178 }
179
180 fn iter(&self) -> Self::SpatialIter<'_> {
181 self.data.iter().map(|(p, v)| (PP::view(p), VP::view(v)))
182 }
183}
184
185impl<M, P, V, PP, VP> Knn for LinearContainer<M, P, V, PP, VP>
186where
187 M: Metric<PP>,
188 PP: ProxyView<Owned = P>,
189 VP: ProxyView<Owned = V>,
190{
191 type KnnIter<'a>
192 = vec::IntoIter<(M::Unit, View<'a, PP>, View<'a, VP>)>
193 where
194 Self: 'a;
195
196 fn knn<'a, 'b>(&'a self, query: View<'b, Self::PointProxy>, num: usize) -> Self::KnnIter<'a> {
197 linear_knn::<M, PP, VP>(
198 self.metric,
199 self.data
200 .iter()
201 .map(|(pt, val)| (PP::view(pt), VP::view(val))),
202 query,
203 num,
204 )
205 .into_iter()
206 }
207
208 fn nn<'a, 'b>(
209 &'a self,
210 query: View<'b, Self::PointProxy>,
211 ) -> Option<(M::Unit, View<'a, PP>, View<'a, VP>)> {
212 linear_nn::<M, PP, VP>(
213 self.metric,
214 self.data
215 .iter()
216 .map(|(pt, val)| (PP::view(pt), VP::view(val))),
217 query,
218 )
219 }
220}