Skip to content

Commit b806b29

Browse files
committed
sample_efraimidis_spirakis: keep at most amount candidates
Approx 2% improvement to tests sampling 2 of 100 elements
1 parent d645952 commit b806b29

File tree

1 file changed

+8
-14
lines changed

1 file changed

+8
-14
lines changed

src/seq/index.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -387,13 +387,18 @@ where
387387

388388
impl<N> Eq for Element<N> {}
389389

390-
let mut candidates = Vec::with_capacity(length.as_usize());
390+
let mut candidates = Vec::with_capacity(amount.as_usize());
391391
let mut index = N::zero();
392392
while index < length {
393393
let weight = weight(index.as_usize()).into();
394394
if weight > 0.0 {
395395
let key = rng.random::<f64>().ln() / weight;
396-
candidates.push(Element { index, key });
396+
if candidates.len() < amount.as_usize() {
397+
candidates.push(Element { index, key });
398+
} else if key > candidates[0].key {
399+
candidates[0] = Element { index, key };
400+
}
401+
candidates.sort_unstable();
397402
} else if !(weight >= 0.0) {
398403
return Err(WeightError::InvalidWeight);
399404
}
@@ -406,18 +411,7 @@ where
406411
return Err(WeightError::InsufficientNonZero);
407412
}
408413

409-
// Partially sort the array to find the `amount` elements with the greatest
410-
// keys. Do this by using `select_nth_unstable` to put the elements with
411-
// the *smallest* keys at the beginning of the list in `O(n)` time, which
412-
// provides equivalent information about the elements with the *greatest* keys.
413-
let (_, mid, greater) = candidates.select_nth_unstable(avail - amount.as_usize());
414-
415-
let mut result: Vec<N> = Vec::with_capacity(amount.as_usize());
416-
result.push(mid.index);
417-
for element in greater {
418-
result.push(element.index);
419-
}
420-
Ok(IndexVec::from(result))
414+
Ok(IndexVec::from(candidates.iter().map(|elt| elt.index).collect()))
421415
}
422416

423417
/// Randomly sample exactly `amount` indices from `0..length`, using Floyd's

0 commit comments

Comments
 (0)