From 9172e6f32b675f095c9b060bde0da0a1a41b1b1d Mon Sep 17 00:00:00 2001 From: Sebastien Rousseau Date: Sat, 4 May 2024 15:49:51 +0100 Subject: [PATCH] docs(vrd): :memo: updating examples documentation and sorting --- examples/example.rs | 402 ++++++++++++++++++++++++-------------------- 1 file changed, 218 insertions(+), 184 deletions(-) diff --git a/examples/example.rs b/examples/example.rs index d586d57..009af0d 100644 --- a/examples/example.rs +++ b/examples/example.rs @@ -12,12 +12,12 @@ //! //! ## Examples //! +//! ### Basic Number Generation +//! //! - Generating a random number: Demonstrates how to generate a random number using the `rand` method. //! //! - Generating a random double-precision floating-point number: Shows how to generate a random floating-point number within the range [0.0, 1.0). //! -//! - Seeding the RNG: Illustrates how to seed the random number generator with a specific value to ensure reproducible results. -//! //! - Generating random integers: Shows various ways to generate random integers within different ranges. //! //! - Generating random booleans: Demonstrates how to generate random boolean values with customizable probabilities. @@ -26,14 +26,25 @@ //! //! - Generating random characters and strings: Illustrates how to generate random characters and strings of specified lengths. //! -//! - Shuffling and sampling: Shows how to shuffle and sample elements from slices using the `shuffle`, `sample`, and `sample_with_replacement` methods. +//! ### Advanced PRNG Usage //! -//! - Serialization and deserialization: Demonstrates how to serialize and deserialize the random number generator state to/from JSON. +//! - Seeding the RNG: Illustrates how to seed the random number generator with a specific value to ensure reproducible results. //! //! - Custom Mersenne Twister configuration: Shows how to create a custom configuration for the Mersenne Twister RNG and serialize it to a file. //! -//! - Comparing `vrd` RNG with Rust's default RNG: Compares the random number generated by `vrd` RNG with Rust's default RNG. +//! - Altering the state of the PRNG: Demonstrates how seeding, twisting, and retrieving the MTI can be combined to control sequences of random numbers reproducibly. +//! +//! ### Shuffling and Sampling +//! +//! - Shuffling and sampling: Shows how to shuffle and sample elements from slices using the `shuffle`, `sample`, and `sample_with_replacement` methods. +//! +//! ### Serialization and Deserialization with Error Handling +//! +//! - Serialization and deserialization: Demonstrates how to serialize and deserialize the random number generator state to/from JSON, incorporating error handling. +//! +//! ### Miscellaneous Examples //! +//! - Comparing `vrd` RNG with Rust's default RNG: Compares the random number generated by `vrd` RNG with Rust's default RNG. use vrd::mersenne_twister::{ MersenneTwisterConfig, MersenneTwisterParams, @@ -46,107 +57,111 @@ use vrd::{ }; fn main() { - // Initializing a new random number generator (RNG) instance. - let mut rng = Random::from_entropy(); - println!("🦀 Random::new(): ✅ {rng}"); - - // Accessing the default RNG provided by the `vrd` crate. - let default = Random::default(); - println!("🦀 Random::default(): ✅ {default}"); - - // Seeding the RNG with a specific value to ensure reproducible results. - let seed_value = 12345; - rng.seed(seed_value); - println!("🦀 Random::seed(): ✅ {}", seed_value); - - // Generating a random integer between 0 and the maximum value a u32 can hold. - let random = rng.rand(); - println!("🦀 Random::random(): ✅ {random}"); - - // Generating a random double-precision floating-point number. - let random_double = Random::double(&mut rng); - println!("🦀 Random::double(): ✅ {}", random_double); - - // Generating a random 64-bit signed integer. - let random_i64 = rng.i64(); - println!("🦀 Random::i64(): ✅ {}", random_i64); - - // Generating a random 64-bit unsigned integer. - let random_u64 = rng.u64(); - println!("🦀 Random::u64(): ✅ {}", random_u64); - - // Generating a random 64-bit floating-point number. - let random_f64 = rng.f64(); - println!("🦀 Random::f64(): ✅ {}", random_f64); - - // Generating a random floating-point number between 0 and 1. - let float = rng.rand() as f32 / 0x7FFF as f32; - println!("🦀 Random::float(): ✅ {float}"); - - // Producing a random usize value. - let int = rng.rand() as usize; - println!("🦀 Random::int(): ✅ {int}"); - - // Generating a random integer within the specified range (0 to 100). - let min = 0; - let max = 100; - let rand_int = rand_int!(rng, min, max); - println!( - "🦀 Random integer between {} and {}: {}", - min, max, rand_int - ); - - // Generating a random number within a specified range using the `rand_range` macro. - let rand_range_macro = rand_range!(rng, 10, 20); - println!( - "🦀 Random number between 10 and 20: {}", - rand_range_macro - ); - - // Generating a random floating-point number within a specified range. - let rand_range = - rand_float!(rng) * (max as f32 - min as f32) + min as f32; - println!( - "🦀 Random number between {} and {}: {}", - min, max, rand_range - ); - - // Creating a random 32-bit unsigned integer within a specified range. - let rand_uint = random_range!(rng, 0, u32::MAX); - println!( - "🦀 Random u32 between 0 and u32::max_value(): {}", - rand_uint - ); - - // Generating a random boolean with a 50% probability. - let rand_bool = rand_bool!(rng, 0.5); - println!("🦀 Random boolean with 50% probability: {}", rand_bool); - - // Creating a vector of 10 random bytes. - let rand_bytes = rand_bytes!(rng, 10); - println!("🦀 Random bytes: {:?}", rand_bytes); - - // Creating a vector of 1000 random bytes. - let bytes = Random::bytes(&mut rng, 1000); - println!("🦀 Random::bytes(): ✅ {bytes:?}"); - - // Generating a random character within the range 'a' to 'z'. - let rand_char = rand_char!(rng); - println!("🦀 Random char between 'a' and 'z': {}", rand_char); - - // Generating a random string of length 10. - let random_string = rng.string(10); - println!("🦀 Random string: {}", random_string); - - // Picking a random element from a predefined slice of integers. - let values = &[1, 2, 3, 4, 5]; - let rand_choose = rand_choose!(rng, values); - println!( - "🦀 Random element from [1, 2, 3, 4, 5]: {:?}", - rand_choose - ); - + // ... Basic Number Generation Examples ... + + // Initializing a new random number generator (RNG) instance. + let mut rng = Random::from_entropy(); + println!("🦀 Random::new(): ✅ {rng}"); + + // Accessing the default RNG provided by the `vrd` crate. + let default = Random::default(); + println!("🦀 Random::default(): ✅ {default}"); + + // Seeding the RNG with a specific value to ensure reproducible results. + let seed_value = 12345; + rng.seed(seed_value); + println!("🦀 Random::seed(): ✅ {}", seed_value); + + // Generating a random integer between 0 and the maximum value a u32 can hold. + let random = rng.rand(); + println!("🦀 Random::random(): ✅ {random}"); + + // Generating a random double-precision floating-point number. + let random_double = Random::double(&mut rng); + println!("🦀 Random::double(): ✅ {}", random_double); + + // Generating a random 64-bit signed integer. + let random_i64 = rng.i64(); + println!("🦀 Random::i64(): ✅ {}", random_i64); + + // Generating a random 64-bit unsigned integer. + let random_u64 = rng.u64(); + println!("🦀 Random::u64(): ✅ {}", random_u64); + + // Generating a random 64-bit floating-point number. + let random_f64 = rng.f64(); + println!("🦀 Random::f64(): ✅ {}", random_f64); + + // Generating a random floating-point number between 0 and 1. + let float = rng.rand() as f32 / 0x7FFF as f32; + println!("🦀 Random::float(): ✅ {float}"); + + // Producing a random usize value. + let int = rng.rand() as usize; + println!("🦀 Random::int(): ✅ {int}"); + + // Generating a random integer within the specified range (0 to 100). + let min = 0; + let max = 100; + let rand_int = rand_int!(rng, min, max); + println!( + "🦀 Random integer between {} and {}: {}", + min, max, rand_int + ); + + // Generating a random number within a specified range using the `rand_range` macro. + let rand_range_macro = rand_range!(rng, 10, 20); + println!( + "🦀 Random number between 10 and 20: {}", + rand_range_macro + ); + + // Generating a random floating-point number within a specified range. + let rand_range = + rand_float!(rng) * (max as f32 - min as f32) + min as f32; + println!( + "🦀 Random number between {} and {}: {}", + min, max, rand_range + ); + + // Creating a random 32-bit unsigned integer within a specified range. + let rand_uint = random_range!(rng, 0, u32::MAX); + println!( + "🦀 Random u32 between 0 and u32::max_value(): {}", + rand_uint + ); + + // Generating a random boolean with a 50% probability. + let rand_bool = rand_bool!(rng, 0.5); + println!("🦀 Random boolean with 50% probability: {}", rand_bool); + + // Creating a vector of 10 random bytes. + let rand_bytes = rand_bytes!(rng, 10); + println!("🦀 Random bytes: {:?}", rand_bytes); + + // Creating a vector of 1000 random bytes. + let bytes = Random::bytes(&mut rng, 1000); + println!("🦀 Random::bytes(): ✅ {bytes:?}"); + + // Generating a random character within the range 'a' to 'z'. + let rand_char = rand_char!(rng); + println!("🦀 Random char between 'a' and 'z': {}", rand_char); + + // Generating a random string of length 10. + let random_string = rng.string(10); + println!("🦀 Random string: {}", random_string); + + // Picking a random element from a predefined slice of integers. + let values = &[1, 2, 3, 4, 5]; + let rand_choose = rand_choose!(rng, values); + println!( + "🦀 Random element from [1, 2, 3, 4, 5]: {:?}", + rand_choose + ); + + // ... Shuffling and Sampling Examples ... // Example of using the `rand_slice` function to generate a random subslice from a given slice. + // This can be useful for selecting random samples from a larger dataset. let rand_slice = Random::rand_slice(&mut rng, values, 3); println!("🦀 Random sub-slice of length 3: {:?}", rand_slice); @@ -172,83 +187,102 @@ fn main() { Random::fill(&mut rng, &mut buffer); println!("🦀 Filled buffer with random values: {:?}", buffer); - // Creating a random 32-bit unsigned integer using a pseudo-random number generator (PRNG). - let rand_pseudo = rand_pseudo!(rng); - println!("🦀 Random u32 using the PRNG: {}", rand_pseudo); - - // Seeding the PRNG with a specific value to get deterministic outputs. - rand_seed!(rng, 42); - let rand_seed = rand_pseudo!(rng); - println!("🦀 Random u32 using the seeded PRNG: {}", rand_seed); - - // Altering the state of the PRNG to vary its output. - rand_twist!(rng); - let rand_twist = rand_pseudo!(rng); - println!( - "🦀 Random u32 after twisting the PRNG state: {}", - rand_twist - ); - - // Retrieving the current state index (MTI) of the Mersenne Twister RNG. - let mti_value = Random::mti(&rng); - println!("🦀 MTI value: {}", mti_value); - - // Generate a random even number. - let even_number = - (0..).map(|_| rng.rand()).find(|&n| n % 2 == 0).unwrap(); - println!("🦀 Random even number: {}", even_number); - - // Pre-generating a large number of random values for performance. - let mut pre_generated_numbers = Vec::new(); - for _ in 0..1000 { - pre_generated_numbers.push(rng.rand()); - } - println!( - "🦀 Pre-generated random numbers: {:?}", - pre_generated_numbers - ); - - // Comparing `vrd` RNG with Rust's default RNG. - let default_rng_number = rand::random::(); - let vrd_rng_number = rng.rand(); - println!( - "🦀 Default RNG number: {}, `vrd` RNG number: {}", - default_rng_number, vrd_rng_number - ); - - // Serialize the random number generator to JSON. - let serialized_rng = serde_json::to_string(&rng).unwrap(); - println!("🦀 Serialized RNG: {}", serialized_rng); - - // Deserialize the random number generator from JSON. - let deserialized_rng: Random = - serde_json::from_str(&serialized_rng).unwrap(); - println!("🦀 Deserialized RNG: {:?}", deserialized_rng); - - // Creating a custom Mersenne Twister configuration. - let params = MersenneTwisterParams { - matrix_a: 0x9908b0df, - upper_mask: 0x80000000, - lower_mask: 0x7fffffff, - tempering_mask_b: 0x9d2c5680, - tempering_mask_c: 0xefc60000, - }; - - // Creating a custom Mersenne Twister configuration. - let config = MersenneTwisterConfig::new_custom(624, 397, params); - println!("🦀 Custom MersenneTwisterConfig: {}", config); - - // Serialize to a file - MersenneTwisterConfig::serialize_to_file(&config, "config.json") - .unwrap(); - println!("🦀 Serialized MersenneTwisterConfig to file"); - - // Deserialize from a file - let deserialized_config = - MersenneTwisterConfig::deserialize_from_file("config.json") - .unwrap(); - println!( - "🦀 Deserialized MersenneTwisterConfig from file: {:?}", - deserialized_config - ); + // ... PRNG Examples ... + + // Creating a random 32-bit unsigned integer using a pseudo-random number generator (PRNG). + let rand_pseudo = rand_pseudo!(rng); + println!("🦀 Random u32 using the PRNG: {}", rand_pseudo); + + // Seeding the PRNG with a specific value to get deterministic outputs. + rand_seed!(rng, 42); + let rand_seed = rand_pseudo!(rng); + println!("🦀 Random u32 using the seeded PRNG: {}", rand_seed); + + // Altering the state of the PRNG to vary its output. + rand_twist!(rng); + let rand_twist = rand_pseudo!(rng); + println!( + "🦀 Random u32 after twisting the PRNG state: {}", + rand_twist + ); + + // Retrieving the current state index (MTI) of the Mersenne Twister RNG. + let mti_value = Random::mti(&rng); + println!("🦀 MTI value: {}", mti_value); + + // Generate a random even number. + let even_number = + (0..).map(|_| rng.rand()).find(|&n| n % 2 == 0).unwrap(); + println!("🦀 Random even number: {}", even_number); + + // Pre-generating a large number of random values for performance. + let mut pre_generated_numbers = Vec::new(); + for _ in 0..1000 { + pre_generated_numbers.push(rng.rand()); + } + println!( + "🦀 Pre-generated random numbers: {:?}", + pre_generated_numbers + ); + + // Comparing `vrd` RNG with Rust's default RNG. + let default_rng_number = rand::random::(); + let vrd_rng_number = rng.rand(); + println!( + "🦀 Default RNG number: {}, `vrd` RNG number: {}", + default_rng_number, vrd_rng_number + ); + + // ... Serialization Examples ... + // Serialize the random number generator to JSON. + let serialized_rng = serde_json::to_string(&rng); + match serialized_rng { + Ok(ref serialized) => { + println!("🦀 Serialized RNG: {}", serialized) + } + Err(ref e) => eprintln!("🔴 Serialization error: {}", e), + } + + // Deserialize the random number generator from JSON. + let deserialized_rng: Result = + serde_json::from_str(&serialized_rng.unwrap()); + match deserialized_rng { + Ok(deserialized) => { + println!("🦀 Deserialized RNG: {:?}", deserialized) + } + Err(e) => eprintln!("🔴 Deserialization error: {}", e), + } + + // Creating a custom Mersenne Twister configuration. + let params = MersenneTwisterParams { + matrix_a: 0x9908b0df, + upper_mask: 0x80000000, + lower_mask: 0x7fffffff, + tempering_mask_b: 0x9d2c5680, + tempering_mask_c: 0xefc60000, + }; + + // Creating a custom Mersenne Twister configuration. + let config = MersenneTwisterConfig::new_custom(624, 397, params); + println!("🦀 Custom MersenneTwisterConfig: {}", config); + + // Serialize to a file + if let Err(e) = + MersenneTwisterConfig::serialize_to_file(&config, "config.json") + { + eprintln!("🔴 Error serializing to file: {}", e); + } else { + println!("🦀 Serialized MersenneTwisterConfig to file"); + } + + // Deserialize from a file + let deserialized_config = + MersenneTwisterConfig::deserialize_from_file("config.json"); + match deserialized_config { + Ok(deserialized) => println!( + "🦀 Deserialized MersenneTwisterConfig from file: {:?}", + deserialized + ), + Err(e) => eprintln!("🔴 Deserialization error: {}", e), + } }