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 {...@@ -136,22 +136,16 @@ pub const Random = struct {
136 pub fn uintLessThan(r: Random, comptime T: type, less_than: T) T {136 pub fn uintLessThan(r: Random, comptime T: type, less_than: T) T {
137 comptime assert(@typeInfo(T).Int.signedness == .unsigned);137 comptime assert(@typeInfo(T).Int.signedness == .unsigned);
138 const bits = @typeInfo(T).Int.bits;138 const bits = @typeInfo(T).Int.bits;
139 comptime assert(bits <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
140 assert(0 < less_than);139 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
147 // adapted from:141 // adapted from:
148 // http://www.pcg-random.org/posts/bounded-rands.html142 // http://www.pcg-random.org/posts/bounded-rands.html
149 // "Lemire's (with an extra tweak from me)"143 // "Lemire's (with an extra tweak from me)"
150 var x: Small = r.int(Small);144 var x = r.int(T);
151 var m: Large = @as(Large, x) * @as(Large, less_than);145 var m = math.mulWide(T, x, less_than);
152 var l: Small = @as(Small, @truncate(m));146 var l: T = @truncate(m);
153 if (l < less_than) {147 if (l < less_than) {
154 var t: Small = -%less_than;148 var t = -%less_than;
155149
156 if (t >= less_than) {150 if (t >= less_than) {
157 t -= less_than;151 t -= less_than;
...@@ -160,12 +154,12 @@ pub const Random = struct {...@@ -160,12 +154,12 @@ pub const Random = struct {
160 }154 }
161 }155 }
162 while (l < t) {156 while (l < t) {
163 x = r.int(Small);157 x = r.int(T);
164 m = @as(Large, x) * @as(Large, less_than);158 m = math.mulWide(T, x, less_than);
165 l = @as(Small, @truncate(m));159 l = @truncate(m);
166 }160 }
167 }161 }
168 return @as(T, @intCast(m >> small_bits));162 return @intCast(m >> bits);
169 }163 }
170164
171 /// Constant-time implementation off `uintAtMost`.165 /// Constant-time implementation off `uintAtMost`.