dipstick/src/pcg32.rs

50 lines
1.7 KiB
Rust
Raw Normal View History

2018-06-14 16:37:21 +00:00
//! PCG32 random number generation for fast sampling
2018-09-14 10:47:31 +00:00
//! Kept here for low dependency count.
2018-06-14 16:37:21 +00:00
2018-10-04 17:13:55 +00:00
#![cfg_attr(feature = "tool_lints", allow(clippy::unreadable_literal))]
2019-04-16 21:29:55 +00:00
#![allow(clippy::unreadable_literal)]
2018-10-04 17:13:55 +00:00
2018-06-14 16:37:21 +00:00
use std::cell::RefCell;
fn seed() -> u64 {
let seed = 5573589319906701683_u64;
2019-03-18 01:42:00 +00:00
let seed = seed
.wrapping_mul(6364136223846793005)
2018-06-14 16:37:21 +00:00
.wrapping_add(1442695040888963407)
.wrapping_add(time::precise_time_ns());
seed.wrapping_mul(6364136223846793005)
.wrapping_add(1442695040888963407)
}
/// quickly return a random int
fn pcg32_random() -> u32 {
thread_local! {
static PCG32_STATE: RefCell<u64> = RefCell::new(seed());
}
PCG32_STATE.with(|state| {
2018-10-04 17:13:55 +00:00
let old_state: u64 = *state.borrow();
2018-06-14 16:37:21 +00:00
// XXX could generate the increment from the thread ID
2018-10-04 17:13:55 +00:00
*state.borrow_mut() = old_state
2018-06-14 16:37:21 +00:00
.wrapping_mul(6364136223846793005)
.wrapping_add(1442695040888963407);
2018-10-04 17:13:55 +00:00
((((old_state >> 18) ^ old_state) >> 27) as u32).rotate_right((old_state >> 59) as u32)
2018-06-14 16:37:21 +00:00
})
}
/// Convert a floating point sampling rate to an integer so that a fast integer RNG can be used
/// Float rate range is between 1.0 (send 100% of the samples) and 0.0 (_no_ samples taken)
/// . | float rate | int rate | percentage
/// ---- | ---------- | -------- | ----
/// all | 1.0 | 0x0 | 100%
/// none | 0.0 | 0xFFFFFFFF | 0%
pub fn to_int_rate(float_rate: f64) -> u32 {
2022-07-12 18:11:39 +00:00
assert!((0.0..=1.0).contains(&float_rate));
2019-04-16 21:29:55 +00:00
((1.0 - float_rate) * f64::from(::std::u32::MAX)) as u32
2018-06-14 16:37:21 +00:00
}
/// randomly select samples based on an int rate
pub fn accept_sample(int_rate: u32) -> bool {
pcg32_random() > int_rate
}