1#![no_std]
17#![allow(clippy::style)]
18#![warn(missing_docs)]
19
20use core::sync::atomic::{AtomicU64, Ordering};
21
22pub const KEY: u64 = 0x5d8491e219f6537d;
24
25pub mod distr;
26
27#[inline]
28pub const fn rand32(counter: u64, key: u64) -> u32 {
36 let mut x = counter.wrapping_mul(key);
37 let y = x;
38 let z = y.wrapping_add(key);
39
40 x = x.wrapping_mul(x).wrapping_add(y);
41 x = (x >> 32) | (x << 32);
42
43 x = x.wrapping_mul(x).wrapping_add(z);
44 x = (x >> 32) | (x << 32);
45
46 x = x.wrapping_mul(x).wrapping_add(y);
47 x = (x >> 32) | (x << 32);
48
49 (x.wrapping_mul(x).wrapping_add(z) >> 32) as u32
50}
51
52#[inline]
53pub const fn rand64(counter: u64, key: u64) -> u64 {
61 let mut x = counter.wrapping_mul(key);
62 let y = x;
63 let z = y.wrapping_add(key);
64
65 x = x.wrapping_mul(x).wrapping_add(y);
66 x = (x >> 32) | (x << 32);
67
68 x = x.wrapping_mul(x).wrapping_add(z);
69 x = (x >> 32) | (x << 32);
70
71 x = x.wrapping_mul(x).wrapping_add(y);
72 x = (x >> 32) | (x << 32);
73
74 x = x.wrapping_mul(x).wrapping_add(z);
75 let t = x;
76 x = (x >> 32) | (x << 32);
77
78 t ^ (x.wrapping_mul(x).wrapping_add(y) >> 32)
79}
80
81
82pub struct RandRes<T> {
84 pub counter: u64,
86 pub value: T
88}
89
90#[derive(Debug)]
91pub struct Rand {
95 counter: AtomicU64,
96 key: u64,
97}
98
99impl Rand {
100 #[inline(always)]
101 pub const fn new(key: u64) -> Self {
103 Self::with_counter(0, key)
104 }
105
106 #[inline]
107 pub const fn with_counter(counter: u64, key: u64) -> Self {
109 Self {
110 counter: AtomicU64::new(counter),
111 key,
112 }
113 }
114
115 #[inline]
116 pub fn set_counter(&self, counter: u64) -> u64 {
118 self.counter.swap(counter, Ordering::AcqRel)
119 }
120
121 #[inline]
122 pub fn counter(&self) -> u64 {
124 self.counter.load(Ordering::Acquire)
125 }
126
127 #[inline]
128 pub fn next_full_u32(&self) -> RandRes<u32> {
130 let counter = self.counter.fetch_add(1, Ordering::AcqRel);
131 RandRes {
132 counter,
133 value: rand32(counter, self.key)
134 }
135 }
136
137 #[inline]
138 pub fn next_u32(&self) -> u32 {
140 rand32(self.counter.fetch_add(1, Ordering::AcqRel), self.key)
141 }
142
143 #[inline]
144 pub fn next_u32_up(&self, to: u32) -> u32 {
146 #[inline(always)]
147 fn mul_high_u32(a: u32, b: u32) -> u32 {
148 (((a as u64) * (b as u64)) >> 32) as u32
149 }
150
151 let mut result = self.next_u32();
153 let mut hi = mul_high_u32(result, to);
154 let mut lo = result.wrapping_mul(to);
155
156 if lo < to {
157 while lo < (to.wrapping_neg() % to) {
158 result = self.next_u32();
159 hi = mul_high_u32(result, to);
160 lo = result.wrapping_mul(to);
161 }
162 }
163
164 hi
165 }
166
167 #[inline]
168 pub fn next_full_u64(&self) -> RandRes<u64> {
170 let counter = self.counter.fetch_add(1, Ordering::AcqRel);
171 RandRes {
172 counter,
173 value: rand64(counter, self.key)
174 }
175 }
176
177 #[inline]
178 pub fn next_u64(&self) -> u64 {
180 rand64(self.counter.fetch_add(1, Ordering::AcqRel), self.key)
181 }
182
183 #[inline]
184 pub fn next_u64_up(&self, to: u64) -> u64 {
186 #[inline(always)]
187 fn mul_high_u64(a: u64, b: u64) -> u64 {
188 (((a as u128) * (b as u128)) >> 64) as u64
189 }
190
191 let mut result = self.next_u64();
193 let mut hi = mul_high_u64(result, to);
194 let mut lo = result.wrapping_mul(to);
195
196 if lo < to {
197 while lo < (to.wrapping_neg() % to) {
198 result = self.next_u64();
199 hi = mul_high_u64(result, to);
200 lo = result.wrapping_mul(to);
201 }
202 }
203
204 hi
205 }
206}
207
208impl Default for Rand {
209 #[inline(always)]
210 fn default() -> Self {
211 Self::new(KEY)
212 }
213}