1
1
use crate :: { Rng , RngCore } ;
2
2
3
- /// Similar to a Uniform distribution, but after returning a number in the range [0,n], n is increased by 1.
3
+ /// Similar to a Uniform distribution,
4
+ /// but after returning a number in the range [0,n], n is increased by 1.
4
5
pub ( crate ) struct IncreasingUniform < R : RngCore > {
5
6
pub rng : R ,
6
7
n : u32 ,
7
- //TODO(opt): this should depend on RNG word size
8
- chunk : u32 , //Chunk is a random number in [0, (n + 1) * (n + 2) *..* (n + chunk_remaining) )
8
+ // Chunk is a random number in [0, (n + 1) * (n + 2) *..* (n + chunk_remaining) )
9
+ chunk : u32 ,
9
10
chunk_remaining : u8 ,
10
11
}
11
12
12
13
impl < R : RngCore > IncreasingUniform < R > {
13
14
/// Create a dice roller.
14
15
/// The next item returned will be a random number in the range [0,n]
15
16
pub fn new ( rng : R , n : u32 ) -> Self {
16
- let chunk_remaining = if n == 0 { 1 } else { 0 } ; // If n = 0, the first number returned will always be 0, so we don't need to generate a random number
17
+ // If n = 0, the first number returned will always be 0
18
+ // so we don't need to generate a random number
19
+ let chunk_remaining = if n == 0 { 1 } else { 0 } ;
17
20
Self {
18
21
rng,
19
22
n,
@@ -30,22 +33,24 @@ impl<R: RngCore> IncreasingUniform<R> {
30
33
let next_n = self . n + 1 ;
31
34
32
35
let next_chunk_remaining = self . chunk_remaining . checked_sub ( 1 ) . unwrap_or_else ( || {
33
- //If the chunk is empty, generate a new chunk
36
+ // If the chunk is empty, generate a new chunk
34
37
let ( bound, remaining) = calculate_bound_u32 ( next_n) ;
35
- //bound = (n + 1) * (n + 2) *..* (n + remaining)
38
+ // bound = (n + 1) * (n + 2) *..* (n + remaining)
36
39
self . chunk = self . rng . gen_range ( 0 ..bound) ;
37
- // Chunk is a random number in [0, (n + 1) * (n + 2) *..* (n + remaining) )
40
+ // Chunk is a random number in
41
+ // [0, (n + 1) * (n + 2) *..* (n + remaining) )
38
42
39
43
remaining - 1
40
44
} ) ;
41
45
42
46
let result = if next_chunk_remaining == 0 {
43
- //If the chunk is empty we asr
44
- self . chunk as usize
45
47
// `chunk` is a random number in the range [0..n+1)
46
- // Because `chunk_remaining` is about to be set to zero, we do not need to clear the chunk here
48
+ // Because `chunk_remaining` is about to be set to zero
49
+ // we do not need to clear the chunk here
50
+ self . chunk as usize
47
51
} else {
48
- // `chunk` is a random number in a range that is a multiple of n+1 so r will be a random number in [0..n+1)
52
+ // `chunk` is a random number in a range that is a multiple of n+1
53
+ // so r will be a random number in [0..n+1)
49
54
let r = self . chunk % next_n;
50
55
self . chunk /= next_n;
51
56
r as usize
@@ -70,15 +75,18 @@ fn calculate_bound_u32(m: u32) -> (u32, u8) {
70
75
product = p;
71
76
current += 1 ;
72
77
} else {
73
- let count = ( current - m) as u8 ; //Maximum value of 13 for when min is 1 or 2
78
+ // Count has a maximum value of 13 for when min is 1 or 2
79
+ let count = ( current - m) as u8 ;
74
80
return ( product, count) ;
75
81
}
76
82
}
77
83
}
78
84
79
85
const RESULT2 : ( u32 , u8 ) = inner ( 2 ) ;
80
86
if m == 2 {
81
- return RESULT2 ; //Making this value a constant instead of recalculating it gives a significant (~50%) performance boost for small shuffles
87
+ // Making this value a constant instead of recalculating it
88
+ // gives a significant (~50%) performance boost for small shuffles
89
+ return RESULT2 ;
82
90
}
83
91
84
92
inner ( m)
0 commit comments