1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
macro_rules! gen_int_const {
($func:ident, $int:ty, $doc:tt) => {
#[doc = $doc]
#[inline]
fn $func(&self) -> $int {
<$int>::from_le_bytes(self.gen())
}
};
}
macro_rules! trait_range_int {
($value:tt, $unsigned:tt, $bigger:ty, $source:ident, $doc:tt) => {
#[doc = $doc]
#[inline]
fn $value(&self, bounds: impl RangeBounds<$value>) -> $value {
const BITS: $bigger = $value::BITS as $bigger;
let lower = match bounds.start_bound() {
Bound::Included(lower) => *lower,
Bound::Excluded(lower) => lower.saturating_add(1),
Bound::Unbounded => $value::MIN,
};
let upper = match bounds.end_bound() {
Bound::Included(upper) => *upper,
Bound::Excluded(upper) => upper.saturating_sub(1),
Bound::Unbounded => $value::MAX,
};
assert!(lower <= upper, "Range should not be zero sized or invalid");
match (lower, upper) {
($value::MIN, $value::MAX) => self.$source(),
(_, _) => {
let range = upper.wrapping_sub(lower).wrapping_add(1) as $unsigned;
let mut generated = self.$source() as $unsigned;
let mut high = (generated as $bigger).wrapping_mul(range as $bigger);
let mut low = high as $unsigned;
if low < range {
let threshold = range.wrapping_neg() % range;
while low < threshold {
generated = self.$source() as $unsigned;
high = (generated as $bigger).wrapping_mul(range as $bigger);
low = high as $unsigned;
}
}
let value = (high >> BITS) as $value;
lower.wrapping_add(value)
}
}
}
};
}
macro_rules! trait_float_gen {
($name:ident, $value:tt, $int:ty, $scale:expr, $source:ident, $doc:tt) => {
#[doc = $doc]
#[inline]
fn $name(&self) -> $value {
const FLOAT_SIZE: u32 = (core::mem::size_of::<$value>() as u32) * 8;
const SCALE: $value = $scale / ((1 as $int << <$value>::MANTISSA_DIGITS) as $value);
let value = self.$source() >> (FLOAT_SIZE - <$value>::MANTISSA_DIGITS);
SCALE * (value as $value)
}
};
}
macro_rules! trait_rand_chars {
($func:ident, $chars:expr, $doc:tt) => {
#[doc = $doc]
#[inline]
fn $func(&self) -> char {
const CHARS: &[u8] = $chars;
self.sample(CHARS).map(|&value| value as char).unwrap()
}
};
}