├── .github └── workflows │ └── rust.yml ├── .gitignore ├── Cargo.toml ├── LICENSE-MIT ├── README.md ├── benches ├── README.md └── benchmark_rand.rs ├── src └── lib.rs └── LICENSE-APACHE /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Build 20 | run: cargo build --verbose 21 | - name: Run tests 22 | run: cargo test --verbose 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | # only include lib files 13 | src/main.rs 14 | 15 | # Added by cargo 16 | # 17 | # already existing elements were commented out 18 | 19 | /target 20 | #Cargo.lock 21 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "alea" 3 | version = "0.2.2" 4 | authors = ["Jeff Shen "] 5 | edition = "2018" 6 | license = "MIT OR Apache-2.0" 7 | 8 | readme = "README.md" 9 | description = "Fast and easy zero-dep random number generation." 10 | repository = "https://github.com/al-jshen/alea" 11 | documentation = "https://docs.rs/alea" 12 | 13 | categories = ["algorithms"] 14 | 15 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 16 | 17 | [dependencies] 18 | 19 | [dev-dependencies] 20 | criterion = "0.3" 21 | fastrand = "1" 22 | rand = "0.8" 23 | rand_pcg = "0.3" 24 | rand_xorshift = "0.3" 25 | 26 | [[bench]] 27 | name = "benchmark_rand" 28 | harness = false 29 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Jeff Shen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # alea 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/alea.svg?style=for-the-badge&color=fc8d62&logo=rust)](https://crates.io/crates/alea) 4 | [![Documentation](https://img.shields.io/badge/docs.rs-alea-5E81AC?style=for-the-badge&labelColor=555555&logoColor=white)](https://docs.rs/alea) 5 | ![License](https://img.shields.io/crates/l/alea?label=License&style=for-the-badge&color=62a69b) 6 | 7 | A zero-dependency crate for fast number generation, with a focus on ease of use (no more passing `&mut rng` everywhere!). 8 | 9 | The implementation is based on [wyrand](https://github.com/wangyi-fudan/wyhash), a high-quality and fast generator. 10 | 11 | This crate is heavily inspired by [fastrand](https://github.com/smol-rs/fastrand). For some benchmarks, see [benches](benches). 12 | 13 | ## Usage 14 | 15 | Add the following to your `Cargo.toml`: 16 | 17 | ```rust 18 | [dependencies] 19 | alea = "0.2" 20 | ``` 21 | 22 | ## Examples 23 | 24 | Flip a coin: 25 | 26 | ```rust 27 | if alea::bool() { 28 | println!("heads"); 29 | } else { 30 | println!("tails"); 31 | } 32 | ``` 33 | 34 | Generate a `u64`: 35 | 36 | ```rust 37 | let u = alea::u64(); 38 | ``` 39 | 40 | Fill a vector with random integers in some range: 41 | 42 | ```rust 43 | let n = 1_000_000; 44 | 45 | let mut v = vec![0; n]; 46 | for i in 0..n { 47 | v[i] = alea::i32_in_range(-200, 150); 48 | } 49 | ``` 50 | 51 | Seed the generator to get reproducible results: 52 | 53 | ```rust 54 | alea::set_seed(10); 55 | ``` 56 | -------------------------------------------------------------------------------- /benches/README.md: -------------------------------------------------------------------------------- 1 | ## Benchmarks 2 | 3 | Benchmarks are run with [`criterion.rs`](https://github.com/bheisler/criterion.rs). The reported values are the means and standard deviations. To run the benchmarks yourself, clone the repository and run 4 | 5 | ``` 6 | cargo bench 7 | ``` 8 | 9 | | | alea | fastrand | rand | rand_pcg | 10 | | ------------ | ----------------------- | ----------------------- | ----------------------- | ----------------------- | 11 | | f64 | 2.0002 ns +/- 21.718 ps | 3.6868 ns +/- 40.030 ps | 4.7417 ns +/- 75.082 ps | 1.4531 ns +/- 73.249 ps | 12 | | f32 | 2.0911 ns +/- 87.985 ps | 2.6735 ns +/- 35.334 ps | 1.8259 ns +/- 34.666 ps | 1.4482 ns +/- 29.133 ps | 13 | | u64 | 2.0062 ns +/- 13.639 ps | 5.1602 ns +/- 132.48 ps | 4.6494 ns +/- 68.218 ps | 1.3561 ns +/- 7.0908 ps | 14 | | u32 | 1.9777 ns +/- 4.3646 ps | 4.5852 ns +/- 120.84 ps | 1.6488 ns +/- 55.921 ps | 1.3668 ns +/- 10.669 ps | 15 | | u64 in range | 4.5298 ns +/- 99.716 ps | 5.1845 ns +/- 240.30 ps | 9.8593 ns +/- 41.581 ps | 5.4817 ns +/- 21.622 ps | 16 | | u32 in range | 2.6764 ns +/- 32.698 ps | 4.3292 ns +/- 20.041 ps | 5.5542 ns +/- 45.249 ps | 4.9378 ns +/- 96.550 ps | 17 | | i64 | 2.0042 ns +/- 23.321 ps | 3.7119 ns +/- 44.196 ps | 4.6275 ns +/- 63.446 ps | 1.3506 ns +/- 17.385 ps | 18 | | i32 | 1.9826 ns +/- 10.443 ps | 2.6396 ns +/- 7.6008 ps | 1.6326 ns +/- 26.437 ps | 1.3668 ns +/- 7.4342 ps | 19 | | i64 in range | 4.4474 ns +/- 96.470 ps | 3.8003 ns +/- 16.704 ps | 5.6069 ns +/- 54.102 ps | 5.5278 ns +/- 84.057 ps | 20 | | i32 in range | 2.4168 ns +/- 19.926 ps | 2.7006 ns +/- 6.5716 ps | 2.8754 ns +/- 26.128 ps | 4.9530 ns +/- 179.12 ps | 21 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | cell::Cell, 3 | collections::hash_map::DefaultHasher, 4 | hash::{Hash, Hasher}, 5 | thread, 6 | time::Instant, 7 | }; 8 | 9 | #[derive(Debug)] 10 | /// Random number generator. 11 | pub struct Rng(Cell); 12 | 13 | const CF64: f64 = 1.0 / ((1u64 << 53) as f64); 14 | 15 | impl Rng { 16 | #[inline] 17 | pub fn new() -> Self { 18 | Self::with_seed({ 19 | let mut hasher = DefaultHasher::new(); 20 | Instant::now().hash(&mut hasher); 21 | thread::current().id().hash(&mut hasher); 22 | let hash = hasher.finish(); 23 | (hash << 1) | 1 24 | }) 25 | } 26 | 27 | #[inline] 28 | pub const fn with_seed(seed: u64) -> Self { 29 | Self { 0: Cell::new(seed) } 30 | } 31 | 32 | #[inline] 33 | pub fn get_seed(&self) -> u64 { 34 | self.0.get() 35 | } 36 | 37 | #[inline] 38 | pub fn set_seed(&self, seed: u64) { 39 | self.0.set(seed); 40 | } 41 | 42 | #[inline] 43 | pub fn u64(&self) -> u64 { 44 | self.0.set(self.0.get().wrapping_add(0xa0761d6478bd642f)); 45 | let s = self.0.get(); 46 | let t = u128::from(s) * (u128::from(s ^ 0xe7037ed1a0b428db)); 47 | ((t >> 64) as u64) ^ (t as u64) 48 | } 49 | 50 | #[inline] 51 | pub fn u32(&self) -> u32 { 52 | self.u64() as u32 53 | } 54 | 55 | #[inline] 56 | pub fn f64(&self) -> f64 { 57 | ((self.u64() >> 11) as f64) * CF64 58 | } 59 | 60 | #[inline] 61 | pub fn f32(&self) -> f32 { 62 | (self.u32() as f32) / (u32::MAX as f32) 63 | } 64 | 65 | #[inline] 66 | pub fn i64(&self) -> i64 { 67 | self.u64() as i64 68 | } 69 | 70 | #[inline] 71 | pub fn i32(&self) -> i32 { 72 | self.u32() as i32 73 | } 74 | 75 | #[inline] 76 | pub fn u64_less_than(&self, max: u64) -> u64 { 77 | let mut r = self.u64(); 78 | let mut hi = mul_high_u64(r, max); 79 | let mut lo = r.wrapping_mul(max); 80 | if lo < max { 81 | let t = max.wrapping_neg() % max; 82 | while lo < t { 83 | r = self.u64(); 84 | hi = mul_high_u64(r, max); 85 | lo = r.wrapping_mul(max); 86 | } 87 | } 88 | hi 89 | } 90 | 91 | #[inline] 92 | pub fn u32_less_than(&self, max: u32) -> u32 { 93 | let mut r = self.u32(); 94 | let mut hi = mul_high_u32(r, max); 95 | let mut lo = r.wrapping_mul(max); 96 | if lo < max { 97 | let t = max.wrapping_neg() % max; 98 | while lo < t { 99 | r = self.u32(); 100 | hi = mul_high_u32(r, max); 101 | lo = r.wrapping_mul(max); 102 | } 103 | } 104 | hi 105 | } 106 | 107 | #[inline] 108 | pub fn f64_less_than(&self, max: f64) -> f64 { 109 | assert!(max > 0., "max must be positive"); 110 | self.f64() * max 111 | } 112 | 113 | #[inline] 114 | pub fn f32_less_than(&self, max: f32) -> f32 { 115 | assert!(max > 0., "max must be positive"); 116 | self.f32() * max 117 | } 118 | 119 | #[inline] 120 | pub fn i64_less_than(&self, max: i64) -> i64 { 121 | self.u64_less_than(max as u64) as i64 122 | } 123 | 124 | #[inline] 125 | pub fn i32_less_than(&self, max: i32) -> i32 { 126 | self.u32_less_than(max as u32) as i32 127 | } 128 | 129 | #[inline] 130 | pub fn u64_in_range(&self, min: u64, max: u64) -> u64 { 131 | assert!(max > min, "max must be greater than min"); 132 | min + self.u64_less_than(max + 1 - min) 133 | } 134 | 135 | #[inline] 136 | pub fn u32_in_range(&self, min: u32, max: u32) -> u32 { 137 | assert!(max > min, "max must be greater than min"); 138 | min + self.u32_less_than(max + 1 - min) 139 | } 140 | 141 | #[inline] 142 | pub fn f64_in_range(&self, min: f64, max: f64) -> f64 { 143 | assert!(max > min, "max must be greater than min"); 144 | min + self.f64_less_than(max - min) 145 | } 146 | 147 | #[inline] 148 | pub fn f32_in_range(&self, min: f32, max: f32) -> f32 { 149 | assert!(max > min, "max must be greater than min"); 150 | min + self.f32_less_than(max - min) 151 | } 152 | 153 | #[inline] 154 | pub fn i64_in_range(&self, min: i64, max: i64) -> i64 { 155 | assert!(max > min, "max must be greater than min"); 156 | min + self.i64_less_than(max + 1 - min) 157 | } 158 | 159 | #[inline] 160 | pub fn i32_in_range(&self, min: i32, max: i32) -> i32 { 161 | assert!(max > min, "max must be greater than min"); 162 | min + self.i32_less_than(max + 1 - min) 163 | } 164 | 165 | #[inline] 166 | pub fn bool(&self) -> bool { 167 | self.f32() < 0.5 168 | } 169 | 170 | #[inline] 171 | pub fn wyhash_u64(&self) -> u64 { 172 | self.0.set(self.0.get() + 0x60bee2bee120fc15); 173 | let mut tmp: u128 = (self.0.get() as u128) * 0xa3b195354a39b70d; 174 | let m1: u64 = ((tmp >> 64) ^ tmp) as u64; 175 | tmp = (m1 as u128) * 0x1b03738712fad5c9; 176 | ((tmp >> 64) ^ tmp) as u64 177 | } 178 | 179 | #[inline] 180 | pub fn wyhash_f64(&self) -> f64 { 181 | (self.wyhash_u64() as f64) / (u64::MAX as f64) 182 | } 183 | } 184 | 185 | #[inline] 186 | fn mul_high_u32(a: u32, b: u32) -> u32 { 187 | (((a as u64) * (b as u64)) >> 32) as u32 188 | } 189 | 190 | #[inline] 191 | fn mul_high_u64(a: u64, b: u64) -> u64 { 192 | (((a as u128) * (b as u128)) >> 64) as u64 193 | } 194 | 195 | thread_local! { 196 | static RNG: Rng = Rng::new(); 197 | } 198 | 199 | #[doc = "Get the seed for the random number generator."] 200 | pub fn get_seed() -> u64 { 201 | RNG.with(|rng| rng.get_seed()) 202 | } 203 | 204 | #[doc = "Set the seed for the random number generator."] 205 | pub fn set_seed(seed: u64) { 206 | RNG.with(|rng| rng.set_seed(seed)); 207 | } 208 | 209 | macro_rules! impl_rng_functions { 210 | ($doc1: tt $doc2: tt | $($fn: ident $type: ident $($arg: ident)* ),+ $(,)?) => { 211 | $( 212 | #[doc = $doc1] 213 | #[doc = stringify!($type)] 214 | #[doc = $doc2] 215 | pub fn $fn( $($arg: $type, )* ) -> $type { 216 | RNG.with(|rng| rng.$fn( $($arg, )* )) 217 | } 218 | )+ 219 | }; 220 | } 221 | 222 | macro_rules! impl_rng_functions_helper_1 { 223 | ($doc1: tt $doc2: tt | $($type: ident, )+) => { 224 | impl_rng_functions!($doc1 $doc2 | $($type $type, )+); 225 | }; 226 | } 227 | 228 | macro_rules! impl_rng_functions_helper_2 { 229 | ($doc1: tt $doc2: tt | $($fn: tt $type: ident, )+) => { 230 | impl_rng_functions!($doc1 $doc2 | $($fn $type max, )+); 231 | }; 232 | } 233 | 234 | macro_rules! impl_rng_functions_helper_3 { 235 | ($($fn: tt $type: ident, )+) => { 236 | impl_rng_functions!("Generate a random `" "` value in the range [min, max] (i.e., both endpoints are included)." | $($fn $type min max, )+); 237 | } 238 | } 239 | 240 | impl_rng_functions_helper_1!("Generate a random `" "` value." | u64, u32, i64, i32, bool,); 241 | impl_rng_functions_helper_1!("Generate a random `" "` value in the range [0, 1)." | f64, f32,); 242 | impl_rng_functions_helper_2!("Generate a random `" "` value less than `max`." | u64_less_than u64, u32_less_than u32, i64_less_than i64, i32_less_than i32,); 243 | impl_rng_functions_helper_2!("Generate a random `" "` value in the range [0, max)." | f64_less_than f64, f32_less_than f32,); 244 | impl_rng_functions_helper_3!(u64_in_range u64, u32_in_range u32, f64_in_range f64, f32_in_range f32, i64_in_range i64, i32_in_range i32,); 245 | -------------------------------------------------------------------------------- /benches/benchmark_rand.rs: -------------------------------------------------------------------------------- 1 | use criterion::{criterion_group, criterion_main, Criterion}; 2 | use rand::distributions::uniform::Uniform; 3 | use rand::prelude::*; 4 | 5 | fn criterion_u64(c: &mut Criterion) { 6 | c.bench_function("fastrand u64", |b| { 7 | b.iter(|| fastrand::u64(u64::MIN..u64::MAX)) 8 | }); 9 | c.bench_function("alea u64", |b| b.iter(|| alea::u64())); 10 | c.bench_function("rand u64", |b| { 11 | let mut rng = rand::thread_rng(); 12 | b.iter(|| rng.gen::()); 13 | }); 14 | c.bench_function("rand_pcg u64", |b| { 15 | let mut rng = rand_pcg::Lcg128Xsl64::from_entropy(); 16 | b.iter(|| rng.gen::()); 17 | }); 18 | c.bench_function("rand_xorshift u64", |b| { 19 | let mut rng = rand_xorshift::XorShiftRng::from_entropy(); 20 | b.iter(|| rng.gen::()); 21 | }); 22 | 23 | c.bench_function("fastrand u64 in range", |b| { 24 | b.iter(|| fastrand::u64(20..200)) 25 | }); 26 | c.bench_function("alea u64 in range", |b| { 27 | b.iter(|| alea::u64_in_range(20, 200)) 28 | }); 29 | c.bench_function("rand u64 in range", |b| { 30 | let mut rng = rand::thread_rng(); 31 | b.iter(|| rng.gen_range(20_u64..200)); 32 | }); 33 | c.bench_function("rand u64 in range with uniform", |b| { 34 | let mut rng = thread_rng(); 35 | let unif = Uniform::new(20_u64, 200); 36 | b.iter(|| unif.sample(&mut rng)); 37 | }); 38 | c.bench_function("rand_pcg u64 in range", |b| { 39 | let mut rng = rand_pcg::Lcg128Xsl64::from_entropy(); 40 | b.iter(|| rng.gen_range(20_u64..200)); 41 | }); 42 | c.bench_function("rand_xorshift u64 in range", |b| { 43 | let mut rng = rand_xorshift::XorShiftRng::from_entropy(); 44 | b.iter(|| rng.gen_range(20_u64..200)); 45 | }); 46 | } 47 | 48 | fn criterion_u32(c: &mut Criterion) { 49 | c.bench_function("fastrand u32", |b| { 50 | b.iter(|| fastrand::u32(u32::MIN..u32::MAX)) 51 | }); 52 | c.bench_function("alea u32", |b| b.iter(|| alea::u32())); 53 | c.bench_function("rand u32", |b| { 54 | let mut rng = rand::thread_rng(); 55 | b.iter(|| rng.gen::()); 56 | }); 57 | c.bench_function("rand_pcg u32", |b| { 58 | let mut rng = rand_pcg::Lcg128Xsl64::from_entropy(); 59 | b.iter(|| rng.gen::()); 60 | }); 61 | c.bench_function("rand_xorshift u32", |b| { 62 | let mut rng = rand_xorshift::XorShiftRng::from_entropy(); 63 | b.iter(|| rng.gen::()); 64 | }); 65 | 66 | c.bench_function("fastrand u32 in range", |b| { 67 | b.iter(|| fastrand::u32(20..200)) 68 | }); 69 | c.bench_function("alea u32 in range", |b| { 70 | b.iter(|| alea::u32_in_range(20, 200)) 71 | }); 72 | c.bench_function("rand u32 in range", |b| { 73 | let mut rng = rand::thread_rng(); 74 | b.iter(|| rng.gen_range(20_u32..200)); 75 | }); 76 | c.bench_function("rand u32 in range with uniform", |b| { 77 | let mut rng = thread_rng(); 78 | let unif = Uniform::new(20_u32, 200); 79 | b.iter(|| unif.sample(&mut rng)); 80 | }); 81 | c.bench_function("rand_pcg u32 in range", |b| { 82 | let mut rng = rand_pcg::Lcg128Xsl64::from_entropy(); 83 | b.iter(|| rng.gen_range(20_u32..200)); 84 | }); 85 | c.bench_function("rand_xorshift u32 in range", |b| { 86 | let mut rng = rand_xorshift::XorShiftRng::from_entropy(); 87 | b.iter(|| rng.gen_range(20_u32..200)); 88 | }); 89 | } 90 | 91 | fn criterion_i32(c: &mut Criterion) { 92 | c.bench_function("fastrand i32", |b| { 93 | b.iter(|| fastrand::i32(i32::MIN..i32::MAX)) 94 | }); 95 | c.bench_function("alea i32", |b| b.iter(|| alea::i32())); 96 | c.bench_function("rand i32", |b| { 97 | let mut rng = rand::thread_rng(); 98 | b.iter(|| rng.gen::()); 99 | }); 100 | c.bench_function("rand_pcg i32", |b| { 101 | let mut rng = rand_pcg::Lcg128Xsl64::from_entropy(); 102 | b.iter(|| rng.gen::()); 103 | }); 104 | c.bench_function("rand_xorshift i32", |b| { 105 | let mut rng = rand_xorshift::XorShiftRng::from_entropy(); 106 | b.iter(|| rng.gen::()); 107 | }); 108 | 109 | c.bench_function("fastrand i32 in range", |b| { 110 | b.iter(|| fastrand::i32(-20..10)) 111 | }); 112 | c.bench_function("alea i32 in range", |b| { 113 | b.iter(|| alea::i32_in_range(-20, 10)) 114 | }); 115 | c.bench_function("rand i32 in range", |b| { 116 | let mut rng = rand::thread_rng(); 117 | b.iter(|| rng.gen_range(-20_i32..10)); 118 | }); 119 | c.bench_function("rand i32 in range with uniform", |b| { 120 | let mut rng = thread_rng(); 121 | let unif = Uniform::new(20_i32, 200); 122 | b.iter(|| unif.sample(&mut rng)); 123 | }); 124 | c.bench_function("rand_pcg i32 in range", |b| { 125 | let mut rng = rand_pcg::Lcg128Xsl64::from_entropy(); 126 | b.iter(|| rng.gen_range(20_i32..200)); 127 | }); 128 | c.bench_function("rand_xorshift i32 in range", |b| { 129 | let mut rng = rand_xorshift::XorShiftRng::from_entropy(); 130 | b.iter(|| rng.gen_range(20_i32..200)); 131 | }); 132 | } 133 | 134 | fn criterion_i64(c: &mut Criterion) { 135 | c.bench_function("fastrand i64", |b| { 136 | b.iter(|| fastrand::i64(i64::MIN..i64::MAX)) 137 | }); 138 | c.bench_function("alea i64", |b| b.iter(|| alea::i64())); 139 | c.bench_function("rand i64", |b| { 140 | let mut rng = rand::thread_rng(); 141 | b.iter(|| rng.gen::()); 142 | }); 143 | c.bench_function("rand_pcg i64", |b| { 144 | let mut rng = rand_pcg::Lcg128Xsl64::from_entropy(); 145 | b.iter(|| rng.gen::()); 146 | }); 147 | c.bench_function("rand_xorshift i64", |b| { 148 | let mut rng = rand_xorshift::XorShiftRng::from_entropy(); 149 | b.iter(|| rng.gen::()); 150 | }); 151 | 152 | c.bench_function("fastrand i64 in range", |b| { 153 | b.iter(|| fastrand::i64(-20..10)) 154 | }); 155 | c.bench_function("alea i64 in range", |b| { 156 | b.iter(|| alea::i64_in_range(-20, 10)) 157 | }); 158 | c.bench_function("rand i64 in range", |b| { 159 | let mut rng = rand::thread_rng(); 160 | b.iter(|| rng.gen_range(-20_i64..10)); 161 | }); 162 | c.bench_function("rand i64 in range with uniform", |b| { 163 | let mut rng = thread_rng(); 164 | let unif = Uniform::new(20_i64, 200); 165 | b.iter(|| unif.sample(&mut rng)); 166 | }); 167 | c.bench_function("rand_pcg i64 in range", |b| { 168 | let mut rng = rand_pcg::Lcg128Xsl64::from_entropy(); 169 | b.iter(|| rng.gen_range(20_i64..200)); 170 | }); 171 | c.bench_function("rand_xorshift i64 in range", |b| { 172 | let mut rng = rand_xorshift::XorShiftRng::from_entropy(); 173 | b.iter(|| rng.gen_range(20_i64..200)); 174 | }); 175 | } 176 | 177 | fn criterion_f64(c: &mut Criterion) { 178 | c.bench_function("fastrand f64", |b| b.iter(|| fastrand::f64())); 179 | c.bench_function("alea f64", |b| b.iter(|| alea::f64())); 180 | c.bench_function("rand f64", |b| { 181 | let mut rng = rand::thread_rng(); 182 | b.iter(|| rng.gen::()); 183 | }); 184 | c.bench_function("rand random f64", |b| { 185 | b.iter(|| rand::random::()); 186 | }); 187 | c.bench_function("rand_pcg f32", |b| { 188 | let mut rng = rand_pcg::Lcg128Xsl64::from_entropy(); 189 | b.iter(|| rng.gen::()); 190 | }); 191 | c.bench_function("rand_xorshift f64", |b| { 192 | let mut rng = rand_xorshift::XorShiftRng::from_entropy(); 193 | b.iter(|| rng.gen::()); 194 | }); 195 | } 196 | 197 | fn criterion_f32(c: &mut Criterion) { 198 | c.bench_function("fastrand f32", |b| b.iter(|| fastrand::f32())); 199 | c.bench_function("alea f32", |b| b.iter(|| alea::f32())); 200 | c.bench_function("rand f32", |b| { 201 | let mut rng = rand::thread_rng(); 202 | b.iter(|| rng.gen::()); 203 | }); 204 | c.bench_function("rand random f32", |b| { 205 | b.iter(|| rand::random::()); 206 | }); 207 | c.bench_function("rand_pcg f64", |b| { 208 | let mut rng = rand_pcg::Lcg128Xsl64::from_entropy(); 209 | b.iter(|| rng.gen::()); 210 | }); 211 | c.bench_function("rand_xorshift f32", |b| { 212 | let mut rng = rand_xorshift::XorShiftRng::from_entropy(); 213 | b.iter(|| rng.gen::()); 214 | }); 215 | } 216 | 217 | criterion_group!( 218 | benches, 219 | criterion_u32, 220 | criterion_u64, 221 | criterion_f64, 222 | criterion_f32, 223 | criterion_i64, 224 | criterion_i32 225 | ); 226 | criterion_main!(benches); 227 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | --------------------------------------------------------------------------------