1 // Copyright 2018 Developers of the Rand project.
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
9 #[cfg(feature="serde1")] use serde::{Serialize, Deserialize};
10 use rand_core
::impls
::fill_bytes_via_next
;
11 use rand_core
::le
::read_u64_into
;
12 use rand_core
::{SeedableRng, RngCore, Error}
;
14 /// A xoshiro256** random number generator.
16 /// The xoshiro256** algorithm is not suitable for cryptographic purposes, but
17 /// is very fast and has excellent statistical properties.
19 /// The algorithm used here is translated from [the `xoshiro256plusplus.c`
20 /// reference source code](http://xoshiro.di.unimi.it/xoshiro256plusplus.c) by
21 /// David Blackman and Sebastiano Vigna.
22 #[derive(Debug, Clone, PartialEq, Eq)]
23 #[cfg_attr(feature="serde1", derive(Serialize, Deserialize))]
24 pub struct Xoshiro256PlusPlus
{
28 impl SeedableRng
for Xoshiro256PlusPlus
{
31 /// Create a new `Xoshiro256PlusPlus`. If `seed` is entirely 0, it will be
32 /// mapped to a different seed.
34 fn from_seed(seed
: [u8; 32]) -> Xoshiro256PlusPlus
{
35 if seed
.iter().all(|&x
| x
== 0) {
36 return Self::seed_from_u64(0);
38 let mut state
= [0; 4];
39 read_u64_into(&seed
, &mut state
);
40 Xoshiro256PlusPlus { s: state }
43 /// Create a new `Xoshiro256PlusPlus` from a `u64` seed.
45 /// This uses the SplitMix64 generator internally.
46 fn seed_from_u64(mut state
: u64) -> Self {
47 const PHI
: u64 = 0x9e3779b97f4a7c15;
48 let mut seed
= Self::Seed
::default();
49 for chunk
in seed
.as_mut().chunks_mut(8) {
50 state
= state
.wrapping_add(PHI
);
52 z
= (z ^
(z
>> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
53 z
= (z ^
(z
>> 27)).wrapping_mul(0x94d049bb133111eb);
55 chunk
.copy_from_slice(&z
.to_le_bytes());
61 impl RngCore
for Xoshiro256PlusPlus
{
63 fn next_u32(&mut self) -> u32 {
64 // The lowest bits have some linear dependencies, so we use the
65 // upper bits instead.
66 (self.next_u64() >> 32) as u32
70 fn next_u64(&mut self) -> u64 {
71 let result_plusplus
= self.s
[0]
72 .wrapping_add(self.s
[3])
74 .wrapping_add(self.s
[0]);
76 let t
= self.s
[1] << 17;
78 self.s
[2] ^
= self.s
[0];
79 self.s
[3] ^
= self.s
[1];
80 self.s
[1] ^
= self.s
[2];
81 self.s
[0] ^
= self.s
[3];
85 self.s
[3] = self.s
[3].rotate_left(45);
91 fn fill_bytes(&mut self, dest
: &mut [u8]) {
92 fill_bytes_via_next(self, dest
);
96 fn try_fill_bytes(&mut self, dest
: &mut [u8]) -> Result
<(), Error
> {
97 self.fill_bytes(dest
);
108 let mut rng
= Xoshiro256PlusPlus
::from_seed(
109 [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
110 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0]);
111 // These values were produced with the reference implementation:
112 // http://xoshiro.di.unimi.it/xoshiro256plusplus.c
114 41943041, 58720359, 3588806011781223, 3591011842654386,
115 9228616714210784205, 9973669472204895162, 14011001112246962877,
116 12406186145184390807, 15849039046786891736, 10450023813501588000,
118 for &e
in &expected
{
119 assert_eq
!(rng
.next_u64(), e
);