| ... | ... | @@ -47,6 +47,19 @@ pub const Random = struct { |
| 47 | 47 | return r.int(u1) != 0; |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | /// Returns a random value from an enum, evenly distributed. |
| 51 | pub fn enumValue(r: *Random, comptime EnumType: type) EnumType { |
| 52 | if (comptime !std.meta.trait.is(.Enum)(EnumType)) { |
| 53 | @compileError("Random.enumValue requires an enum type, not a " ++ @typeName(EnumType)); |
| 54 | } |
| 55 | |
| 56 | // We won't use int -> enum casting because enum elements can have |
| 57 | // arbitrary values. Instead we'll randomly pick one of the type's values. |
| 58 | const values = std.enums.values(EnumType); |
| 59 | const index = r.uintLessThan(usize, values.len); |
| 60 | return values[index]; |
| 61 | } |
| 62 | |
| 50 | 63 | /// Returns a random int `i` such that `0 <= i <= maxInt(T)`. |
| 51 | 64 | /// `i` is evenly distributed. |
| 52 | 65 | pub fn int(r: *Random, comptime T: type) T { |
| ... | ... | @@ -377,6 +390,23 @@ fn testRandomBoolean() !void { |
| 377 | 390 | try expect(r.random.boolean() == true); |
| 378 | 391 | } |
| 379 | 392 | |
| 393 | test "Random enum" { |
| 394 | try testRandomEnumValue(); |
| 395 | comptime try testRandomEnumValue(); |
| 396 | } |
| 397 | fn testRandomEnumValue() !void { |
| 398 | const TestEnum = enum { |
| 399 | First, |
| 400 | Second, |
| 401 | Third, |
| 402 | }; |
| 403 | var r = SequentialPrng.init(); |
| 404 | r.next_value = 0; |
| 405 | try expect(r.random.enumValue(TestEnum) == TestEnum.First); |
| 406 | try expect(r.random.enumValue(TestEnum) == TestEnum.First); |
| 407 | try expect(r.random.enumValue(TestEnum) == TestEnum.First); |
| 408 | } |
| 409 | |
| 380 | 410 | test "Random intLessThan" { |
| 381 | 411 | @setEvalBranchQuota(10000); |
| 382 | 412 | try testRandomIntLessThan(); |