@@ -93,22 +93,31 @@ u32 PcgRandom::range(u32 bound)
93
93
// If the bound is 0, we cover the whole RNG's range
94
94
if (bound == 0 )
95
95
return next ();
96
+
96
97
/*
97
- If the bound is not a multiple of the RNG's range, it may cause bias,
98
- e.g. a RNG has a range from 0 to 3 and we take want a number 0 to 2.
99
- Using rand() % 3, the number 0 would be twice as likely to appear.
100
- With a very large RNG range, the effect becomes less prevalent but
101
- still present. This can be solved by modifying the range of the RNG
102
- to become a multiple of bound by dropping values above the a threshold.
103
- In our example, threshold == 4 - 3 = 1 % 3 == 1, so reject 0, thus
104
- making the range 3 with no bias.
105
-
106
- This loop looks dangerous, but will always terminate due to the
107
- RNG's property of uniformity.
98
+ This is an optimization of the expression:
99
+ 0x100000000ull % bound
100
+ since 64-bit modulo operations typically much slower than 32.
108
101
*/
109
102
u32 threshold = -bound % bound;
110
103
u32 r;
111
104
105
+ /*
106
+ If the bound is not a multiple of the RNG's range, it may cause bias,
107
+ e.g. a RNG has a range from 0 to 3 and we take want a number 0 to 2.
108
+ Using rand() % 3, the number 0 would be twice as likely to appear.
109
+ With a very large RNG range, the effect becomes less prevalent but
110
+ still present.
111
+
112
+ This can be solved by modifying the range of the RNG to become a
113
+ multiple of bound by dropping values above the a threshold.
114
+
115
+ In our example, threshold == 4 % 3 == 1, so reject values < 1
116
+ (that is, 0), thus making the range == 3 with no bias.
117
+
118
+ This loop may look dangerous, but will always terminate due to the
119
+ RNG's property of uniformity.
120
+ */
112
121
while ((r = next ()) < threshold)
113
122
;
114
123
0 commit comments