| 1 | const builtin = @import("builtin"); |
| 2 | const std = @import("std"); |
| 3 | const symbol = @import("../../c.zig").symbol; |
| 4 | |
| 5 | comptime { |
| 6 | if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) { |
| 7 | symbol(&rand, "rand"); |
| 8 | symbol(&srand, "srand"); |
| 9 | symbol(&rand_r, "rand_r"); |
| 10 | } |
| 11 | } |
| 12 | |
| 13 | // NOTE: The PRNG used for `rand` is unspecified, so it can be any! |
| 14 | var rand_state: std.Random.SplitMix64 = .init(1); |
| 15 | |
| 16 | fn rand_r(seed: *c_uint) callconv(.c) c_int { |
| 17 | var mix: std.Random.SplitMix64 = .init(seed.*); |
| 18 | defer seed.* = @truncate(mix.s); |
| 19 | |
| 20 | // Every bundled libc defines RAND_MAX as `std.math.maxInt(u31)` (except windows where it is `std.math.maxInt(u15)`) |
| 21 | return @as(u31, @truncate(mix.next() >> 33)); |
| 22 | } |
| 23 | |
| 24 | fn srand(seed: c_uint) callconv(.c) void { |
| 25 | rand_state = .init(seed); |
| 26 | } |
| 27 | |
| 28 | fn rand() callconv(.c) c_int { |
| 29 | return @as(u31, @truncate(rand_state.next() >> 33)); |
| 30 | } |