| ... | @@ -63,17 +63,11 @@ pub const Random = struct { | ... | @@ -63,17 +63,11 @@ pub const Random = struct { |
| 63 | comptime assert(T.is_signed == false); | 63 | comptime assert(T.is_signed == false); |
| 64 | comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation! | 64 | comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation! |
| 65 | assert(0 < less_than); | 65 | assert(0 < less_than); |
| 66 | // Small is typically u32 | 66 | if (T.bit_count <= 32) { |
| 67 | const Small = @IntType(false, @divTrunc(T.bit_count + 31, 32) * 32); | 67 | return @intCast(T, limitRangeBiased(u32, r.int(u32), less_than)); |
| 68 | // Large is typically u64 | 68 | } else { |
| 69 | const Large = @IntType(false, Small.bit_count * 2); | 69 | return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than)); |
| 70 | | 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); | | |
| 77 | } | 71 | } |
| 78 | /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`. | 72 | /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`. |
| 79 | /// This function assumes that the underlying ::fillFn produces evenly distributed values. | 73 | /// This function assumes that the underlying ::fillFn produces evenly distributed values. |
| ... | @@ -276,6 +270,20 @@ pub const Random = struct { | ... | @@ -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 | const SequentialPrng = struct { | 287 | const SequentialPrng = struct { |
| 280 | const Self = @This(); | 288 | const Self = @This(); |
| 281 | random: Random, | 289 | random: Random, |