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 {...@@ -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 u3266 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 u6468 } else {
69 const Large = @IntType(false, Small.bit_count * 2);69 return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than));
7070 }
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};
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
279const SequentialPrng = struct {287const SequentialPrng = struct {
280 const Self = @This();288 const Self = @This();
281 random: Random,289 random: Random,