| ... | ... | @@ -63,17 +63,11 @@ pub const Random = struct { |
| 63 | 63 | comptime assert(T.is_signed == false); |
| 64 | 64 | comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation! |
| 65 | 65 | assert(0 < less_than); |
| 66 | | // Small is typically u32 |
| 67 | | const Small = @IntType(false, @divTrunc(T.bit_count + 31, 32) * 32); |
| 68 | | // Large is typically u64 |
| 69 | | const Large = @IntType(false, Small.bit_count * 2); |
| 70 | | |
| 71 | | // adapted from: |
| 72 | | // http://www.pcg-random.org/posts/bounded-rands.html |
| 73 | | // "Integer Multiplication (Biased)" |
| 74 | | var x: Small = r.int(Small); |
| 75 | | var m: Large = Large(x) * Large(less_than); |
| 76 | | return @intCast(T, m >> Small.bit_count); |
| 66 | if (T.bit_count <= 32) { |
| 67 | return @intCast(T, limitRangeBiased(u32, r.int(u32), less_than)); |
| 68 | } else { |
| 69 | return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than)); |
| 70 | } |
| 77 | 71 | } |
| 78 | 72 | /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`. |
| 79 | 73 | /// This function assumes that the underlying ::fillFn produces evenly distributed values. |
| ... | ... | @@ -276,6 +270,20 @@ pub const Random = struct { |
| 276 | 270 | } |
| 277 | 271 | }; |
| 278 | 272 | |
| 273 | /// Convert a random integer 0 <= random_int <= maxValue(T), |
| 274 | /// into an integer 0 <= result < less_than. |
| 275 | /// This function introduces a minor bias. |
| 276 | pub fn limitRangeBiased(comptime T: type, random_int: T, less_than: T) T { |
| 277 | comptime assert(T.is_signed == false); |
| 278 | const T2 = @IntType(false, T.bit_count * 2); |
| 279 | |
| 280 | // adapted from: |
| 281 | // http://www.pcg-random.org/posts/bounded-rands.html |
| 282 | // "Integer Multiplication (Biased)" |
| 283 | var m: T2 = T2(random_int) * T2(less_than); |
| 284 | return @intCast(T, m >> T.bit_count); |
| 285 | } |
| 286 | |
| 279 | 287 | const SequentialPrng = struct { |
| 280 | 288 | const Self = @This(); |
| 281 | 289 | random: Random, |