Skip to main content

romu/
stable_tls.rs

1use core::ops::RangeBounds;
2
3use crate::{Rng, SeedSource};
4
5thread_local! {
6    static RNG: Rng = const { Rng::fixed_tls() };
7}
8
9#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
10/// Seeds the thread local instance from the best available randomness source.
11pub fn seed() {
12    RNG.with(|f| f.seed())
13}
14
15#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
16/// Shows which source was used to acquire the seed for the thread local instance.
17pub fn seed_source() -> SeedSource {
18    RNG.with(|f| f.seed_source())
19}
20
21#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
22/// Seeds the thread local instance with the given 64-bit seed.
23pub fn seed_with_64bit(seed: u64) {
24    RNG.with(|f| f.seed_with_64bit(seed))
25}
26
27#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
28/// Seeds the thread local instance with the given 192-bit seed.
29///
30/// If the seed is of low quality, user should call [`mix()`] to improve the quality of the
31/// first couple of random numbers.
32///
33/// # Notice
34/// The variables must be seeded such that at least one bit of state is non-zero.
35///
36/// # Panics
37/// Panics if all values are zero.
38pub fn seed_with_192bit(seed: [u64; 3]) {
39    RNG.with(|f| f.seed_with_192bit(seed))
40}
41
42#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
43/// Mixes the state, which should improve the quality of the random numbers.
44///
45/// Should be called when having (re-)seeded the generator with a fixed value of low randomness.
46pub fn mix() {
47    RNG.with(|rng| rng.mix())
48}
49
50#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
51/// Generates a random u8 value.
52#[inline(always)]
53pub fn u8() -> u8 {
54    RNG.with(|rng| rng.u8())
55}
56
57#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
58/// Generates a random u16 value.
59#[inline(always)]
60pub fn u16() -> u16 {
61    RNG.with(|rng| rng.u16())
62}
63
64#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
65/// Generates a random u32 value.
66#[inline(always)]
67pub fn u32() -> u32 {
68    RNG.with(|rng| rng.u32())
69}
70
71#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
72/// Generates a random u64 value.
73#[inline(always)]
74pub fn u64() -> u64 {
75    RNG.with(|rng| rng.u64())
76}
77
78#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
79/// Generates a random usize value.
80#[inline(always)]
81pub fn usize() -> usize {
82    RNG.with(|rng| rng.usize())
83}
84
85#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
86/// Generates a random i8 value.
87#[inline(always)]
88pub fn i8() -> i8 {
89    RNG.with(|rng| rng.i8())
90}
91
92#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
93/// Generates a random i16 value.
94#[inline(always)]
95pub fn i16() -> i16 {
96    RNG.with(|rng| rng.i16())
97}
98
99#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
100/// Generates a random i32 value.
101#[inline(always)]
102pub fn i32() -> i32 {
103    RNG.with(|rng| rng.i32())
104}
105
106#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
107/// Generates a random i64 value.
108#[inline(always)]
109pub fn i64() -> i64 {
110    RNG.with(|rng| rng.i64())
111}
112
113#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
114/// Generates a random isize value.
115#[inline(always)]
116pub fn isize() -> isize {
117    RNG.with(|rng| rng.isize())
118}
119
120#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
121/// Generates a random f32 value in range (0..1).
122#[inline(always)]
123pub fn f32() -> f32 {
124    RNG.with(|rng| rng.f32())
125}
126
127#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
128/// Generates a random f64 value in range (0..1).
129#[inline(always)]
130pub fn f64() -> f64 {
131    RNG.with(|rng| rng.f64())
132}
133
134#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
135/// Generates a random bool value.
136#[inline(always)]
137pub fn bool() -> bool {
138    RNG.with(|rng| rng.bool())
139}
140
141#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
142/// Randomly shuffles a slice.
143pub fn shuffle<T>(slice: &mut [T]) {
144    RNG.with(|rng| rng.shuffle(slice))
145}
146
147#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
148/// Fills a mutable `[u8]` slice with random values.
149pub fn fill_bytes(slice: &mut [u8]) {
150    RNG.with(|rng| rng.fill_bytes(slice))
151}
152
153#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
154/// Generates a random u8 value in range (0..n).
155///
156/// # Notice
157/// This has a very slight bias. Use [`range_u8()`] instead for no bias.
158#[inline(always)]
159pub fn mod_u8(n: u8) -> u8 {
160    RNG.with(|rng| rng.mod_u8(n))
161}
162
163#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
164/// Generates a random u16 value in range (0..n).
165///
166/// # Notice
167/// This has a very slight bias. Use [`range_u16()`] instead for no bias.
168#[inline(always)]
169pub fn mod_u16(n: u16) -> u16 {
170    RNG.with(|rng| rng.mod_u16(n))
171}
172
173#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
174/// Generates a random u32 value in range (0..n).
175///
176/// # Notice
177/// This has a very slight bias. Use [`range_u32()`] instead for no bias.
178#[inline(always)]
179pub fn mod_u32(n: u32) -> u32 {
180    RNG.with(|rng| rng.mod_u32(n))
181}
182
183#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
184/// Generates a random u64 value in range (0..n).
185///
186/// # Notice
187/// This has a very slight bias. Use [`range_u64()`] instead for no bias.
188#[inline(always)]
189pub fn mod_u64(n: u64) -> u64 {
190    RNG.with(|rng| rng.mod_u64(n))
191}
192
193#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
194/// Generates a random usize value in range (0..n).
195///
196/// # Notice
197/// This has a very slight bias. Use [`range_usize()`] instead for no bias.
198#[inline(always)]
199pub fn mod_usize(n: usize) -> usize {
200    RNG.with(|rng| rng.mod_usize(n))
201}
202
203#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
204/// Generates a random u8 value in the given range.
205#[inline(always)]
206pub fn range_u8<T: RangeBounds<u8>>(range: T) -> u8 {
207    RNG.with(|rng| rng.range_u8(range))
208}
209
210#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
211/// Generates a random u16 value in the given range.
212#[inline(always)]
213pub fn range_u16<T: RangeBounds<u16>>(range: T) -> u16 {
214    RNG.with(|rng| rng.range_u16(range))
215}
216
217#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
218/// Generates a random u32 value in the given range.
219#[inline(always)]
220pub fn range_u32<T: RangeBounds<u32>>(range: T) -> u32 {
221    RNG.with(|rng| rng.range_u32(range))
222}
223
224#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
225/// Generates a random u64 value in the given range.
226#[inline(always)]
227pub fn range_u64<T: RangeBounds<u64>>(range: T) -> u64 {
228    RNG.with(|rng| rng.range_u64(range))
229}
230
231#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
232/// Generates a random usize value in the given range.
233#[inline(always)]
234pub fn range_usize<T: RangeBounds<usize>>(range: T) -> usize {
235    RNG.with(|rng| rng.range_usize(range))
236}
237
238#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
239/// Generates a random i8 value in the given range.
240#[inline(always)]
241pub fn range_i8<T: RangeBounds<i8>>(range: T) -> i8 {
242    RNG.with(|rng| rng.range_i8(range))
243}
244
245#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
246/// Generates a random i16 value in the given range.
247#[inline(always)]
248pub fn range_i16<T: RangeBounds<i16>>(range: T) -> i16 {
249    RNG.with(|rng| rng.range_i16(range))
250}
251
252#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
253/// Generates a random i32 value in the given range.
254#[inline(always)]
255pub fn range_i32<T: RangeBounds<i32>>(range: T) -> i32 {
256    RNG.with(|rng| rng.range_i32(range))
257}
258
259#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
260/// Generates a random i64 value in the given range.
261#[inline(always)]
262pub fn range_i64<T: RangeBounds<i64>>(range: T) -> i64 {
263    RNG.with(|rng| rng.range_i64(range))
264}
265
266#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
267/// Generates a random isize value in the given range.
268#[inline(always)]
269pub fn range_isize<T: RangeBounds<isize>>(range: T) -> isize {
270    RNG.with(|rng| rng.range_isize(range))
271}