devela/num/rand/xorshift/
u64.rs

1// alazar::xorshift::u64
2//
3//! 64-bit version of XorShift.
4//
5
6#[cfg(feature = "join")]
7use crate::Cast;
8use crate::{ConstDefault, Own, xorshift_basis};
9
10#[doc = crate::TAG_RAND!()]
11/// The `XorShift64` <abbr title="Pseudo-Random Number Generator">PRNG</abbr>.
12///
13/// It has a 64-bit state and generates 64-bit numbers.
14///
15/// This is the classic 64-bit *XorShift* by George Marsaglia.
16///
17/// The `BASIS` and triplet (`A`, `B`, `C`) values default to the canonical example.
18#[must_use]
19#[derive(Clone, Copy, Debug, PartialEq, Eq)]
20pub struct XorShift64<
21    const BASIS: usize = 0,
22    const A: usize = 13,
23    const B: usize = 7,
24    const C: usize = 17,
25>(u64);
26
27/// Creates a new PRNG initialized with the default fixed seed.
28impl Default for XorShift64 {
29    fn default() -> Self {
30        Self::DEFAULT
31    }
32}
33/// Creates a new PRNG initialized with the default fixed seed.
34impl ConstDefault for XorShift64 {
35    const DEFAULT: Self = Self::new_unchecked(Self::DEFAULT_SEED);
36}
37
38// private associated items
39impl<const BASIS: usize, const A: usize, const B: usize, const C: usize>
40    XorShift64<BASIS, A, B, C>
41{
42    const DEFAULT_SEED: u64 = 0xDEFA_0017_DEFA_0017;
43
44    #[cold] #[allow(dead_code)] #[rustfmt::skip]
45    const fn cold_path_default() -> Self { Self::new_unchecked(Self::DEFAULT_SEED) }
46}
47
48impl<const BASIS: usize, const A: usize, const B: usize, const C: usize>
49    XorShift64<BASIS, A, B, C>
50{
51    /// Returns a seeded `XorShift64` generator from the given 64-bit seed.
52    ///
53    /// If the seed is `0`, the default seed is used instead.
54    pub const fn new(seed: u64) -> Self {
55        if seed == 0 { Self::cold_path_default() } else { Self(seed) }
56    }
57
58    /// Returns a seeded `XorShift64` generator from the given 8-bit seed, unchecked.
59    ///
60    /// The seed must not be `0`, otherwise every result will also be `0`.
61    pub const fn new_unchecked(seed: u64) -> Self {
62        debug_assert![seed != 0, "Seed must be non-zero"];
63        Self(seed)
64    }
65
66    #[must_use]
67    /// Returns the PRNG's inner state as a raw snapshot.
68    pub const fn inner_state(self) -> u64 {
69        self.0
70    }
71    /// Restores the PRNG from the given state.
72    pub const fn from_state(state: u64) -> Self {
73        Self(state)
74    }
75
76    /// Returns the current random `u64`.
77    #[must_use]
78    pub const fn current_u64(&self) -> u64 {
79        self.0
80    }
81
82    /// Returns the next random `u64`.
83    #[must_use]
84    pub fn next_u64(&mut self) -> u64 {
85        let mut x = self.0;
86        xorshift_basis!(x, BASIS, (A, B, C));
87        self.0 = x;
88        x
89    }
90
91    /// Returns a copy of the next new random state.
92    pub const fn peek_next_state(&self) -> Self {
93        let mut x = self.0;
94        xorshift_basis!(x, BASIS, (A, B, C));
95        Self(x)
96    }
97
98    /// Returns both the next random state and the `u64` value.
99    pub const fn own_next_u64(self) -> Own<Self, u64> {
100        let s = self.peek_next_state();
101        let v = s.current_u64();
102        Own::new(s, v)
103    }
104}
105
106/// # Extra constructors
107impl<const BASIS: usize, const A: usize, const B: usize, const C: usize>
108    XorShift64<BASIS, A, B, C>
109{
110    /// Returns a seeded `XorShift64` generator from the given 64-bit seed.
111    ///
112    /// This is an alias of [`new`][Self#method.new].
113    pub const fn new1_u64(seed: u64) -> Self {
114        Self::new(seed)
115    }
116
117    /// Returns a seeded `XorShift64` generator from the given 2 × 32-bit seeds.
118    ///
119    /// The seeds will be joined in little endian order.
120    #[cfg(feature = "join")]
121    #[cfg_attr(nightly_doc, doc(cfg(feature = "join")))]
122    pub const fn new2_u32(seeds: [u32; 2]) -> Self {
123        Self::new(Cast::<u64>::from_u32_le(seeds))
124    }
125
126    /// Returns a seeded `XorShift64` generator from the given 4 × 16-bit seeds.
127    ///
128    /// The seeds will be joined in little endian order.
129    #[cfg(feature = "join")]
130    #[cfg_attr(nightly_doc, doc(cfg(feature = "join")))]
131    pub const fn new4_u16(seeds: [u16; 4]) -> Self {
132        Self::new(Cast::<u64>::from_u16_le(seeds))
133    }
134
135    /// Returns a seeded `XorShift64` generator from the given 4 × 8-bit seeds.
136    ///
137    /// The seeds will be joined in little endian order.
138    pub const fn new8_u8(seeds: [u8; 8]) -> Self {
139        Self::new(u64::from_le_bytes(seeds))
140    }
141}
142
143#[cfg(feature = "dep_rand_core")]
144#[cfg_attr(nightly_doc, doc(cfg(feature = "dep_rand_core")))]
145mod impl_rand {
146    use super::XorShift64;
147    use crate::_dep::rand_core::{RngCore, SeedableRng};
148
149    impl<const BASIS: usize, const A: usize, const B: usize, const C: usize> RngCore
150        for XorShift64<BASIS, A, B, C>
151    {
152        /// Returns the next random `u32`,
153        /// from the first 32-bits of `next_u64`.
154        fn next_u32(&mut self) -> u32 {
155            self.next_u64() as u32
156        }
157
158        /// Returns the next random `u64`.
159        fn next_u64(&mut self) -> u64 {
160            self.next_u64()
161        }
162
163        fn fill_bytes(&mut self, dest: &mut [u8]) {
164            let mut i = 0;
165            while i < dest.len() {
166                let random_u64 = self.next_u64();
167                let bytes = random_u64.to_le_bytes();
168                let remaining = dest.len() - i;
169
170                if remaining >= 8 {
171                    dest[i..i + 8].copy_from_slice(&bytes);
172                    i += 8;
173                } else {
174                    dest[i..].copy_from_slice(&bytes[..remaining]);
175                    break;
176                }
177            }
178        }
179    }
180
181    impl<const BASIS: usize, const A: usize, const B: usize, const C: usize> SeedableRng
182        for XorShift64<BASIS, A, B, C>
183    {
184        type Seed = [u8; 8];
185
186        /// When seeded with zero this implementation uses the default seed
187        /// value as the cold path.
188        fn from_seed(seed: Self::Seed) -> Self {
189            if seed == [0; 8] {
190                Self::cold_path_default()
191            } else {
192                Self::new_unchecked(u64::from_le_bytes(seed))
193            }
194        }
195    }
196}
197
198/// 275 × good triplets for 64-bit xorshift. (825 Bytes)
199#[doc(hidden)]
200#[rustfmt::skip]
201#[allow(dead_code)]
202pub const XOROSHIFT_64_TRIPLETS: [(u8, u8, u8); 275] = [
203    ( 1, 1,54), ( 1, 1,55), ( 1, 3,45), ( 1, 7, 9), ( 1, 7,44), ( 1, 7,46),
204    ( 1, 9,50), ( 1,11,35), ( 1,11,50), ( 1,13,45), ( 1,15, 4), ( 1,15,63),
205    ( 1,19, 6), ( 1,19,16), ( 1,23,14), ( 1,23,29), ( 1,29,34), ( 1,35, 5),
206    ( 1,35,11), ( 1,35,34), ( 1,45,37), ( 1,51,13), ( 1,53, 3), ( 1,59,14),
207    ( 2,13,23), ( 2,31,51), ( 2,31,53), ( 2,43,27), ( 2,47,49), ( 3, 1,11),
208    ( 3, 5,21), ( 3,13,59), ( 3,21,31), ( 3,25,20), ( 3,25,31), ( 3,25,56),
209    ( 3,29,40), ( 3,29,47), ( 3,29,49), ( 3,35,14), ( 3,37,17), ( 3,43, 4),
210    ( 3,43, 6), ( 3,43,11), ( 3,51,16), ( 3,53, 7), ( 3,61,17), ( 3,61,26),
211    ( 4, 7,19), ( 4, 9,13), ( 4,15,51), ( 4,15,53), ( 4,29,45), ( 4,29,49),
212    ( 4,31,33), ( 4,35,15), ( 4,35,21), ( 4,37,11), ( 4,37,21), ( 4,41,19),
213    ( 4,41,45), ( 4,43,21), ( 4,43,31), ( 4,53, 7), ( 5, 9,23), ( 5,11,54),
214    ( 5,15,27), ( 5,17,11), ( 5,23,36), ( 5,33,29), ( 5,41,20), ( 5,45,16),
215    ( 5,47,23), ( 5,53,20), ( 5,59,33), ( 5,59,35), ( 5,59,63), ( 6, 1,17),
216    ( 6, 3,49), ( 6,17,47), ( 6,23,27), ( 6,27, 7), ( 6,43,21), ( 6,49,29),
217    ( 6,55,17), ( 7, 5,41), ( 7, 5,47), ( 7, 5,55), ( 7, 7,20), ( 7, 9,38),
218    ( 7,11,10), ( 7,11,35), ( 7,13,58), ( 7,19,17), ( 7,19,54), ( 7,23, 8),
219    ( 7,25,58), ( 7,27,59), ( 7,33, 8), ( 7,41,40), ( 7,43,28), ( 7,51,24),
220    ( 7,57,12), ( 8, 5,59), ( 8, 9,25), ( 8,13,25), ( 8,13,61), ( 8,15,21),
221    ( 8,25,59), ( 8,29,19), ( 8,31,17), ( 8,37,21), ( 8,51,21), ( 9, 1,27),
222    ( 9, 5,36), ( 9, 5,43), ( 9, 7,18), ( 9,19,18), ( 9,21,11), ( 9,21,20),
223    ( 9,21,40), ( 9,23,57), ( 9,27,10), ( 9,29,12), ( 9,29,37), ( 9,37,31),
224    ( 9,41,45), (10, 7,33), (10,27,59), (10,53,13), (11, 5,32), (11, 5,34),
225    (11, 5,43), (11, 5,45), (11, 9,14), (11, 9,34), (11,13,40), (11,15,37),
226    (11,23,42), (11,23,56), (11,25,48), (11,27,26), (11,29,14), (11,31,18),
227    (11,53,23), (12, 1,31), (12, 3,13), (12, 3,49), (12, 7,13), (12,11,47),
228    (12,25,27), (12,39,49), (12,43,19), (13, 3,40), (13, 3,53), (13, 7,17),
229    (13, 9,15), (13, 9,50), (13,13,19), (13,17,43), (13,19,28), (13,19,47),
230    (13,21,18), (13,21,49), (13,29,35), (13,35,30), (13,35,38), (13,47,23),
231    (13,51,21), (14,13,17), (14,15,19), (14,23,33), (14,31,45), (14,47,15),
232    (15, 1,19), (15, 5,37), (15,13,28), (15,13,52), (15,17,27), (15,19,63),
233    (15,21,46), (15,23,23), (15,45,17), (15,47,16), (15,49,26), (16, 5,17),
234    (16, 7,39), (16,11,19), (16,11,27), (16,13,55), (16,21,35), (16,25,43),
235    (16,27,53), (16,47,17), (17,15,58), (17,23,29), (17,23,51), (17,23,52),
236    (17,27,22), (17,45,22), (17,47,28), (17,47,29), (17,47,54), (18, 1,25),
237    (18, 3,43), (18,19,19), (18,25,21), (18,41,23), (19, 7,36), (19, 7,55),
238    (19,13,37), (19,15,46), (19,21,52), (19,25,20), (19,41,21), (19,43,27),
239    (20, 1,31), (20, 5,29), (21, 1,27), (21, 9,29), (21,13,52), (21,15,28),
240    (21,15,29), (21,17,24), (21,17,30), (21,17,48), (21,21,32), (21,21,34),
241    (21,21,37), (21,21,38), (21,21,40), (21,21,41), (21,21,43), (21,41,23),
242    (22, 3,39), (23, 9,38), (23, 9,48), (23, 9,57), (23,13,38), (23,13,58),
243    (23,13,61), (23,17,25), (23,17,54), (23,17,56), (23,17,62), (23,41,34),
244    (23,41,51), (24, 9,35), (24,11,29), (24,25,25), (24,31,35), (25, 7,46),
245    (25, 7,49), (25, 9,39), (25,11,57), (25,13,29), (25,13,39), (25,13,62),
246    (25,15,47), (25,21,44), (25,27,27), (25,27,53), (25,33,36), (25,39,54),
247    (28, 9,55), (28,11,53), (29,27,37), (31, 1,51), (31,25,37), (31,27,35),
248    (33,31,43), (33,31,55), (43,21,46), (49,15,61), (55, 9,56)
249];