use rand::RngCore;
pub fn gen_range_int<R: RngCore>(rng: &mut R, min: u64, max: u64) -> u64 {
debug_assert!(min <= max, "min must be less than or equal to max");
let range = max - min + 1;
let max_acceptable = u64::MAX - (u64::MAX % range);
loop {
let random_u64 = rng.next_u64();
if random_u64 < max_acceptable {
return min + (random_u64 % range);
}
}
}
pub fn gen_range_float<R: RngCore>(rng: &mut R, min: f64, max: f64) -> f64 {
debug_assert!(min <= max, "min must be less than or equal to max");
let random_u64 = rng.next_u64();
let normalized = (random_u64 as f64) / (u64::MAX as f64);
min + normalized * (max - min)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gen_range_int() {
let mut rng = rand::rng();
for _ in 0..100 {
let value = gen_range_int(&mut rng, 1, 10);
assert!((1..=10).contains(&value));
}
let value = gen_range_int(&mut rng, 5, 5);
assert_eq!(value, 5);
}
#[test]
fn test_gen_range_float() {
let mut rng = rand::rng();
for _ in 0..100 {
let value = gen_range_float(&mut rng, 0.0, 1.0);
assert!((0.0..=1.0).contains(&value));
}
for _ in 0..100 {
let value = gen_range_float(&mut rng, 10.5, 20.5);
assert!((10.5..=20.5).contains(&value));
}
}
}