Skip to content

Commit ccefad4

Browse files
committed
refactor: remove within_unsorted_iter_owned in favour of modifying within_unsorted_iter
within_unsorted_iter is modified to decouple the lifetime of the iterator from that of the query by performing a generally very cheap copy just once at the start of the query
1 parent f9e9621 commit ccefad4

4 files changed

Lines changed: 44 additions & 59 deletions

File tree

src/common/generate_within_unsorted_iter.rs

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ macro_rules! generate_within_unsorted_iter {
77
#[inline]
88
pub fn within_unsorted_iter<D>(
99
&'a self,
10-
query: &'a [A; K],
10+
query: &'query [A; K],
1111
dist: A,
1212
) -> WithinUnsortedIter<'a, A, T>
1313
where
@@ -16,37 +16,7 @@ macro_rules! generate_within_unsorted_iter {
1616
let mut off = [A::zero(); K];
1717
let root_index: IDX = *transform(&self.root_index);
1818

19-
let gen = Gn::new_scoped(move |gen_scope| {
20-
unsafe {
21-
self.within_unsorted_iter_recurse::<D>(
22-
query,
23-
dist,
24-
root_index,
25-
0,
26-
gen_scope,
27-
&mut off,
28-
A::zero(),
29-
);
30-
}
31-
32-
done!();
33-
});
34-
35-
WithinUnsortedIter::new(gen)
36-
}
37-
38-
#[inline]
39-
pub fn within_unsorted_iter_owned<D>(
40-
&'a self,
41-
query: [A; K],
42-
dist: A,
43-
) -> WithinUnsortedIterOwned<'a, A, T>
44-
where
45-
D: DistanceMetric<A, K>,
46-
{
47-
let mut off = [A::zero(); K];
48-
let root_index: IDX = *transform(&self.root_index);
49-
19+
let query = query.clone();
5020
let gen = Gn::new_scoped(move |gen_scope| {
5121
let query_ref = &query;
5222
unsafe {
@@ -64,7 +34,7 @@ macro_rules! generate_within_unsorted_iter {
6434
done!();
6535
});
6636

67-
WithinUnsortedIterOwned::new(gen)
37+
WithinUnsortedIter::new(gen)
6838
}
6939

7040
#[allow(clippy::too_many_arguments)]

src/fixed/query/within_unsorted_iter.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,19 @@ use crate::nearest_neighbour::NearestNeighbour;
77
use crate::rkyv_utils::transform;
88
use crate::traits::DistanceMetric;
99
use crate::traits::{is_stem_index, Content, Index};
10-
use crate::within_unsorted_iter::{WithinUnsortedIter, WithinUnsortedIterOwned};
10+
use crate::within_unsorted_iter::WithinUnsortedIter;
1111

1212
use crate::generate_within_unsorted_iter;
1313

14-
impl<'a, A: Axis, T: Content, const K: usize, const B: usize, IDX: Index<T = IDX> + Send>
15-
KdTree<A, T, K, B, IDX>
14+
impl<
15+
'a,
16+
'query,
17+
A: Axis,
18+
T: Content,
19+
const K: usize,
20+
const B: usize,
21+
IDX: Index<T = IDX> + Send,
22+
> KdTree<A, T, K, B, IDX>
1623
where
1724
usize: Cast<IDX>,
1825
{

src/float/query/within_unsorted_iter.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::nearest_neighbour::NearestNeighbour;
77
use crate::rkyv_utils::transform;
88
use crate::traits::DistanceMetric;
99
use crate::traits::{is_stem_index, Content, Index};
10-
use crate::within_unsorted_iter::{WithinUnsortedIter, WithinUnsortedIterOwned};
10+
use crate::within_unsorted_iter::WithinUnsortedIter;
1111

1212
use crate::generate_within_unsorted_iter;
1313

@@ -36,8 +36,15 @@ assert_eq!(within.len(), 2);
3636
};
3737
}
3838

39-
impl<'a, A: Axis, T: Content, const K: usize, const B: usize, IDX: Index<T = IDX> + Send>
40-
KdTree<A, T, K, B, IDX>
39+
impl<
40+
'a,
41+
'query,
42+
A: Axis,
43+
T: Content,
44+
const K: usize,
45+
const B: usize,
46+
IDX: Index<T = IDX> + Send,
47+
> KdTree<A, T, K, B, IDX>
4148
where
4249
usize: Cast<IDX>,
4350
{
@@ -54,6 +61,7 @@ use crate::float::kdtree::ArchivedKdTree;
5461
#[cfg(feature = "rkyv")]
5562
impl<
5663
'a,
64+
'query,
5765
A: Axis + rkyv::Archive<Archived = A>,
5866
T: Content + rkyv::Archive<Archived = T>,
5967
const K: usize,
@@ -77,6 +85,7 @@ use crate::float::kdtree::ArchivedR8KdTree;
7785
#[cfg(feature = "rkyv_08")]
7886
impl<
7987
'a,
88+
'query,
8089
A: Axis + Send + rkyv_08::Archive,
8190
T: Content + Send + rkyv_08::Archive,
8291
const K: usize,
@@ -145,10 +154,25 @@ mod tests {
145154
let radius = 0.2;
146155
let expected = linear_search(&content_to_add, &query_point, radius);
147156

148-
let result: Vec<_> = tree
149-
.within_unsorted_iter::<Manhattan>(&query_point, radius)
150-
.collect();
151-
assert_eq!(result, expected);
157+
// Store some iterators in a way that the test will fail to compile
158+
// if the lifetime of the iterator is tied to the query as well as to
159+
// the lifetime of the tree
160+
let mut iterators = Vec::new();
161+
for _ in 0..2 {
162+
// take a copy of query_point to ensure that the lifetime of the
163+
// iterator is tied to the lifetime of the tree and not the lifetime
164+
// of the query
165+
let temp_query = query_point;
166+
167+
let iter = tree.within_unsorted_iter::<Manhattan>(&temp_query, radius);
168+
169+
iterators.push(iter);
170+
}
171+
172+
for iter in iterators {
173+
let result: Vec<_> = iter.collect();
174+
assert_eq!(result, expected);
175+
}
152176

153177
let mut rng = rand::rng();
154178
for _i in 0..1000 {

src/within_unsorted_iter.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,3 @@ impl<A, T> Iterator for WithinUnsortedIter<'_, A, T> {
1818
self.0.next()
1919
}
2020
}
21-
22-
pub struct WithinUnsortedIterOwned<'a, A, T>(Generator<'a, (), NearestNeighbour<A, T>>);
23-
24-
impl<'a, A, T> WithinUnsortedIterOwned<'a, A, T> {
25-
pub(crate) fn new(gen: Generator<'a, (), NearestNeighbour<A, T>>) -> Self {
26-
WithinUnsortedIterOwned(gen)
27-
}
28-
}
29-
30-
impl<A, T> Iterator for WithinUnsortedIterOwned<'_, A, T> {
31-
type Item = NearestNeighbour<A, T>;
32-
33-
fn next(&mut self) -> Option<Self::Item> {
34-
self.0.next()
35-
}
36-
}

0 commit comments

Comments
 (0)