codecov unsafe forbidden

SmolPRNG

This is a small PRNG library/framwork written in pure Rust, that is a translation of another project of mine, SmallPRNG. The main goal of this project is to not implement every feature possible but to provide a general framework for implmenting PRNG algorithms to test monte carlo codes. This was made primarilly as a educational project of learning Rust and it's features but I hope that this can be used for productive projects like SmallPRNG was.

To live up to the name of SmolPRNG there are less then 1000 lines of code but implements over 22 different algorithms out of the box, can sample from 15 statistical distributions this includes all code + tests + docs + benchs.

SmolPRNG is performance competative to the Rand Rust crate and is much more straightforward to extend.

Features

Generate Numbers

Generating random numbers is straight forward after initilizing a PRNG object

```rust let prng = PRNG{generator: JsfGenerator::default()};

let randbool = prng.genbool(); // Generates a random bool

let randu8 = prng.genu8(); //Generates a random u8 let randu16 = prng.genu16(); //Generates a random u16 let randu32 = prng.genu32(); //Generates a random u32 let randu64 = prng.genu64(); //Generates a random u64 let randu128 = prng.genu128(); //Generates a random u128

let randf32 = prng.genf32(); //Generates a random f32 let randf64 = prng.genf64(); //Generates a random f64 ```

Implement Your own algorithm

Here is an example of injecting a new algorithm to generate pseudo-random numbers by impl the Algorithm trait on a struct. Availible Outputs are u8,u16,u32,u64,u128.

```rust struct StepGenerator{ state: u32, }

impl Algorithm for StepGenerator { type Output = u32;

fn gen(&mut self) -> Self::Output { self.data = self.data.overflowing_add(1).0; self.data } }

// somewhat gross macro, that adds the traits Iterator, Default, and From where U in {u8, u16, u32, u64, u128} prngsetup! {StepGenerator, StepGenerator, data, make1_u32} ```

Using this, we can then create a PRNG struct from

rust // create step generator state from output of SplitMix64 algorithm of a u32 seed let step_generator = StepGenerator::from(12765u32); let prng = PRNG{generator: step_generator}

Performance

This is an overview of the performance of the package, running on an intel 12700k CPU. This is categorized as three different benchmarks, generating a 1024 byte buffer filled with random numbers, summing 1 million randomly generated f64 and then 1 million generated f32. The fastest Step generator result is used as a baseline, as this is the algorithm defined by adding 1 and returning state. It is the simplest possible algorithm other than the constant generator.

This is not exhaustive but to cover the broad strokes of the performance characters.

Generating 1024 byte Buffer

| | Time | Bandwidth | |----------------|:-----:|:---------:| | Step Generator | 49ns | 20.4 GB/s | | Xoshiro256+ | 87ns | 11.5 GB/s | | SplitMix64 | 92ns | 10.9 GB/s | | JSFLarge | 105ns | 9.5 GB/s |

Summing 1 million randomly generated f32

| | Time | Time per f32 | |----------------|:-------:|:------------:| | Step Generator | 0.28 ms | 0.28 ns | | SCFSmall | 0.51 ms | 0.51 ns | | Xoshiro256+ | 0.61 ms | 0.61 ns | | SplitMix64 | 0.65 ms | 0.65 ns | | JSFLarge | 0.83 ms | 0.83 ns |

Summing 1 million randomly generated f64

| | Time | Time per f64 | |----------------|:-------:|:------------:| | Step Generator | 0.32 ms | 0.32 ns | | Xoshiro256+ | 0.62 ms | 0.62 ns | | SplitMix64 | 0.63 ms | 0.63 ns | | JSFLarge | 0.79 ms | 0.79 ns |