Skip to content

Commit 0f662b1

Browse files
committed
sample_efraimidis_spirakis: use algorithm A-ExpJ
This results in approx 18% faster tests choosing 2-in-100 items
1 parent b806b29 commit 0f662b1

File tree

1 file changed

+25
-9
lines changed

1 file changed

+25
-9
lines changed

src/seq/index.rs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -389,28 +389,44 @@ where
389389

390390
let mut candidates = Vec::with_capacity(amount.as_usize());
391391
let mut index = N::zero();
392-
while index < length {
392+
while index < length && candidates.len() < amount.as_usize() {
393393
let weight = weight(index.as_usize()).into();
394394
if weight > 0.0 {
395395
let key = rng.random::<f64>().ln() / weight;
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();
396+
// let key = rng.random::<f64>().powf(1.0 / weight);
397+
candidates.push(Element { index, key });
402398
} else if !(weight >= 0.0) {
403399
return Err(WeightError::InvalidWeight);
404400
}
405401

406402
index += N::one();
407403
}
404+
candidates.sort_unstable();
408405

409-
let avail = candidates.len();
410-
if avail < amount.as_usize() {
406+
if candidates.len() < amount.as_usize() {
411407
return Err(WeightError::InsufficientNonZero);
412408
}
413409

410+
let mut x = rng.random::<f64>().ln() / candidates[0].key;
411+
while index < length {
412+
let weight = weight(index.as_usize()).into();
413+
if weight > 0.0 {
414+
x -= weight;
415+
if x <= 0.0 {
416+
let t = core::f64::consts::E.powf(candidates[0].key * weight);
417+
let key = rng.random_range(t..1.0).ln() / weight;
418+
candidates[0] = Element { index, key };
419+
candidates.sort_unstable();
420+
421+
x = rng.random::<f64>().ln() / candidates[0].key;
422+
}
423+
} else if !(weight >= 0.0) {
424+
return Err(WeightError::InvalidWeight);
425+
}
426+
427+
index += N::one();
428+
}
429+
414430
Ok(IndexVec::from(candidates.iter().map(|elt| elt.index).collect()))
415431
}
416432

0 commit comments

Comments
 (0)