diff --git a/Cargo.lock b/Cargo.lock index 70e1857..4cf4834 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,9 +22,9 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" [[package]] name = "assert_cmd" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d6b683edf8d1119fe420a94f8a7e389239666aa72e65495d91c00462510151" +checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6" dependencies = [ "anstyle", "bstr", @@ -58,6 +58,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "bstr" version = "1.4.0" @@ -128,14 +134,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", - "bitflags", - "clap_lex", + "bitflags 1.3.2", + "clap_lex 0.2.4", "indexmap", "strsim", "termcolor", "textwrap", ] +[[package]] +name = "clap" +version = "4.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1" +dependencies = [ + "anstyle", + "clap_lex 0.6.0", +] + [[package]] name = "clap_lex" version = "0.2.4" @@ -145,6 +170,12 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + [[package]] name = "console" version = "0.15.5" @@ -160,19 +191,19 @@ dependencies = [ [[package]] name = "criterion" -version = "0.4.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" dependencies = [ "anes", - "atty", "cast", "ciborium", - "clap", + "clap 4.4.10", "criterion-plot", + "is-terminal", "itertools", - "lazy_static", "num-traits", + "once_cell", "oorandom", "plotters", "rayon", @@ -482,6 +513,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.1", + "rustix 0.38.25", + "windows-sys 0.48.0", +] + [[package]] name = "itertools" version = "0.10.5" @@ -514,9 +556,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.142" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "linux-raw-sys" @@ -524,6 +566,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" +[[package]] +name = "linux-raw-sys" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" + [[package]] name = "log" version = "0.4.17" @@ -659,18 +707,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -733,7 +781,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -763,11 +811,24 @@ version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", - "linux-raw-sys", + "linux-raw-sys 0.3.7", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys 0.4.11", "windows-sys 0.48.0", ] @@ -794,22 +855,22 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.162" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.162" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.43", ] [[package]] @@ -858,9 +919,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" dependencies = [ "proc-macro2", "quote", @@ -876,7 +937,7 @@ dependencies = [ "cfg-if", "fastrand", "redox_syscall", - "rustix", + "rustix 0.37.19", "windows-sys 0.45.0", ] @@ -925,11 +986,12 @@ checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "vrd" -version = "0.0.4" +version = "0.0.5" dependencies = [ "assert_cmd", "criterion", "rand", + "serde", ] [[package]] @@ -1214,7 +1276,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "464ca5c2bac1d1fcdbef9da6c09c6a14f2c7ac6c8845f574ab12065a2b72bb8b" dependencies = [ "anyhow", - "clap", + "clap 3.2.25", "derive_builder", "dialoguer", "duct", diff --git a/Cargo.toml b/Cargo.toml index 8662b3d..2168dc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,24 +1,17 @@ [package] -authors = ["Sebastien Rousseau "] +authors = ["The vrd contributors "] build = "build.rs" categories = ['Algorithms', 'Encoding','Parser implementations','Data structures'] description = "A Rust library for generating random and pseudo-random numbers based on the Mersenne Twister algorithm" -documentation = "https://lib.rs/crates/vrd" +documentation = "https://docs.rs/vrd" edition = "2021" exclude = [ "/.git/*", "/.github/*", "/.gitignore", "/.vscode/*" - ] +] homepage = "https://vrdlib.one" -keywords = ["entropy", "rand", "random-number", "random", "vrd"] -license = "MIT OR Apache-2.0" -name = "vrd" -readme = "README.md" -repository = "https://github.com/sebastienrousseau/vrd" -rust-version = "1.69.0" -version = "0.0.4" include = [ "/CONTRIBUTING.md", "/LICENSE-APACHE", @@ -32,6 +25,13 @@ include = [ "/tests/**", "/xtask/**", ] +keywords = ["entropy", "rand", "random-number", "random", "vrd"] +license = "MIT OR Apache-2.0" +name = "vrd" +readme = "README.md" +repository = "https://github.com/sebastienrousseau/vrd" +rust-version = "1.71.1" +version = "0.0.5" [workspace] members = ["xtask"] @@ -46,10 +46,11 @@ debug = true [dependencies] rand = "0.8.5" +serde = { version = "1.0.193", features = ["derive"] } [dev-dependencies] -assert_cmd = "2.0.11" -criterion = "0.4.0" +assert_cmd = "2.0.12" +criterion = "0.5.1" [lib] crate-type = ["lib"] @@ -75,16 +76,16 @@ rpath = false strip = false [profile.release] -codegen-units = 1 # Compile crates one after another so the compiler can optimize better -debug = false # Disable debug information -debug-assertions = false # Disable debug assertions -incremental = false # Disable incremental compilation -lto = true # Enables link to optimizations -opt-level = "s" # Optimize for binary size -overflow-checks = false # Disable overflow checks -panic = "abort" # Strip expensive panic clean-up logic -rpath = false # Disable rpath -strip = "symbols" # Automatically strip symbols from the binary. +codegen-units = 1 +debug = false +debug-assertions = false +incremental = false +lto = true +opt-level = "s" +overflow-checks = false +panic = "abort" +rpath = false +strip = "symbols" [profile.test] codegen-units = 256 diff --git a/README.md b/README.md index 68ae506..58ba9ba 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Mersenne Twister algorithm. `Random (VRD)` is a Rust library for generating high-quality random numbers based on the Mersenne Twister algorithm. -The Mersenne Twister is a pseudorandom number generator (PRNG) that is often used in computer simulations and games. It is a fast and reliable PRNG. +The `Random` struct in this library provides a robust interface for generating a variety of random numbers using the Mersenne Twister algorithm. Additionally, the `MersenneTwisterConfig` struct allows for advanced configuration of the algorithm. The Random (VRD) is used to generate random numbers using the Mersenne Twister algorithm. It generates pseudorandom integers uniformly distributed in 0..(2^32 - 1) starting from any odd seed in 0..(2^32 - 1). @@ -126,7 +126,7 @@ To use the `Random (VRD)` library in your project, add the following to your `Ca ```toml [dependencies] -vrd = "0.0.4" +vrd = "0.0.5" ``` Add the following to your `main.rs` file: diff --git a/benches/criterion.rs b/benches/criterion.rs index ce7c88b..ba12875 100644 --- a/benches/criterion.rs +++ b/benches/criterion.rs @@ -1,5 +1,8 @@ -// Copyright © 2023 Random (VRD) library. All rights reserved. +// Copyright © 2023-2024 Random (VRD) library. All rights reserved. // SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is part of the `Random (VRD)` library, a Rust implementation of the Mersenne Twister RNG. +// See LICENSE-APACHE.md and LICENSE-MIT.md in the repository root for full license information. + //! Benchmarks using the `criterion` crate. //! //! This file contains benchmarks that use the `criterion` crate for performance testing. diff --git a/build.rs b/build.rs index 227ffcb..63ec026 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,4 @@ -// Copyright © 2023 Random (VRD) library. All rights reserved. +// Copyright © 2023-2024 Random (VRD) library. All rights reserved. // SPDX-License-Identifier: Apache-2.0 OR MIT //! This is the main function for the build script. diff --git a/examples/example.rs b/examples/example.rs index 8b304b1..2290f6b 100644 --- a/examples/example.rs +++ b/examples/example.rs @@ -1,125 +1,127 @@ -// Copyright © 2023 Random (VRD) library. All rights reserved. +// Copyright © 2023-2024 Random (VRD) library. All rights reserved. // SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is part of the `Random (VRD)` library, a Rust implementation of the Mersenne Twister RNG. +// See LICENSE-APACHE.md and LICENSE-MIT.md in the repository root for full license information. + //! Example code using the `vrd` crate. //! -//! This example demonstrates the usage of the `vrd` crate. -//! It imports the `Random` trait and other items from the `vrd` crate. -//! The example code showcases the generation of random numbers. -//! -//! # Example -//! -//! ``` -//! extern crate vrd; -//! -//! use self::vrd::Random; -//! use vrd::*; -//! -//! fn main() { -//! let random_number = u32::random(); -//! println!("Random number: {}", random_number); -//! } -//! ``` +//! This example demonstrates the usage of the `vrd` crate for generating random numbers. +//! It covers a variety of functionalities provided by the `vrd` crate, including generating +//! random booleans, integers, floating-point numbers, and more complex operations like seeding +//! and state manipulation of the random number generator (RNG). + extern crate vrd; use self::vrd::Random; use vrd::*; fn main() { - // Create a new random boolean with 50% probability of being true + // Generating a random boolean with a 50% chance of being true. + // This demonstrates the usage of Random::bool method. let bool: bool = Random::bool(&mut Random::new(), 0.5); println!("🦀 Random::bool(): ✅ {bool}"); - // Create a new random number generator + // Initializing a new random number generator (RNG) instance. let mut rng = Random::new(); println!("🦀 Random::new(): ✅ {rng}"); - // Get the default random number generator + // Accessing the default RNG provided by the `vrd` crate. let default = Random::default(); println!("🦀 Random::default(): ✅ {default}"); - // Generate a random number between 0 and u32::max_value() + // Generating a random integer between 0 and the maximum value a u32 can hold. let random = rng.rand(); println!("🦀 Random::random(): ✅ {random}"); - // Seed the PRNG with a given value + // Seeding the RNG with a specific value to ensure reproducible results. let seed_value = 12345; let mut rng = Random::new(); - rng.seed(seed_value); // Seed the RNG - println!("🦀 Random::seed(): ✅ {}", seed_value); // Print the seed value + rng.seed(seed_value); + println!("🦀 Random::seed(): ✅ {}", seed_value); - // Generate a vector of random bytes with a given length + // Creating a vector of 1000 random bytes. let bytes = Random::bytes(&mut rng, 1000); println!("🦀 Random::bytes(): ✅ {bytes:?}"); - // Generate a random float between 0 and 1 + // Generating a random floating-point number between 0 and 1. let float = rng.rand() as f32 / 0x7FFF as f32; println!("🦀 Random::float(): ✅ {float}"); - // Generate a random usize + // Producing a random usize value. let int = rng.rand() as usize; println!("🦀 Random::int(): ✅ {int}"); - // Generate a random integer within a range of values + // Generating a random integer within the specified range (0 to 100). let mut rng = Random::new(); let min = 0; let max = 100; - - // Generate a random integer within a range let rand_int = rand_int!(rng, min, max); - println!( - "🦀 Random integer between {} and {}: {}", - min, max, rand_int - ); - - // Generate a random number within a range - let rand_range = - rand_float!(rng) * (max as f32 - min as f32) + min as f32; + println!("🦀 Random integer between {} and {}: {}", min, max, rand_int); + + // 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 0 and 1: {}", rand_range); - // Generate a random 32-bit unsigned integer within a range + // Creating a random 32-bit unsigned integer within a specified range. let rand_uint = random_range!(rng, 0, u32::max_value()); - println!( - "🦀 Random u32 between 0 and u32::max_value(): {}", - rand_uint - ); + println!("🦀 Random u32 between 0 and u32::max_value(): {}", rand_uint); - // Generate a random boolean with a given probability + // Generating a random boolean with a 50% probability. let rand_bool = rand_bool!(rng, 0.5); println!("🦀 Random boolean with 50% probability: {}", rand_bool); - // Generate a vector of random bytes with a given length + // Creating a vector of 10 random bytes. let rand_bytes = rand_bytes!(rng, 10); println!("🦀 Random bytes: {:?}", rand_bytes); - // Generate a random char within the range 'a'..='z' + // 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); - // Generate a random element from a slice of values + // 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 - ); + println!("🦀 Random element from [1, 2, 3, 4, 5]: {:?}", rand_choose); - // Generate a random float + // Generating a random floating-point number. let rand_float = rand_float!(rng); println!("🦀 Random float: {}", rand_float); - // Generate a random 32-bit unsigned integer + // 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); - // Seed the PRNG with a given value + // 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); - // Twist the state of the PRNG + // 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 - ); + println!("🦀 Random u32 after twisting the PRNG state: {}", rand_twist); + + // Generating a random double-precision floating-point number. + let random_double = Random::double(&mut rng); + println!("🦀 Random double: {}", random_double); + + // 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); + } diff --git a/src/lib.rs b/src/lib.rs index 77be38d..7b6f8bb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,8 @@ -// Copyright © 2023 Random (VRD) library. All rights reserved. +// Copyright © 2023-2024 Random (VRD) library. All rights reserved. // SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is part of the `Random (VRD)` library, a Rust implementation of the Mersenne Twister RNG. +// See LICENSE-APACHE.md and LICENSE-MIT.md in the repository root for full license information. + //! //! # `Random (VRD)` 🦀 //! @@ -45,7 +48,7 @@ //! //! ```toml //! [dependencies] -//! vrd = "0.0.4" +//! vrd = "0.0.5" //! serde = { version = "1.0.160", features = ["derive"] } //! ``` //! @@ -105,65 +108,77 @@ use rand::thread_rng; use rand::Rng; -/// The `macros` module contains functions for generating macros. -pub mod macros; - -/// N is the number of elements in the array used for the Mersenne -/// Twister algorithm. Its value is set to 624 for optimal performance. -const N: usize = 624; - -/// M is the number of elements to skip in the array used for the -/// Mersenne Twister algorithm. Its value is set to 397 for optimal -/// performance. -const M: usize = 397; - -/// MATRIX_A is a constant value used in the Mersenne Twister algorithm. -const MATRIX_A: u32 = 0x9908b0df; - -/// UPPER_MASK is a constant value used in the Mersenne Twister -/// algorithm. -const UPPER_MASK: u32 = 0x80000000; - -/// LOWER_MASK is a constant value used in the Mersenne Twister -/// algorithm. -const LOWER_MASK: u32 = 0x7fffffff; +/// The `mersenne_twister` module contains the implementation of the Mersenne Twister algorithm. +pub mod mersenne_twister; -/// TEMPERING_MASK_B is a constant value used in the Mersenne Twister -/// algorithm. -const TEMPERING_MASK_B: u32 = 0x9d2c5680; +// Re-export MersenneTwisterConfig so it's accessible from outside the crate +pub use mersenne_twister::MersenneTwisterConfig; -/// TEMPERING_MASK_C is a constant value used in the Mersenne Twister -/// algorithm. -const TEMPERING_MASK_C: u32 = 0xefc60000; +/// The `macros` module contains functions for generating macros. +pub mod macros; #[non_exhaustive] #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -/// The `Random` struct is used to generate random numbers using the -/// Mersenne Twister algorithm. +/// The `Random` struct is used to generate random numbers using the Mersenne Twister algorithm. /// -/// It contains an array of unsigned 32-bit integers and an index used -/// to generate random numbers. The array contains 624 elements and the -/// index is used to generate random numbers from the array. +/// This struct maintains an internal state for random number generation and provides methods to generate various types of random numbers. /// -/// The index is incremented after each random number is generated. -/// When the index reaches 624, the array is reinitialized and the index -/// is reset to 0. +/// # Initialization +/// The random number generator can be initialized with the `new` method, which seeds the generator with a default value. +/// ``` +/// use vrd::Random; +/// let mut rng = Random::new(); +/// ``` + +/// # Random Number Generation pub struct Random { /// The array of unsigned 32-bit integers used to generate random /// numbers - pub mt: [u32; N], + pub mt: [u32; 624], /// The current index of the array used in the generation of random /// numbers pub mti: usize, } impl Random { - /// Returns a random bool with a probability that can be set. + /// Returns a random bool with a specified probability. + /// + /// The `bool` method returns a random boolean value. The probability of returning `true` is determined + /// by the `probability` parameter. This method is useful for generating random boolean outcomes, like + /// simulating a coin flip. + /// + /// # Arguments + /// * `probability` - A f64 value representing the probability of the function returning `true`. + /// This should be a value between 0.0 and 1.0, where 0.0 always returns `false` and 1.0 always returns `true`. + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// let random_bool = rng.bool(0.5); // 50% chance to get true + /// ``` + /// + /// # Panics + /// Panics if `probability` is not between 0.0 and 1.0. pub fn bool(&mut self, probability: f64) -> bool { thread_rng().gen_bool(probability) } - /// Returns a vector of random bytes of the given length + /// Generates a vector of random bytes of the specified length. + /// + /// # Arguments + /// * `len` - The length of the byte vector to be generated. + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// let random_bytes = rng.bytes(10); // Generates 10 random bytes + /// println!("Random bytes: {:?}", random_bytes); + /// ``` + /// + /// # Returns + /// A `Vec` containing `len` randomly generated bytes. pub fn bytes(&mut self, len: usize) -> Vec { let mut res = Vec::with_capacity(len); for _ in 0..len { @@ -173,12 +188,42 @@ impl Random { res } - /// Returns a random char within the range 'a'..='z' + /// Generates a random character within the range 'a' to 'z'. + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// let random_char = rng.char(); // Generates a random lowercase character + /// println!("Random char: {}", random_char); + /// ``` + /// + /// # Returns + /// A `char` representing a randomly chosen lowercase letter from 'a' to 'z'. pub fn char(&mut self) -> char { thread_rng().gen_range('a'..='z') } - /// Returns a random element from a slice of values + /// Selects a random element from a provided slice. + /// + /// # Arguments + /// * `values` - A slice of values from which to select a random element. + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// let items = [1, 2, 3, 4, 5]; + /// let random_item = rng.choose(&items); + /// println!("Random item from the array: {:?}", random_item); + /// ``` + /// + /// # Returns + /// An `Option<&T>` which is `Some(&T)` if the slice is not empty, containing a randomly chosen element from the slice. + /// Returns `None` if the slice is empty. + /// + /// # Panics + /// Does not panic under normal operation. pub fn choose<'a, T>(&'a mut self, values: &'a [T]) -> Option<&T> { if values.is_empty() { return None; @@ -188,38 +233,152 @@ impl Random { Some(&values[index]) } - /// Returns a random float. + /// Generates a random floating-point number in the range [0.0, 1.0). + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// let random_float = rng.float(); // Generates a random float + /// println!("Random float: {}", random_float); + /// ``` + /// + /// # Returns + /// A `f32` representing a randomly generated floating-point number. + /// + /// # Notes + /// The generated float is inclusive of 0.0 and exclusive of 1.0. pub fn float(&mut self) -> f32 { thread_rng().gen::() as f32 } - /// Returns a random integer within the given range + /// Generates a random integer within a specified range. + /// + /// # Arguments + /// * `min` - The lower bound of the range (inclusive). + /// * `max` - The upper bound of the range (inclusive). + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// let random_int = rng.int(1, 10); // Generates a random integer between 1 and 10 + /// println!("Random integer between 1 and 10: {}", random_int); + /// ``` + /// + /// # Returns + /// An `i32` representing a randomly generated integer within the specified range. + /// + /// # Panics + /// Panics if `min` is greater than `max`. pub fn int(&mut self, min: i32, max: i32) -> i32 { thread_rng().gen_range(min..=max) } - /// Returns a random unsigned integer within the given range + /// Generates a random unsigned integer within a specified range. + /// + /// # Arguments + /// * `min` - The lower bound of the range (inclusive). + /// * `max` - The upper bound of the range (inclusive). + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// let random_uint = rng.uint(1, 100); // Generates a random unsigned integer between 1 and 100 + /// println!("Random unsigned integer between 1 and 100: {}", random_uint); + /// ``` + /// + /// # Returns + /// A `u32` representing a randomly generated unsigned integer within the specified range. + /// + /// # Panics + /// Panics if `min` is greater than `max`. pub fn uint(&mut self, min: u32, max: u32) -> u32 { thread_rng().gen_range(min..=max) } - /// Returns a random double. + /// Generates a random double-precision floating-point number. + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// let random_double = rng.double(); // Generates a random double + /// println!("Random double: {}", random_double); + /// ``` + /// + /// # Returns + /// A `f64` representing a randomly generated double-precision floating-point number. + /// + /// # Notes + /// The generated double is a number in the range [0.0, 1.0). pub fn double(&mut self) -> f64 { thread_rng().gen::() } - /// Return the value of the `mti` field + /// Returns the current index of the internal state array used in random number generation. + /// + /// This method is useful for inspecting the state of the random number generator. + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let rng = Random::new(); + /// let current_index = rng.mti(); + /// println!("Current index of the RNG state array: {}", current_index); + /// ``` + /// + /// # Returns + /// The current index (`usize`) of the internal state array (`mt`) used by the Mersenne Twister algorithm. pub fn mti(&self) -> usize { self.mti } - /// Set the value of the `mti` field + /// Sets the value of the current index of the internal state array used in random number generation. + /// + /// # Arguments + /// * `value` - The new index value to set for the internal state array. + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// rng.set_mti(100); // Sets the current index to 100 + /// assert_eq!(rng.mti(), 100); + /// ``` + /// + /// # Notes + /// - This method allows for manual manipulation of the internal state of the random number generator. + /// - It should be used with caution, as incorrect values can affect the quality of the generated random numbers. pub fn set_mti(&mut self, value: usize) { self.mti = value; } - /// Returns new random number generator + /// Creates a new instance of the `Random` struct, initializing the internal state for random number generation. + /// + /// This method seeds the random number generator with a default value obtained from the thread's random number generator. + /// + /// + /// The `new` method initializes the `Random` struct. It sets the initial state of the `mt` array + /// using a default seed obtained from the system's RNG. This seeding process is crucial for ensuring + /// that each instance of `Random` produces a unique and unpredictable sequence of numbers. + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); // Creates a new instance of Random + /// let random_number = rng.rand(); // Generates a random number + /// println!("Random number: {}", random_number); + /// ``` + /// + /// # Returns + /// A new instance of `Random` with its internal state initialized for random number generation. + /// + /// # Notes + /// - The internal state is initialized with a seed value, ensuring that each instance of `Random` produces a unique sequence of random numbers. + /// - The `new` method ensures that the internal state is appropriately set up for the Mersenne Twister algorithm. pub fn new() -> Self { + const N: usize = 624; let mut rng = Random { mt: [0; N], mti: N + 1, @@ -235,7 +394,24 @@ impl Random { rng } - /// Returns pseudo random number + /// Generates a pseudo-random number by combining multiple random number generations. + /// + /// This method enhances the randomness by XOR-ing multiple calls to the basic random number generator. + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// let pseudo_random_number = rng.pseudo(); // Generates a pseudo-random number + /// println!("Pseudo-random number: {}", pseudo_random_number); + /// ``` + /// + /// # Returns + /// A `u32` representing a pseudo-random number generated by combining multiple random number generations. + /// + /// # Notes + /// - This method is intended to provide a more complex random number by aggregating multiple random number generations. + /// - It might be useful in scenarios where a single call to the basic random number generator does not provide sufficient randomness. pub fn pseudo(&mut self) -> u32 { let mut res = self.rand(); for _ in 0..31 { @@ -244,10 +420,32 @@ impl Random { res } - /// Returns a random 32-bit unsigned integer. + /// Generates a random 32-bit unsigned integer using the Mersenne Twister algorithm. + /// + /// This method is the core function of the `Random` struct, providing the basic mechanism for generating random numbers. + /// + /// The `rand` method generates a random 32-bit number using the current state of the `mt` array. + /// It applies a series of bitwise transformations for tempering, which refines the output and improves + /// the statistical properties of the generated numbers. + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// let random_number = rng.rand(); // Generates a random 32-bit unsigned integer + /// println!("Random number: {}", random_number); + /// ``` + /// + /// # Returns + /// A `u32` representing a randomly generated 32-bit unsigned integer. + /// + /// # Notes + /// - This method updates the internal state of the random number generator each time it is called. + /// - If the internal index (`mti`) reaches the threshold, it automatically reinitializes the internal state array. pub fn rand(&mut self) -> u32 { - if self.mti >= N { - if self.mti == N + 1 { + let config = MersenneTwisterConfig::default(); + if self.mti >= config.n { + if self.mti == config.n + 1 + 1 { self.seed(5489); } self.twist(); @@ -256,24 +454,89 @@ impl Random { let mut y = self.mt[self.mti]; self.mti += 1; y ^= y >> 11; - y ^= (y << 7) & TEMPERING_MASK_B; - y ^= (y << 15) & TEMPERING_MASK_C; + y ^= (y << 7) & config.tempering_mask_b; + y ^= (y << 15) & config.tempering_mask_c; y ^= y >> 18; y } - /// Returns a random 32-bit unsigned integer within a given range. + /// Generates a random 32-bit unsigned integer within a specified range. + /// + /// # Arguments + /// * `min` - The lower bound of the range (inclusive). + /// * `max` - The upper bound of the range (exclusive). + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// let random_number = rng.random_range(10, 20); // Generates a random number between 10 (inclusive) and 20 (exclusive) + /// println!("Random number between 10 and 20: {}", random_number); + /// ``` + /// + /// # Returns + /// A `u32` representing a randomly generated number within the specified range. + /// + /// # Panics + /// Panics if `min` is not less than `max`. + /// + /// # Notes + /// - This method offers a convenient way to specify the range for random number generation. pub fn random_range(&mut self, min: u32, max: u32) -> u32 { min + self.rand() % (max - min) } - /// Returns a random number within a given range. + /// Generates a random number within a specified range of integer values. + /// + /// # Arguments + /// * `min` - The lower bound of the range (inclusive). + /// * `max` - The upper bound of the range (inclusive). + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// let random_number = rng.range(1, 100); // Generates a random number between 1 and 100 + /// println!("Random number between 1 and 100: {}", random_number); + /// ``` + /// + /// # Returns + /// An `i32` representing a randomly generated number within the specified range. + /// + /// # Panics + /// Panics if `min` is greater than `max`. + /// + /// # Notes + /// - This method is similar to `int` but allows for a different interface for specifying the range. pub fn range(&mut self, min: i32, max: i32) -> i32 { thread_rng().gen_range(min..=max) } - /// Seeds the random number generator with a given value. + /// Seeds the random number generator with a specified value. + /// + /// This method initializes the internal state array of the generator with a given seed, affecting the sequence of random numbers generated. + /// + /// The constant 1812433253u32 is used in the seeding process. It's derived from the fractional part + /// of the square root of 2. This particular value is chosen to provide good statistical properties + /// for the initial array of numbers. + /// + /// # Arguments + /// * `seed` - A `u32` value used to seed the generator. + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// rng.seed(12345); // Seeds the random number generator + /// let random_number = rng.rand(); // Generates a random number based on the new seed + /// println!("Random number with seed 12345: {}", random_number); + /// ``` + /// + /// # Notes + /// - Seeding the generator is essential for reproducibility of the random number sequence. + /// - Different seeds will produce different sequences, while the same seed will always produce the same sequence. pub fn seed(&mut self, seed: u32) { + const N: usize = 624; self.mt[0] = seed; for i in 1..N { self.mt[i] = 1812433253u32 @@ -283,16 +546,35 @@ impl Random { self.mti = N; } - /// Twists the state of the random number generator. + /// Performs the "twisting" operation to update the internal state array of the random number generator. + /// + /// This method is a key part of the Mersenne Twister algorithm, and it's called internally when the generator's index exceeds its predefined threshold. + /// + /// The `twist` method is a key part of the Mersenne Twister algorithm. It generates a new array of + /// 624 numbers based on the current array. This method uses bitwise operations and modular arithmetic + /// to transform the existing numbers into a new set, thereby 'twisting' the current state. This is + /// essential for maintaining the algorithm's long period and high-quality randomness. + /// + /// # Examples + /// ``` + /// use vrd::Random; + /// let mut rng = Random::new(); + /// rng.twist(); // Manually performs a twist operation + /// ``` + /// + /// # Notes + /// - This method modifies the internal state array, ensuring that future random numbers generated are different from the previous ones. + /// - It is typically not called directly by users of the `Random` struct, as it is automatically managed by the `rand` and other methods. pub fn twist(&mut self) { - for i in 0..N { - let x = (self.mt[i] & UPPER_MASK) - + (self.mt[(i + 1) % N] & LOWER_MASK); + let config = MersenneTwisterConfig::default(); + for i in 0..config.n { + let x = (self.mt[i] & config.upper_mask) + + (self.mt[(i + 1) % config.n] & config.lower_mask); let x_a = x >> 1; if x % 2 != 0 { - self.mt[i] = self.mt[(i + M) % N] ^ x_a ^ MATRIX_A; + self.mt[i] = self.mt[(i + config.m) % config.n] ^ x_a ^ config.matrix_a; } else { - self.mt[i] = self.mt[(i + M) % N] ^ x_a; + self.mt[i] = self.mt[(i + config.m) % config.n] ^ x_a; } } self.mti = 0; @@ -313,7 +595,28 @@ impl Default for Random { } } -/// This is the main entry point for the `Random (VRD)` library. +/// The main entry point for the `Random (VRD)` library. +/// +/// This function performs initial setup and checks before the library can be used. It also provides a basic interface for interacting with the library. +/// +/// # Returns +/// - `Ok(())` if the library initializes successfully. +/// - `Err(Box)` if there is an error during initialization. +/// +/// # Examples +/// ``` +/// use vrd::Random; +/// if let Err(e) = vrd::run() { +/// println!("Error initializing Random (VRD) library: {}", e); +/// } +/// ``` +/// +/// # Errors +/// - Returns a simulated error if the environment variable `VRD_TEST_MODE` is set to "1". This is typically used for testing purposes. +/// +/// # Notes +/// - The function prints a welcome message and a brief description of the library. +/// - It checks for the `VRD_TEST_MODE` environment variable to simulate an error, which can be useful for testing error handling in applications using this library. pub fn run() -> Result<(), Box> { if std::env::var("VRD_TEST_MODE").unwrap_or_default() == "1" { return Err("Simulated error".into()); diff --git a/src/macros.rs b/src/macros.rs index 471d44c..fb71d60 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,5 +1,8 @@ -// Copyright © 2023 Random (VRD) library. All rights reserved. +// Copyright © 2023-2024 Random (VRD) library. All rights reserved. // SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is part of the `Random (VRD)` library, a Rust implementation of the Mersenne Twister RNG. +// See LICENSE-APACHE.md and LICENSE-MIT.md in the repository root for full license information. + //! # Macros for the `Random (VRD)` crate. //! //! This module contains macros that simplify working with the @@ -39,12 +42,35 @@ macro_rules! random_range { }; } -/// Generate a random boolean with the provided probability using the -/// provided `Random (VRD)` struct +/// Generate a random boolean with a provided probability. +/// +/// # Examples +/// +/// ``` +/// #[macro_use] extern crate vrd; +/// # use vrd::Random; +/// # use vrd::rand_bool; +/// # fn main() { +/// # let mut rng = Random::new(); +/// // Generates a boolean with 50% probability of being true +/// # let value = rand_bool!(rng, 0.5); +/// # } +/// ``` +/// +/// # Panics +/// +/// Panics if probability is not between 0.0 and 1.0. #[macro_export] macro_rules! rand_bool { ($rng:expr, $probability:expr) => { - $rng.bool($probability) + { + let valid_range = 0.0..=1.0; + assert!( + valid_range.contains(&$probability), + "Probability must be between 0.0 and 1.0" + ); + $rng.bool($probability) + } }; } @@ -150,3 +176,4 @@ macro_rules! rand_twist { $rng.twist() }; } + diff --git a/src/main.rs b/src/main.rs index dd17bb0..ebe4004 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,7 @@ -// Copyright © 2023 Random (VRD) library. All rights reserved. +// Copyright © 2023-2024 Random (VRD) library. All rights reserved. // SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is part of the `Random (VRD)` library, a Rust implementation of the Mersenne Twister RNG. +// See LICENSE-APACHE.md and LICENSE-MIT.md in the repository root for full license information. //! This is the main entry point for the vrd application. fn main() { diff --git a/src/mersenne_twister.rs b/src/mersenne_twister.rs new file mode 100644 index 0000000..c6f184b --- /dev/null +++ b/src/mersenne_twister.rs @@ -0,0 +1,66 @@ +// Copyright © 2023-2024 Random (VRD) library. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is part of the `Random (VRD)` library, a Rust implementation of the Mersenne Twister RNG. +// See LICENSE-APACHE.md and LICENSE-MIT.md in the repository root for full license information. + +use serde::{Serialize, Deserialize}; + +#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +/// Configuration for the Mersenne Twister algorithm. +pub struct MersenneTwisterConfig { + /// The number of elements in the array used for the Mersenne Twister algorithm. + /// Its value is set to 624 for optimal performance. + pub n: usize, + + /// The number of elements to skip in the array used for the Mersenne Twister algorithm. + /// Its value is set to 397 for optimal performance. + pub m: usize, + + /// A constant value used in the Mersenne Twister algorithm. + pub matrix_a: u32, + + /// A constant value used in the Mersenne Twister algorithm. + pub upper_mask: u32, + + /// A constant value used in the Mersenne Twister algorithm. + pub lower_mask: u32, + + /// A constant value used in the Mersenne Twister algorithm. + pub tempering_mask_b: u32, + + /// A constant value used in the Mersenne Twister algorithm. + pub tempering_mask_c: u32, +} + +/// Implementation of the `MersenneTwisterConfig` struct. +impl MersenneTwisterConfig { + /// Creates a new `MersenneTwisterConfig` with default values. + /// + /// # Examples + /// + /// ``` + /// use vrd::MersenneTwisterConfig; + /// let config = MersenneTwisterConfig::new(); + /// ``` + pub fn new() -> MersenneTwisterConfig { + MersenneTwisterConfig { + // n is the number of elements in the array used for the Mersenne + // Twister algorithm. Its value is set to 624 for optimal performance. + n: 624, + // m is the number of elements to skip in the array used for the + // Mersenne Twister algorithm. Its value is set to 397 for optimal + // performance. + m: 397, // Default value for m + // matrix_a is a constant value used in the Mersenne Twister algorithm. + matrix_a: 0x9908b0df, + // upper_mask is a constant value used in the Mersenne Twister algorithm. + upper_mask: 0x80000000, // Default value for upper_mask + // lower_mask is a constant value used in the Mersenne Twister algorithm. + lower_mask: 0x7fffffff, + // tempering_mask_b is a constant value used in the Mersenne Twister algorithm. + tempering_mask_b: 0x9d2c5680, + // tempering_mask_c is a constant value used in the Mersenne Twister algorithm. + tempering_mask_c: 0xefc60000, // Default value for tempering_mask_c + } + } +} diff --git a/tests/test_lib.rs b/tests/test_lib.rs index c86af96..8a646f3 100644 --- a/tests/test_lib.rs +++ b/tests/test_lib.rs @@ -1,10 +1,14 @@ -// Copyright © 2023 Random (VRD) library. All rights reserved. +// Copyright © 2023-2024 Random (VRD) library. All rights reserved. // SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is part of the `Random (VRD)` library, a Rust implementation of the Mersenne Twister RNG. +// See LICENSE-APACHE.md and LICENSE-MIT.md in the repository root for full license information. + #[cfg(test)] mod tests { extern crate vrd; use vrd::Random; + use std::convert::TryInto; const N: usize = 624; diff --git a/tests/test_macros.rs b/tests/test_macros.rs index d00a4ec..5e86e3e 100644 --- a/tests/test_macros.rs +++ b/tests/test_macros.rs @@ -1,5 +1,7 @@ -// Copyright © 2023 Random (VRD) library. All rights reserved. +// Copyright © 2023-2024 Random (VRD) library. All rights reserved. // SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is part of the `Random (VRD)` library, a Rust implementation of the Mersenne Twister RNG. +// See LICENSE-APACHE.md and LICENSE-MIT.md in the repository root for full license information. #[cfg(test)] mod tests { @@ -8,21 +10,28 @@ mod tests { use vrd::Random; use vrd::*; + #[test] - fn test_random_range_macro() { + fn test_random_range_macro_within_bounds() { let mut rng = Random::new(); let min = 10; let max = 20; let num = random_range!(rng, min, max); - assert!(num >= min && num < max); + assert!(num >= min && num <= max, "Number should be within the given range."); } #[test] - fn test_rand_bool_macro() { + fn test_rand_bool_macro_always_true() { let mut rng = Random::new(); - let p = 1.0; // Set p to 1.0 to always generate true - let b = rand_bool!(rng, p); - assert!(b); + let b = rand_bool!(rng, 1.0); + assert!(b, "rand_bool should always return true with probability 1.0."); + } + + #[test] + fn test_rand_bool_macro_always_false() { + let mut rng = Random::new(); + let b = rand_bool!(rng, 0.0); + assert!(!b, "rand_bool should always return false with probability 0.0."); } #[test] @@ -30,49 +39,48 @@ mod tests { let mut rng = Random::new(); let len = 10; let bytes = rand_bytes!(rng, len); - assert_eq!(bytes.len(), len); + assert_eq!(bytes.len(), len, "Length of bytes should be equal to the specified length."); } #[test] - fn test_rand_char_macro() { + fn test_rand_char_macro_ascii_check() { let mut rng = Random::new(); let c = rand_char!(rng); assert!( - c.is_ascii_lowercase() - || c.is_ascii_uppercase() - || c.is_ascii_digit() + c.is_ascii_lowercase() || c.is_ascii_uppercase() || c.is_ascii_digit(), + "Generated character should be ASCII lowercase, uppercase, or digit." ); } #[test] - fn test_rand_choose_macro() { + fn test_rand_choose_macro_value_in_slice() { let mut rng = Random::new(); let values = vec![1, 2, 3, 4, 5]; let chosen = rand_choose!(rng, &values).unwrap(); - assert!(values.contains(chosen)); + assert!(values.contains(chosen), "Chosen value should be in the provided slice."); } #[test] - fn test_rand_float_macro() { + fn test_rand_float_macro_within_bounds() { let mut rng = Random::new(); let f = rand_float!(rng); - assert!((0.0..1.0).contains(&f)); + assert!((0.0..1.0).contains(&f), "Generated float should be within 0.0 and 1.0."); } #[test] - fn test_rand_int_macro() { + fn test_rand_int_macro_within_range() { let mut rng = Random::new(); let min = 10; let max = 20; let num = rand_int!(rng, min, max); - assert!(num >= min && num <= max); + assert!(num >= min && num <= max, "Generated integer should be within the specified range."); } #[test] - fn test_rand_pseudo_macro() { + fn test_rand_pseudo_macro_upper_bound() { let mut rng = Random::new(); let p = rand_pseudo!(rng); - assert!(p < 4294967295); + assert!(p < 4294967295, "Generated pseudo random number should be less than 4294967295."); } #[test] @@ -99,4 +107,39 @@ mod tests { let num = rng.rand(); assert!(num < 4294967295); } + + #[test] + fn test_random_range_macro_valid_range() { + let mut rng = Random::new(); + let min = 10; + let max = 20; + let num = random_range!(rng, min, max); + assert!(num >= min && num < max, "Number should be within the given range."); + } + + #[test] + fn test_rand_bool_macro_true() { + let mut rng = Random::new(); + let p = 1.0; // Set p to 1.0 to always generate true + let b = rand_bool!(rng, p); + assert!(b, "The probability of 1.0 should always return true."); + } + + #[test] + fn test_rand_bool_macro_false() { + let mut rng = Random::new(); + let p = 0.0; // Set p to 0.0 to always generate false + let b = rand_bool!(rng, p); + assert!(!b, "The probability of 0.0 should always return false."); + } + + #[test] + fn test_rand_int_macro_valid_range() { + let mut rng = Random::new(); + let min = 10; + let max = 20; + let num = rand_int!(rng, min, max); + assert!(num >= min && num <= max, "Number should be within the given range."); + } + } diff --git a/tests/test_main.rs b/tests/test_main.rs index abc7916..cc8fc38 100644 --- a/tests/test_main.rs +++ b/tests/test_main.rs @@ -1,3 +1,8 @@ +// Copyright © 2023-2024 Random (VRD) library. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is part of the `Random (VRD)` library, a Rust implementation of the Mersenne Twister RNG. +// See LICENSE-APACHE.md and LICENSE-MIT.md in the repository root for full license information. + #[cfg(test)] mod tests { use assert_cmd::prelude::*;