authorgravatar for git@e4m2.come4m2 <git@e4m2.com> 2023-08-15 12:02:24+02:00
committergravatar for git@e4m2.come4m2 <git@e4m2.com> 2023-08-15 12:02:24+02:00
logc0baed4a3e8cf710a90f9909fdf383e3c1c52682
tree51d24d421c6595a7a490e6f618a8809c6e15f052
parent6f129c9912369d4d7e22647f98e4d88b11b77bf0

std.rand: Accept ints with >64 bits in `uintLessThan`


1 files changed, 8 insertions(+), 14 deletions(-)

lib/std/rand.zig+8-14
......@@ -136,22 +136,16 @@ pub const Random = struct {
136136 pub fn uintLessThan(r: Random, comptime T: type, less_than: T) T {
137137 comptime assert(@typeInfo(T).Int.signedness == .unsigned);
138138 const bits = @typeInfo(T).Int.bits;
139 comptime assert(bits <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
140139 assert(0 < less_than);
141 // Small is typically u32
142 const small_bits = @divTrunc(bits + 31, 32) * 32;
143 const Small = std.meta.Int(.unsigned, small_bits);
144 // Large is typically u64
145 const Large = std.meta.Int(.unsigned, small_bits * 2);
146140
147141 // adapted from:
148142 // http://www.pcg-random.org/posts/bounded-rands.html
149143 // "Lemire's (with an extra tweak from me)"
150 var x: Small = r.int(Small);
151 var m: Large = @as(Large, x) * @as(Large, less_than);
152 var l: Small = @as(Small, @truncate(m));
144 var x = r.int(T);
145 var m = math.mulWide(T, x, less_than);
146 var l: T = @truncate(m);
153147 if (l < less_than) {
154 var t: Small = -%less_than;
148 var t = -%less_than;
155149
156150 if (t >= less_than) {
157151 t -= less_than;
......@@ -160,12 +154,12 @@ pub const Random = struct {
160154 }
161155 }
162156 while (l < t) {
163 x = r.int(Small);
164 m = @as(Large, x) * @as(Large, less_than);
165 l = @as(Small, @truncate(m));
157 x = r.int(T);
158 m = math.mulWide(T, x, less_than);
159 l = @truncate(m);
166160 }
167161 }
168 return @as(T, @intCast(m >> small_bits));
162 return @intCast(m >> bits);
169163 }
170164
171165 /// Constant-time implementation off `uintAtMost`.