diff --git a/examples/random_demo.rs b/examples/random_demo.rs new file mode 100644 index 0000000..1010d51 --- /dev/null +++ b/examples/random_demo.rs @@ -0,0 +1,67 @@ +use rustframe::random::{crypto_rng, rng, Rng, SliceRandom}; + +/// Demonstrates basic usage of the random number generators. +/// +/// It showcases uniform ranges, booleans, normal distribution, +/// shuffling and the cryptographically secure generator. +fn main() { + basic_usage(); + println!("\n-----\n"); + normal_demo(); + println!("\n-----\n"); + shuffle_demo(); +} + +fn basic_usage() { + println!("Basic PRNG usage\n----------------"); + let mut prng = rng(); + println!("random u64 : {}", prng.next_u64()); + println!("range [10,20): {}", prng.random_range(10..20)); + println!("bool : {}", prng.gen_bool()); +} + +fn normal_demo() { + println!("Normal distribution\n-------------------"); + let mut prng = rng(); + for _ in 0..3 { + let v = prng.normal(0.0, 1.0); + println!("sample: {:.3}", v); + } +} + +fn shuffle_demo() { + println!("Slice shuffling\n----------------"); + let mut prng = rng(); + let mut data = [1, 2, 3, 4, 5]; + data.shuffle(&mut prng); + println!("shuffled: {:?}", data); + + let mut secure = crypto_rng(); + let byte = secure.random_range(0..256usize); + println!("crypto byte: {}", byte); +} + +#[cfg(test)] +mod tests { + use super::*; + use rustframe::random::{CryptoRng, Prng}; + + #[test] + fn test_basic_usage_range_bounds() { + let mut rng = Prng::new(1); + for _ in 0..50 { + let v = rng.random_range(5..10); + assert!(v >= 5 && v < 10); + } + } + + #[test] + fn test_crypto_byte_bounds() { + let mut rng = CryptoRng::new(); + for _ in 0..50 { + let v = rng.random_range(0..256usize); + assert!(v < 256); + } + } +} + diff --git a/examples/random_stats.rs b/examples/random_stats.rs new file mode 100644 index 0000000..6aeef34 --- /dev/null +++ b/examples/random_stats.rs @@ -0,0 +1,57 @@ +use rustframe::random::{crypto_rng, rng, Rng}; + +/// Demonstrates simple statistical checks on random number generators. +fn main() { + chi_square_demo(); + println!("\n-----\n"); + monobit_demo(); +} + +fn chi_square_demo() { + println!("Chi-square test on PRNG"); + let mut rng = rng(); + let mut counts = [0usize; 10]; + let samples = 10000; + for _ in 0..samples { + let v = rng.random_range(0..10usize); + counts[v] += 1; + } + let expected = samples as f64 / 10.0; + let chi2: f64 = counts + .iter() + .map(|&c| { + let diff = c as f64 - expected; + diff * diff / expected + }) + .sum(); + println!("counts: {:?}", counts); + println!("chi-square: {:.3}", chi2); +} + +fn monobit_demo() { + println!("Monobit test on crypto RNG"); + let mut rng = crypto_rng(); + let mut ones = 0usize; + let samples = 1000; + for _ in 0..samples { + ones += rng.next_u64().count_ones() as usize; + } + let ratio = ones as f64 / (samples as f64 * 64.0); + println!("ones ratio: {:.4}", ratio); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_chi_square_demo_runs() { + chi_square_demo(); + } + + #[test] + fn test_monobit_demo_runs() { + monobit_demo(); + } +} +