diff --git a/src/cellgrid/iters.rs b/src/cellgrid/iters.rs
index b89ae50..0a45d14 100644
--- a/src/cellgrid/iters.rs
+++ b/src/cellgrid/iters.rs
@@ -16,11 +16,24 @@ mod private {
/// "Marker" trait indicating a type being a valid neighborhood configuration.
pub trait SpaceConfig {
+ /// Default implementation suitable for `Full`.
#[doc(hidden)]
#[inline]
fn neighbors_as_slice(neighbors: &[i32], _: private::Token) -> &[i32] {
neighbors
}
+
+ /// Default implementation suitable for `Half`.
+ #[doc(hidden)]
+ #[inline]
+ fn intra_cell_pairs
(
+ iter: Iter<'_, P>,
+ _: private::Token,
+ ) -> impl FusedIterator- + Clone {
+ iter.clone()
+ .enumerate()
+ .flat_map(move |(n, i)| iter.clone().skip(n + 1).map(move |j| (i, j)))
+ }
}
/// _Full-space_ neighborhood.
@@ -28,7 +41,20 @@ pub struct Full;
/// _Half-space_ neighborhood.
pub struct Half;
-impl SpaceConfig for Full {}
+impl SpaceConfig for Full {
+ #[inline]
+ fn intra_cell_pairs
(
+ iter: Iter<'_, P>,
+ _: private::Token,
+ ) -> impl FusedIterator- + Clone {
+ let rev = iter.clone().rev();
+ rev.clone()
+ .enumerate()
+ .flat_map(move |(n, i)| rev.clone().skip(n + 1).map(move |j| (i, j)))
+ .chain(Half::intra_cell_pairs(iter.clone(), private::Token))
+ }
+}
+
impl SpaceConfig for Half {
#[inline]
fn neighbors_as_slice(neighbors: &[i32], _: private::Token) -> &[i32] {
@@ -189,20 +215,19 @@ where
/// Returns an iterator over all unique pairs of points in this `GridCell`.
#[inline]
- fn intra_cell_pairs(self) -> impl FusedIterator
- + Clone {
+ fn intra_cell_pairs(self) -> impl FusedIterator
- + Clone {
// this is equivalent to
// self.iter().copied().tuple_combinations::<(P, P)>()
// but faster for our specific case (pairs from slice of `Copy` values)
- self.iter()
- .enumerate()
- .flat_map(move |(n, i)| self.iter().skip(n + 1).map(move |j| (i, j)))
+ // TODO: expose type parameter `S: SpaceConfig` on `{CellGrid, GridCell}::particle_pairs()`
+ S::intra_cell_pairs(self.iter(), private::Token)
}
/// Returns an iterator over all unique pairs of points in this `GridCell` with points of the neighboring cells.
#[inline]
- fn inter_cell_pairs(self) -> impl FusedIterator
- + Clone {
+ fn inter_cell_pairs(self) -> impl FusedIterator
- + Clone {
self.iter()
- .cartesian_product(self.neighbors::().flat_map(|cell| cell.iter()))
+ .cartesian_product(self.neighbors::
().flat_map(|cell| cell.iter()))
}
/// Returns an iterator over all _relevant_ pairs of particles within in the neighborhood of this `GridCell`.
@@ -210,10 +235,9 @@ where
/// _Relevant_ means the distance between paired particles might be less than the `cutoff` but
/// this cannot be guaranteed.\
/// This method consumes `self` but `GridCell` implements [`Copy`].
- //TODO: handle full-space as well
- //TODO: document that we're relying on GridCell impl'ing Copy here (so we can safely consume `self`)
pub fn particle_pairs(self) -> impl FusedIterator- + Clone {
- self.intra_cell_pairs().chain(self.inter_cell_pairs())
+ self.intra_cell_pairs::()
+ .chain(self.inter_cell_pairs::())
}
}
@@ -315,7 +339,7 @@ mod tests {
assert_eq!(
cell_grid
.iter()
- .map(|cell| cell.intra_cell_pairs().count())
+ .map(|cell| cell.intra_cell_pairs::().count())
.sum::(),
4,
"testing intra_cell_pairs()"
@@ -324,10 +348,41 @@ mod tests {
assert_eq!(
cell_grid
.iter()
- .map(|cell| cell.inter_cell_pairs().count())
+ .map(|cell| cell.inter_cell_pairs::().count())
.sum::(),
24,
"testing inter_cell_pairs()"
);
}
+
+ #[test]
+ fn test_half_full_space_particle_pairs() {
+ // Using 0-origin to avoid floating point errors
+ let points = generate_pointcloud([2, 2, 2], 1.0, [0.0, 0.0, 0.0]);
+ let cell_grid = CellGrid::new(points.iter().copied(), 1.0);
+
+ assert_eq!(
+ 2 * cell_grid
+ .iter()
+ .map(|cell| cell.intra_cell_pairs::().count())
+ .sum::(),
+ cell_grid
+ .iter()
+ .map(|cell| cell.intra_cell_pairs::().count())
+ .sum::(),
+ "testing intra_cell_pairs() half-/full-space"
+ );
+
+ assert_eq!(
+ 2 * cell_grid
+ .iter()
+ .map(|cell| cell.inter_cell_pairs::().count())
+ .sum::(),
+ cell_grid
+ .iter()
+ .map(|cell| cell.inter_cell_pairs::().count())
+ .sum::(),
+ "testing inter_cell_pairs() half-/full-space"
+ );
+ }
}
diff --git a/surface-sampling/examples/cli.rs b/surface-sampling/examples/cli.rs
index 4f0a4fb..de29869 100644
--- a/surface-sampling/examples/cli.rs
+++ b/surface-sampling/examples/cli.rs
@@ -48,7 +48,6 @@ enum Commands {
},
/// Evaluate SDF of a PDB file for a specified grid of q=l³ query points
- /// in a gr
Eval {
/// Protein structure file to generate SDF from.
pdb: PathBuf,