authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2018-11-21 19:46:42-05:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2018-11-24 22:25:21-05:00
log9ae5200bd2851aab704b786f53a1495a9f58049e
tree0986fb8114e0597c8db6811244a17f2df7ada4c1
parenteed7b48fe3e02670b3d276e09a2dd376348baf68

factor out and expose biased range limiting function


1 files changed, 19 insertions(+), 11 deletions(-)

std/rand/index.zig+19-11
......@@ -63,17 +63,11 @@ pub const Random = struct {
6363 comptime assert(T.is_signed == false);
6464 comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
6565 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 }
7771 }
7872 /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`.
7973 /// This function assumes that the underlying ::fillFn produces evenly distributed values.
......@@ -276,6 +270,20 @@ pub const Random = struct {
276270 }
277271};
278272
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.
276pub 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
279287const SequentialPrng = struct {
280288 const Self = @This();
281289 random: Random,