From 9af077d71eaf2c004d63405fc5c017e237cb9c6c Mon Sep 17 00:00:00 2001 From: e4m2 Date: Thu, 8 Feb 2024 14:43:20 +0100 Subject: [PATCH 1/4] std.rand: Move to std.Random --- lib/std/Random.zig | 438 ++++++++++++++++++++ lib/std/{rand => Random}/Ascon.zig | 0 lib/std/{rand => Random}/ChaCha.zig | 0 lib/std/{rand => Random}/Isaac64.zig | 0 lib/std/{rand => Random}/Pcg.zig | 0 lib/std/{rand => Random}/RomuTrio.zig | 0 lib/std/{rand => Random}/Sfc64.zig | 0 lib/std/Random/SplitMix64.zig | 21 + lib/std/{rand => Random}/Xoroshiro128.zig | 0 lib/std/{rand => Random}/Xoshiro256.zig | 0 lib/std/{rand => Random}/benchmark.zig | 0 lib/std/{rand => Random}/test.zig | 8 +- lib/std/{rand => Random}/ziggurat.zig | 0 lib/std/rand.zig | 460 ---------------------- lib/std/std.zig | 5 +- 15 files changed, 466 insertions(+), 466 deletions(-) create mode 100644 lib/std/Random.zig rename lib/std/{rand => Random}/Ascon.zig (100%) rename lib/std/{rand => Random}/ChaCha.zig (100%) rename lib/std/{rand => Random}/Isaac64.zig (100%) rename lib/std/{rand => Random}/Pcg.zig (100%) rename lib/std/{rand => Random}/RomuTrio.zig (100%) rename lib/std/{rand => Random}/Sfc64.zig (100%) create mode 100644 lib/std/Random/SplitMix64.zig rename lib/std/{rand => Random}/Xoroshiro128.zig (100%) rename lib/std/{rand => Random}/Xoshiro256.zig (100%) rename lib/std/{rand => Random}/benchmark.zig (100%) rename lib/std/{rand => Random}/test.zig (98%) rename lib/std/{rand => Random}/ziggurat.zig (100%) delete mode 100644 lib/std/rand.zig diff --git a/lib/std/Random.zig b/lib/std/Random.zig new file mode 100644 index 0000000000..8f4ee0872c --- /dev/null +++ b/lib/std/Random.zig @@ -0,0 +1,438 @@ +//! The engines provided here should be initialized from an external source. +//! For a thread-local cryptographically secure pseudo random number generator, +//! use `std.crypto.random`. +//! Be sure to use a CSPRNG when required, otherwise using a normal PRNG will +//! be faster and use substantially less stack space. + +const std = @import("std.zig"); +const math = std.math; +const mem = std.mem; +const assert = std.debug.assert; +const maxInt = std.math.maxInt; +pub const Random = @This(); // Remove pub when `std.rand` namespace is removed. + +/// Fast unbiased random numbers. +pub const DefaultPrng = Xoshiro256; + +/// Cryptographically secure random numbers. +pub const DefaultCsprng = ChaCha; + +pub const Ascon = @import("Random/Ascon.zig"); +pub const ChaCha = @import("Random/ChaCha.zig"); + +pub const Isaac64 = @import("Random/Isaac64.zig"); +pub const Pcg = @import("Random/Pcg.zig"); +pub const Xoroshiro128 = @import("Random/Xoroshiro128.zig"); +pub const Xoshiro256 = @import("Random/Xoshiro256.zig"); +pub const Sfc64 = @import("Random/Sfc64.zig"); +pub const RomuTrio = @import("Random/RomuTrio.zig"); +pub const SplitMix64 = @import("Random/Splitmix64.zig"); +pub const ziggurat = @import("Random/ziggurat.zig"); + +ptr: *anyopaque, +fillFn: *const fn (ptr: *anyopaque, buf: []u8) void, + +pub fn init(pointer: anytype, comptime fillFn: fn (ptr: @TypeOf(pointer), buf: []u8) void) Random { + const Ptr = @TypeOf(pointer); + assert(@typeInfo(Ptr) == .Pointer); // Must be a pointer + assert(@typeInfo(Ptr).Pointer.size == .One); // Must be a single-item pointer + assert(@typeInfo(@typeInfo(Ptr).Pointer.child) == .Struct); // Must point to a struct + const gen = struct { + fn fill(ptr: *anyopaque, buf: []u8) void { + const self: Ptr = @ptrCast(@alignCast(ptr)); + fillFn(self, buf); + } + }; + + return .{ + .ptr = pointer, + .fillFn = gen.fill, + }; +} + +/// Read random bytes into the specified buffer until full. +pub fn bytes(r: Random, buf: []u8) void { + r.fillFn(r.ptr, buf); +} + +pub fn boolean(r: Random) bool { + return r.int(u1) != 0; +} + +/// Returns a random value from an enum, evenly distributed. +/// +/// Note that this will not yield consistent results across all targets +/// due to dependence on the representation of `usize` as an index. +/// See `enumValueWithIndex` for further commentary. +pub inline fn enumValue(r: Random, comptime EnumType: type) EnumType { + return r.enumValueWithIndex(EnumType, usize); +} + +/// Returns a random value from an enum, evenly distributed. +/// +/// An index into an array of all named values is generated using the +/// specified `Index` type to determine the return value. +/// This allows for results to be independent of `usize` representation. +/// +/// Prefer `enumValue` if this isn't important. +/// +/// See `uintLessThan`, which this function uses in most cases, +/// for commentary on the runtime of this function. +pub fn enumValueWithIndex(r: Random, comptime EnumType: type, comptime Index: type) EnumType { + comptime assert(@typeInfo(EnumType) == .Enum); + + // We won't use int -> enum casting because enum elements can have + // arbitrary values. Instead we'll randomly pick one of the type's values. + const values = comptime std.enums.values(EnumType); + comptime assert(values.len > 0); // can't return anything + comptime assert(maxInt(Index) >= values.len - 1); // can't access all values + comptime if (values.len == 1) return values[0]; + + const index = if (comptime values.len - 1 == maxInt(Index)) + r.int(Index) + else + r.uintLessThan(Index, values.len); + + const MinInt = MinArrayIndex(Index); + return values[@as(MinInt, @intCast(index))]; +} + +/// Returns a random int `i` such that `minInt(T) <= i <= maxInt(T)`. +/// `i` is evenly distributed. +pub fn int(r: Random, comptime T: type) T { + const bits = @typeInfo(T).Int.bits; + const UnsignedT = std.meta.Int(.unsigned, bits); + const ceil_bytes = comptime std.math.divCeil(u16, bits, 8) catch unreachable; + const ByteAlignedT = std.meta.Int(.unsigned, ceil_bytes * 8); + + var rand_bytes: [ceil_bytes]u8 = undefined; + r.bytes(&rand_bytes); + + // use LE instead of native endian for better portability maybe? + // TODO: endian portability is pointless if the underlying prng isn't endian portable. + // TODO: document the endian portability of this library. + const byte_aligned_result = mem.readInt(ByteAlignedT, &rand_bytes, .little); + const unsigned_result: UnsignedT = @truncate(byte_aligned_result); + return @bitCast(unsigned_result); +} + +/// Constant-time implementation off `uintLessThan`. +/// The results of this function may be biased. +pub fn uintLessThanBiased(r: Random, comptime T: type, less_than: T) T { + comptime assert(@typeInfo(T).Int.signedness == .unsigned); + assert(0 < less_than); + return limitRangeBiased(T, r.int(T), less_than); +} + +/// Returns an evenly distributed random unsigned integer `0 <= i < less_than`. +/// This function assumes that the underlying `fillFn` produces evenly distributed values. +/// Within this assumption, the runtime of this function is exponentially distributed. +/// If `fillFn` were backed by a true random generator, +/// the runtime of this function would technically be unbounded. +/// However, if `fillFn` is backed by any evenly distributed pseudo random number generator, +/// this function is guaranteed to return. +/// If you need deterministic runtime bounds, use `uintLessThanBiased`. +pub fn uintLessThan(r: Random, comptime T: type, less_than: T) T { + comptime assert(@typeInfo(T).Int.signedness == .unsigned); + const bits = @typeInfo(T).Int.bits; + assert(0 < less_than); + + // adapted from: + // http://www.pcg-random.org/posts/bounded-rands.html + // "Lemire's (with an extra tweak from me)" + var x = r.int(T); + var m = math.mulWide(T, x, less_than); + var l: T = @truncate(m); + if (l < less_than) { + var t = -%less_than; + + if (t >= less_than) { + t -= less_than; + if (t >= less_than) { + t %= less_than; + } + } + while (l < t) { + x = r.int(T); + m = math.mulWide(T, x, less_than); + l = @truncate(m); + } + } + return @intCast(m >> bits); +} + +/// Constant-time implementation off `uintAtMost`. +/// The results of this function may be biased. +pub fn uintAtMostBiased(r: Random, comptime T: type, at_most: T) T { + assert(@typeInfo(T).Int.signedness == .unsigned); + if (at_most == maxInt(T)) { + // have the full range + return r.int(T); + } + return r.uintLessThanBiased(T, at_most + 1); +} + +/// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`. +/// See `uintLessThan`, which this function uses in most cases, +/// for commentary on the runtime of this function. +pub fn uintAtMost(r: Random, comptime T: type, at_most: T) T { + assert(@typeInfo(T).Int.signedness == .unsigned); + if (at_most == maxInt(T)) { + // have the full range + return r.int(T); + } + return r.uintLessThan(T, at_most + 1); +} + +/// Constant-time implementation off `intRangeLessThan`. +/// The results of this function may be biased. +pub fn intRangeLessThanBiased(r: Random, comptime T: type, at_least: T, less_than: T) T { + assert(at_least < less_than); + const info = @typeInfo(T).Int; + if (info.signedness == .signed) { + // Two's complement makes this math pretty easy. + const UnsignedT = std.meta.Int(.unsigned, info.bits); + const lo: UnsignedT = @bitCast(at_least); + const hi: UnsignedT = @bitCast(less_than); + const result = lo +% r.uintLessThanBiased(UnsignedT, hi -% lo); + return @bitCast(result); + } else { + // The signed implementation would work fine, but we can use stricter arithmetic operators here. + return at_least + r.uintLessThanBiased(T, less_than - at_least); + } +} + +/// Returns an evenly distributed random integer `at_least <= i < less_than`. +/// See `uintLessThan`, which this function uses in most cases, +/// for commentary on the runtime of this function. +pub fn intRangeLessThan(r: Random, comptime T: type, at_least: T, less_than: T) T { + assert(at_least < less_than); + const info = @typeInfo(T).Int; + if (info.signedness == .signed) { + // Two's complement makes this math pretty easy. + const UnsignedT = std.meta.Int(.unsigned, info.bits); + const lo: UnsignedT = @bitCast(at_least); + const hi: UnsignedT = @bitCast(less_than); + const result = lo +% r.uintLessThan(UnsignedT, hi -% lo); + return @bitCast(result); + } else { + // The signed implementation would work fine, but we can use stricter arithmetic operators here. + return at_least + r.uintLessThan(T, less_than - at_least); + } +} + +/// Constant-time implementation off `intRangeAtMostBiased`. +/// The results of this function may be biased. +pub fn intRangeAtMostBiased(r: Random, comptime T: type, at_least: T, at_most: T) T { + assert(at_least <= at_most); + const info = @typeInfo(T).Int; + if (info.signedness == .signed) { + // Two's complement makes this math pretty easy. + const UnsignedT = std.meta.Int(.unsigned, info.bits); + const lo: UnsignedT = @bitCast(at_least); + const hi: UnsignedT = @bitCast(at_most); + const result = lo +% r.uintAtMostBiased(UnsignedT, hi -% lo); + return @bitCast(result); + } else { + // The signed implementation would work fine, but we can use stricter arithmetic operators here. + return at_least + r.uintAtMostBiased(T, at_most - at_least); + } +} + +/// Returns an evenly distributed random integer `at_least <= i <= at_most`. +/// See `uintLessThan`, which this function uses in most cases, +/// for commentary on the runtime of this function. +pub fn intRangeAtMost(r: Random, comptime T: type, at_least: T, at_most: T) T { + assert(at_least <= at_most); + const info = @typeInfo(T).Int; + if (info.signedness == .signed) { + // Two's complement makes this math pretty easy. + const UnsignedT = std.meta.Int(.unsigned, info.bits); + const lo: UnsignedT = @bitCast(at_least); + const hi: UnsignedT = @bitCast(at_most); + const result = lo +% r.uintAtMost(UnsignedT, hi -% lo); + return @bitCast(result); + } else { + // The signed implementation would work fine, but we can use stricter arithmetic operators here. + return at_least + r.uintAtMost(T, at_most - at_least); + } +} + +/// Return a floating point value evenly distributed in the range [0, 1). +pub fn float(r: Random, comptime T: type) T { + // Generate a uniformly random value for the mantissa. + // Then generate an exponentially biased random value for the exponent. + // This covers every possible value in the range. + switch (T) { + f32 => { + // Use 23 random bits for the mantissa, and the rest for the exponent. + // If all 41 bits are zero, generate additional random bits, until a + // set bit is found, or 126 bits have been generated. + const rand = r.int(u64); + var rand_lz = @clz(rand); + if (rand_lz >= 41) { + // TODO: when #5177 or #489 is implemented, + // tell the compiler it is unlikely (1/2^41) to reach this point. + // (Same for the if branch and the f64 calculations below.) + rand_lz = 41 + @clz(r.int(u64)); + if (rand_lz == 41 + 64) { + // It is astronomically unlikely to reach this point. + rand_lz += @clz(r.int(u32) | 0x7FF); + } + } + const mantissa: u23 = @truncate(rand); + const exponent = @as(u32, 126 - rand_lz) << 23; + return @bitCast(exponent | mantissa); + }, + f64 => { + // Use 52 random bits for the mantissa, and the rest for the exponent. + // If all 12 bits are zero, generate additional random bits, until a + // set bit is found, or 1022 bits have been generated. + const rand = r.int(u64); + var rand_lz: u64 = @clz(rand); + if (rand_lz >= 12) { + rand_lz = 12; + while (true) { + // It is astronomically unlikely for this loop to execute more than once. + const addl_rand_lz = @clz(r.int(u64)); + rand_lz += addl_rand_lz; + if (addl_rand_lz != 64) { + break; + } + if (rand_lz >= 1022) { + rand_lz = 1022; + break; + } + } + } + const mantissa = rand & 0xFFFFFFFFFFFFF; + const exponent = (1022 - rand_lz) << 52; + return @bitCast(exponent | mantissa); + }, + else => @compileError("unknown floating point type"), + } +} + +/// Return a floating point value normally distributed with mean = 0, stddev = 1. +/// +/// To use different parameters, use: floatNorm(...) * desiredStddev + desiredMean. +pub fn floatNorm(r: Random, comptime T: type) T { + const value = ziggurat.next_f64(r, ziggurat.NormDist); + switch (T) { + f32 => return @floatCast(value), + f64 => return value, + else => @compileError("unknown floating point type"), + } +} + +/// Return an exponentially distributed float with a rate parameter of 1. +/// +/// To use a different rate parameter, use: floatExp(...) / desiredRate. +pub fn floatExp(r: Random, comptime T: type) T { + const value = ziggurat.next_f64(r, ziggurat.ExpDist); + switch (T) { + f32 => return @floatCast(value), + f64 => return value, + else => @compileError("unknown floating point type"), + } +} + +/// Shuffle a slice into a random order. +/// +/// Note that this will not yield consistent results across all targets +/// due to dependence on the representation of `usize` as an index. +/// See `shuffleWithIndex` for further commentary. +pub inline fn shuffle(r: Random, comptime T: type, buf: []T) void { + r.shuffleWithIndex(T, buf, usize); +} + +/// Shuffle a slice into a random order, using an index of a +/// specified type to maintain distribution across targets. +/// Asserts the index type can represent `buf.len`. +/// +/// Indexes into the slice are generated using the specified `Index` +/// type, which determines distribution properties. This allows for +/// results to be independent of `usize` representation. +/// +/// Prefer `shuffle` if this isn't important. +/// +/// See `intRangeLessThan`, which this function uses, +/// for commentary on the runtime of this function. +pub fn shuffleWithIndex(r: Random, comptime T: type, buf: []T, comptime Index: type) void { + const MinInt = MinArrayIndex(Index); + if (buf.len < 2) { + return; + } + + // `i <= j < max <= maxInt(MinInt)` + const max: MinInt = @intCast(buf.len); + var i: MinInt = 0; + while (i < max - 1) : (i += 1) { + const j: MinInt = @intCast(r.intRangeLessThan(Index, i, max)); + mem.swap(T, &buf[i], &buf[j]); + } +} + +/// Randomly selects an index into `proportions`, where the likelihood of each +/// index is weighted by that proportion. +/// It is more likely for the index of the last proportion to be returned +/// than the index of the first proportion in the slice, and vice versa. +/// +/// This is useful for selecting an item from a slice where weights are not equal. +/// `T` must be a numeric type capable of holding the sum of `proportions`. +pub fn weightedIndex(r: std.rand.Random, comptime T: type, proportions: []const T) usize { + // This implementation works by summing the proportions and picking a + // random point in [0, sum). We then loop over the proportions, + // accumulating until our accumulator is greater than the random point. + + const sum = s: { + var sum: T = 0; + for (proportions) |v| sum += v; + break :s sum; + }; + + const point = switch (@typeInfo(T)) { + .Int => |int_info| switch (int_info.signedness) { + .signed => r.intRangeLessThan(T, 0, sum), + .unsigned => r.uintLessThan(T, sum), + }, + // take care that imprecision doesn't lead to a value slightly greater than sum + .Float => @min(r.float(T) * sum, sum - std.math.floatEps(T)), + else => @compileError("weightedIndex does not support proportions of type " ++ + @typeName(T)), + }; + + assert(point < sum); + + var accumulator: T = 0; + for (proportions, 0..) |p, index| { + accumulator += p; + if (point < accumulator) return index; + } else unreachable; +} + +/// Convert a random integer 0 <= random_int <= maxValue(T), +/// into an integer 0 <= result < less_than. +/// This function introduces a minor bias. +pub fn limitRangeBiased(comptime T: type, random_int: T, less_than: T) T { + comptime assert(@typeInfo(T).Int.signedness == .unsigned); + const bits = @typeInfo(T).Int.bits; + + // adapted from: + // http://www.pcg-random.org/posts/bounded-rands.html + // "Integer Multiplication (Biased)" + const m = math.mulWide(T, random_int, less_than); + return @intCast(m >> bits); +} + +/// Returns the smallest of `Index` and `usize`. +fn MinArrayIndex(comptime Index: type) type { + const index_info = @typeInfo(Index).Int; + assert(index_info.signedness == .unsigned); + return if (index_info.bits >= @typeInfo(usize).Int.bits) usize else Index; +} + +test { + std.testing.refAllDecls(@This()); + _ = @import("Random/test.zig"); +} diff --git a/lib/std/rand/Ascon.zig b/lib/std/Random/Ascon.zig similarity index 100% rename from lib/std/rand/Ascon.zig rename to lib/std/Random/Ascon.zig diff --git a/lib/std/rand/ChaCha.zig b/lib/std/Random/ChaCha.zig similarity index 100% rename from lib/std/rand/ChaCha.zig rename to lib/std/Random/ChaCha.zig diff --git a/lib/std/rand/Isaac64.zig b/lib/std/Random/Isaac64.zig similarity index 100% rename from lib/std/rand/Isaac64.zig rename to lib/std/Random/Isaac64.zig diff --git a/lib/std/rand/Pcg.zig b/lib/std/Random/Pcg.zig similarity index 100% rename from lib/std/rand/Pcg.zig rename to lib/std/Random/Pcg.zig diff --git a/lib/std/rand/RomuTrio.zig b/lib/std/Random/RomuTrio.zig similarity index 100% rename from lib/std/rand/RomuTrio.zig rename to lib/std/Random/RomuTrio.zig diff --git a/lib/std/rand/Sfc64.zig b/lib/std/Random/Sfc64.zig similarity index 100% rename from lib/std/rand/Sfc64.zig rename to lib/std/Random/Sfc64.zig diff --git a/lib/std/Random/SplitMix64.zig b/lib/std/Random/SplitMix64.zig new file mode 100644 index 0000000000..9f085162e3 --- /dev/null +++ b/lib/std/Random/SplitMix64.zig @@ -0,0 +1,21 @@ +//! Generator to extend 64-bit seed values into longer sequences. +//! +//! The number of cycles is thus limited to 64-bits regardless of the engine, but this +//! is still plenty for practical purposes. + +const SplitMix64 = @This(); + +s: u64, + +pub fn init(seed: u64) SplitMix64 { + return SplitMix64{ .s = seed }; +} + +pub fn next(self: *SplitMix64) u64 { + self.s +%= 0x9e3779b97f4a7c15; + + var z = self.s; + z = (z ^ (z >> 30)) *% 0xbf58476d1ce4e5b9; + z = (z ^ (z >> 27)) *% 0x94d049bb133111eb; + return z ^ (z >> 31); +} diff --git a/lib/std/rand/Xoroshiro128.zig b/lib/std/Random/Xoroshiro128.zig similarity index 100% rename from lib/std/rand/Xoroshiro128.zig rename to lib/std/Random/Xoroshiro128.zig diff --git a/lib/std/rand/Xoshiro256.zig b/lib/std/Random/Xoshiro256.zig similarity index 100% rename from lib/std/rand/Xoshiro256.zig rename to lib/std/Random/Xoshiro256.zig diff --git a/lib/std/rand/benchmark.zig b/lib/std/Random/benchmark.zig similarity index 100% rename from lib/std/rand/benchmark.zig rename to lib/std/Random/benchmark.zig diff --git a/lib/std/rand/test.zig b/lib/std/Random/test.zig similarity index 98% rename from lib/std/rand/test.zig rename to lib/std/Random/test.zig index d498985097..8ceacbc934 100644 --- a/lib/std/rand/test.zig +++ b/lib/std/Random/test.zig @@ -1,9 +1,9 @@ const std = @import("../std.zig"); const math = std.math; -const DefaultPrng = std.rand.DefaultPrng; -const Random = std.rand.Random; -const SplitMix64 = std.rand.SplitMix64; -const DefaultCsprng = std.rand.DefaultCsprng; +const Random = std.Random; +const DefaultPrng = Random.DefaultPrng; +const SplitMix64 = Random.SplitMix64; +const DefaultCsprng = Random.DefaultCsprng; const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; diff --git a/lib/std/rand/ziggurat.zig b/lib/std/Random/ziggurat.zig similarity index 100% rename from lib/std/rand/ziggurat.zig rename to lib/std/Random/ziggurat.zig diff --git a/lib/std/rand.zig b/lib/std/rand.zig deleted file mode 100644 index 708eed13be..0000000000 --- a/lib/std/rand.zig +++ /dev/null @@ -1,460 +0,0 @@ -//! The engines provided here should be initialized from an external source. -//! For a thread-local cryptographically secure pseudo random number generator, -//! use `std.crypto.random`. -//! Be sure to use a CSPRNG when required, otherwise using a normal PRNG will -//! be faster and use substantially less stack space. - -const std = @import("std.zig"); -const builtin = @import("builtin"); -const assert = std.debug.assert; -const mem = std.mem; -const math = std.math; -const maxInt = std.math.maxInt; - -/// Fast unbiased random numbers. -pub const DefaultPrng = Xoshiro256; - -/// Cryptographically secure random numbers. -pub const DefaultCsprng = ChaCha; - -pub const Ascon = @import("rand/Ascon.zig"); -pub const ChaCha = @import("rand/ChaCha.zig"); - -pub const Isaac64 = @import("rand/Isaac64.zig"); -pub const Pcg = @import("rand/Pcg.zig"); -pub const Xoroshiro128 = @import("rand/Xoroshiro128.zig"); -pub const Xoshiro256 = @import("rand/Xoshiro256.zig"); -pub const Sfc64 = @import("rand/Sfc64.zig"); -pub const RomuTrio = @import("rand/RomuTrio.zig"); -pub const ziggurat = @import("rand/ziggurat.zig"); - -pub const Random = struct { - ptr: *anyopaque, - fillFn: *const fn (ptr: *anyopaque, buf: []u8) void, - - pub fn init(pointer: anytype, comptime fillFn: fn (ptr: @TypeOf(pointer), buf: []u8) void) Random { - const Ptr = @TypeOf(pointer); - assert(@typeInfo(Ptr) == .Pointer); // Must be a pointer - assert(@typeInfo(Ptr).Pointer.size == .One); // Must be a single-item pointer - assert(@typeInfo(@typeInfo(Ptr).Pointer.child) == .Struct); // Must point to a struct - const gen = struct { - fn fill(ptr: *anyopaque, buf: []u8) void { - const self: Ptr = @ptrCast(@alignCast(ptr)); - fillFn(self, buf); - } - }; - - return .{ - .ptr = pointer, - .fillFn = gen.fill, - }; - } - - /// Read random bytes into the specified buffer until full. - pub fn bytes(r: Random, buf: []u8) void { - r.fillFn(r.ptr, buf); - } - - pub fn boolean(r: Random) bool { - return r.int(u1) != 0; - } - - /// Returns a random value from an enum, evenly distributed. - /// - /// Note that this will not yield consistent results across all targets - /// due to dependence on the representation of `usize` as an index. - /// See `enumValueWithIndex` for further commentary. - pub inline fn enumValue(r: Random, comptime EnumType: type) EnumType { - return r.enumValueWithIndex(EnumType, usize); - } - - /// Returns a random value from an enum, evenly distributed. - /// - /// An index into an array of all named values is generated using the - /// specified `Index` type to determine the return value. - /// This allows for results to be independent of `usize` representation. - /// - /// Prefer `enumValue` if this isn't important. - /// - /// See `uintLessThan`, which this function uses in most cases, - /// for commentary on the runtime of this function. - pub fn enumValueWithIndex(r: Random, comptime EnumType: type, comptime Index: type) EnumType { - comptime assert(@typeInfo(EnumType) == .Enum); - - // We won't use int -> enum casting because enum elements can have - // arbitrary values. Instead we'll randomly pick one of the type's values. - const values = comptime std.enums.values(EnumType); - comptime assert(values.len > 0); // can't return anything - comptime assert(maxInt(Index) >= values.len - 1); // can't access all values - comptime if (values.len == 1) return values[0]; - - const index = if (comptime values.len - 1 == maxInt(Index)) - r.int(Index) - else - r.uintLessThan(Index, values.len); - - const MinInt = MinArrayIndex(Index); - return values[@as(MinInt, @intCast(index))]; - } - - /// Returns a random int `i` such that `minInt(T) <= i <= maxInt(T)`. - /// `i` is evenly distributed. - pub fn int(r: Random, comptime T: type) T { - const bits = @typeInfo(T).Int.bits; - const UnsignedT = std.meta.Int(.unsigned, bits); - const ceil_bytes = comptime std.math.divCeil(u16, bits, 8) catch unreachable; - const ByteAlignedT = std.meta.Int(.unsigned, ceil_bytes * 8); - - var rand_bytes: [ceil_bytes]u8 = undefined; - r.bytes(&rand_bytes); - - // use LE instead of native endian for better portability maybe? - // TODO: endian portability is pointless if the underlying prng isn't endian portable. - // TODO: document the endian portability of this library. - const byte_aligned_result = mem.readInt(ByteAlignedT, &rand_bytes, .little); - const unsigned_result: UnsignedT = @truncate(byte_aligned_result); - return @bitCast(unsigned_result); - } - - /// Constant-time implementation off `uintLessThan`. - /// The results of this function may be biased. - pub fn uintLessThanBiased(r: Random, comptime T: type, less_than: T) T { - comptime assert(@typeInfo(T).Int.signedness == .unsigned); - assert(0 < less_than); - return limitRangeBiased(T, r.int(T), less_than); - } - - /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`. - /// This function assumes that the underlying `fillFn` produces evenly distributed values. - /// Within this assumption, the runtime of this function is exponentially distributed. - /// If `fillFn` were backed by a true random generator, - /// the runtime of this function would technically be unbounded. - /// However, if `fillFn` is backed by any evenly distributed pseudo random number generator, - /// this function is guaranteed to return. - /// If you need deterministic runtime bounds, use `uintLessThanBiased`. - pub fn uintLessThan(r: Random, comptime T: type, less_than: T) T { - comptime assert(@typeInfo(T).Int.signedness == .unsigned); - const bits = @typeInfo(T).Int.bits; - assert(0 < less_than); - - // adapted from: - // http://www.pcg-random.org/posts/bounded-rands.html - // "Lemire's (with an extra tweak from me)" - var x = r.int(T); - var m = math.mulWide(T, x, less_than); - var l: T = @truncate(m); - if (l < less_than) { - var t = -%less_than; - - if (t >= less_than) { - t -= less_than; - if (t >= less_than) { - t %= less_than; - } - } - while (l < t) { - x = r.int(T); - m = math.mulWide(T, x, less_than); - l = @truncate(m); - } - } - return @intCast(m >> bits); - } - - /// Constant-time implementation off `uintAtMost`. - /// The results of this function may be biased. - pub fn uintAtMostBiased(r: Random, comptime T: type, at_most: T) T { - assert(@typeInfo(T).Int.signedness == .unsigned); - if (at_most == maxInt(T)) { - // have the full range - return r.int(T); - } - return r.uintLessThanBiased(T, at_most + 1); - } - - /// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`. - /// See `uintLessThan`, which this function uses in most cases, - /// for commentary on the runtime of this function. - pub fn uintAtMost(r: Random, comptime T: type, at_most: T) T { - assert(@typeInfo(T).Int.signedness == .unsigned); - if (at_most == maxInt(T)) { - // have the full range - return r.int(T); - } - return r.uintLessThan(T, at_most + 1); - } - - /// Constant-time implementation off `intRangeLessThan`. - /// The results of this function may be biased. - pub fn intRangeLessThanBiased(r: Random, comptime T: type, at_least: T, less_than: T) T { - assert(at_least < less_than); - const info = @typeInfo(T).Int; - if (info.signedness == .signed) { - // Two's complement makes this math pretty easy. - const UnsignedT = std.meta.Int(.unsigned, info.bits); - const lo: UnsignedT = @bitCast(at_least); - const hi: UnsignedT = @bitCast(less_than); - const result = lo +% r.uintLessThanBiased(UnsignedT, hi -% lo); - return @bitCast(result); - } else { - // The signed implementation would work fine, but we can use stricter arithmetic operators here. - return at_least + r.uintLessThanBiased(T, less_than - at_least); - } - } - - /// Returns an evenly distributed random integer `at_least <= i < less_than`. - /// See `uintLessThan`, which this function uses in most cases, - /// for commentary on the runtime of this function. - pub fn intRangeLessThan(r: Random, comptime T: type, at_least: T, less_than: T) T { - assert(at_least < less_than); - const info = @typeInfo(T).Int; - if (info.signedness == .signed) { - // Two's complement makes this math pretty easy. - const UnsignedT = std.meta.Int(.unsigned, info.bits); - const lo: UnsignedT = @bitCast(at_least); - const hi: UnsignedT = @bitCast(less_than); - const result = lo +% r.uintLessThan(UnsignedT, hi -% lo); - return @bitCast(result); - } else { - // The signed implementation would work fine, but we can use stricter arithmetic operators here. - return at_least + r.uintLessThan(T, less_than - at_least); - } - } - - /// Constant-time implementation off `intRangeAtMostBiased`. - /// The results of this function may be biased. - pub fn intRangeAtMostBiased(r: Random, comptime T: type, at_least: T, at_most: T) T { - assert(at_least <= at_most); - const info = @typeInfo(T).Int; - if (info.signedness == .signed) { - // Two's complement makes this math pretty easy. - const UnsignedT = std.meta.Int(.unsigned, info.bits); - const lo: UnsignedT = @bitCast(at_least); - const hi: UnsignedT = @bitCast(at_most); - const result = lo +% r.uintAtMostBiased(UnsignedT, hi -% lo); - return @bitCast(result); - } else { - // The signed implementation would work fine, but we can use stricter arithmetic operators here. - return at_least + r.uintAtMostBiased(T, at_most - at_least); - } - } - - /// Returns an evenly distributed random integer `at_least <= i <= at_most`. - /// See `uintLessThan`, which this function uses in most cases, - /// for commentary on the runtime of this function. - pub fn intRangeAtMost(r: Random, comptime T: type, at_least: T, at_most: T) T { - assert(at_least <= at_most); - const info = @typeInfo(T).Int; - if (info.signedness == .signed) { - // Two's complement makes this math pretty easy. - const UnsignedT = std.meta.Int(.unsigned, info.bits); - const lo: UnsignedT = @bitCast(at_least); - const hi: UnsignedT = @bitCast(at_most); - const result = lo +% r.uintAtMost(UnsignedT, hi -% lo); - return @bitCast(result); - } else { - // The signed implementation would work fine, but we can use stricter arithmetic operators here. - return at_least + r.uintAtMost(T, at_most - at_least); - } - } - - /// Return a floating point value evenly distributed in the range [0, 1). - pub fn float(r: Random, comptime T: type) T { - // Generate a uniformly random value for the mantissa. - // Then generate an exponentially biased random value for the exponent. - // This covers every possible value in the range. - switch (T) { - f32 => { - // Use 23 random bits for the mantissa, and the rest for the exponent. - // If all 41 bits are zero, generate additional random bits, until a - // set bit is found, or 126 bits have been generated. - const rand = r.int(u64); - var rand_lz = @clz(rand); - if (rand_lz >= 41) { - // TODO: when #5177 or #489 is implemented, - // tell the compiler it is unlikely (1/2^41) to reach this point. - // (Same for the if branch and the f64 calculations below.) - rand_lz = 41 + @clz(r.int(u64)); - if (rand_lz == 41 + 64) { - // It is astronomically unlikely to reach this point. - rand_lz += @clz(r.int(u32) | 0x7FF); - } - } - const mantissa: u23 = @truncate(rand); - const exponent = @as(u32, 126 - rand_lz) << 23; - return @bitCast(exponent | mantissa); - }, - f64 => { - // Use 52 random bits for the mantissa, and the rest for the exponent. - // If all 12 bits are zero, generate additional random bits, until a - // set bit is found, or 1022 bits have been generated. - const rand = r.int(u64); - var rand_lz: u64 = @clz(rand); - if (rand_lz >= 12) { - rand_lz = 12; - while (true) { - // It is astronomically unlikely for this loop to execute more than once. - const addl_rand_lz = @clz(r.int(u64)); - rand_lz += addl_rand_lz; - if (addl_rand_lz != 64) { - break; - } - if (rand_lz >= 1022) { - rand_lz = 1022; - break; - } - } - } - const mantissa = rand & 0xFFFFFFFFFFFFF; - const exponent = (1022 - rand_lz) << 52; - return @bitCast(exponent | mantissa); - }, - else => @compileError("unknown floating point type"), - } - } - - /// Return a floating point value normally distributed with mean = 0, stddev = 1. - /// - /// To use different parameters, use: floatNorm(...) * desiredStddev + desiredMean. - pub fn floatNorm(r: Random, comptime T: type) T { - const value = ziggurat.next_f64(r, ziggurat.NormDist); - switch (T) { - f32 => return @floatCast(value), - f64 => return value, - else => @compileError("unknown floating point type"), - } - } - - /// Return an exponentially distributed float with a rate parameter of 1. - /// - /// To use a different rate parameter, use: floatExp(...) / desiredRate. - pub fn floatExp(r: Random, comptime T: type) T { - const value = ziggurat.next_f64(r, ziggurat.ExpDist); - switch (T) { - f32 => return @floatCast(value), - f64 => return value, - else => @compileError("unknown floating point type"), - } - } - - /// Shuffle a slice into a random order. - /// - /// Note that this will not yield consistent results across all targets - /// due to dependence on the representation of `usize` as an index. - /// See `shuffleWithIndex` for further commentary. - pub inline fn shuffle(r: Random, comptime T: type, buf: []T) void { - r.shuffleWithIndex(T, buf, usize); - } - - /// Shuffle a slice into a random order, using an index of a - /// specified type to maintain distribution across targets. - /// Asserts the index type can represent `buf.len`. - /// - /// Indexes into the slice are generated using the specified `Index` - /// type, which determines distribution properties. This allows for - /// results to be independent of `usize` representation. - /// - /// Prefer `shuffle` if this isn't important. - /// - /// See `intRangeLessThan`, which this function uses, - /// for commentary on the runtime of this function. - pub fn shuffleWithIndex(r: Random, comptime T: type, buf: []T, comptime Index: type) void { - const MinInt = MinArrayIndex(Index); - if (buf.len < 2) { - return; - } - - // `i <= j < max <= maxInt(MinInt)` - const max: MinInt = @intCast(buf.len); - var i: MinInt = 0; - while (i < max - 1) : (i += 1) { - const j: MinInt = @intCast(r.intRangeLessThan(Index, i, max)); - mem.swap(T, &buf[i], &buf[j]); - } - } - - /// Randomly selects an index into `proportions`, where the likelihood of each - /// index is weighted by that proportion. - /// It is more likely for the index of the last proportion to be returned - /// than the index of the first proportion in the slice, and vice versa. - /// - /// This is useful for selecting an item from a slice where weights are not equal. - /// `T` must be a numeric type capable of holding the sum of `proportions`. - pub fn weightedIndex(r: std.rand.Random, comptime T: type, proportions: []const T) usize { - // This implementation works by summing the proportions and picking a - // random point in [0, sum). We then loop over the proportions, - // accumulating until our accumulator is greater than the random point. - - const sum = s: { - var sum: T = 0; - for (proportions) |v| sum += v; - break :s sum; - }; - - const point = switch (@typeInfo(T)) { - .Int => |int_info| switch (int_info.signedness) { - .signed => r.intRangeLessThan(T, 0, sum), - .unsigned => r.uintLessThan(T, sum), - }, - // take care that imprecision doesn't lead to a value slightly greater than sum - .Float => @min(r.float(T) * sum, sum - std.math.floatEps(T)), - else => @compileError("weightedIndex does not support proportions of type " ++ - @typeName(T)), - }; - - assert(point < sum); - - var accumulator: T = 0; - for (proportions, 0..) |p, index| { - accumulator += p; - if (point < accumulator) return index; - } else unreachable; - } - - /// Returns the smallest of `Index` and `usize`. - fn MinArrayIndex(comptime Index: type) type { - const index_info = @typeInfo(Index).Int; - assert(index_info.signedness == .unsigned); - return if (index_info.bits >= @typeInfo(usize).Int.bits) usize else Index; - } -}; - -/// Convert a random integer 0 <= random_int <= maxValue(T), -/// into an integer 0 <= result < less_than. -/// This function introduces a minor bias. -pub fn limitRangeBiased(comptime T: type, random_int: T, less_than: T) T { - comptime assert(@typeInfo(T).Int.signedness == .unsigned); - const bits = @typeInfo(T).Int.bits; - - // adapted from: - // http://www.pcg-random.org/posts/bounded-rands.html - // "Integer Multiplication (Biased)" - const m = math.mulWide(T, random_int, less_than); - return @intCast(m >> bits); -} - -// Generator to extend 64-bit seed values into longer sequences. -// -// The number of cycles is thus limited to 64-bits regardless of the engine, but this -// is still plenty for practical purposes. -pub const SplitMix64 = struct { - s: u64, - - pub fn init(seed: u64) SplitMix64 { - return SplitMix64{ .s = seed }; - } - - pub fn next(self: *SplitMix64) u64 { - self.s +%= 0x9e3779b97f4a7c15; - - var z = self.s; - z = (z ^ (z >> 30)) *% 0xbf58476d1ce4e5b9; - z = (z ^ (z >> 27)) *% 0x94d049bb133111eb; - return z ^ (z >> 31); - } -}; - -test { - std.testing.refAllDecls(@This()); - _ = @import("rand/test.zig"); -} diff --git a/lib/std/std.zig b/lib/std/std.zig index 047da005c3..6f60ad0f00 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -36,6 +36,7 @@ pub const PackedIntSliceEndian = @import("packed_int_array.zig").PackedIntSliceE pub const PriorityQueue = @import("priority_queue.zig").PriorityQueue; pub const PriorityDequeue = @import("priority_dequeue.zig").PriorityDequeue; pub const Progress = @import("Progress.zig"); +pub const Random = @import("Random.zig"); pub const RingBuffer = @import("RingBuffer.zig"); pub const SegmentedList = @import("segmented_list.zig").SegmentedList; pub const SemanticVersion = @import("SemanticVersion.zig"); @@ -159,8 +160,8 @@ pub const pdb = @import("pdb.zig"); /// and spawning of child processes. pub const process = @import("process.zig"); -/// Fast pseudo-random number generators (i.e. not cryptographically secure). -pub const rand = @import("rand.zig"); +/// Deprecated: use `Random` instead. +pub const rand = Random; /// Sorting. pub const sort = @import("sort.zig"); From 8d56e472c9fa97dc6eeae9866eed927910f7dfe2 Mon Sep 17 00:00:00 2001 From: e4m2 Date: Thu, 8 Feb 2024 15:21:35 +0100 Subject: [PATCH 2/4] Replace std.rand references with std.Random --- lib/build_runner.zig | 4 ++-- lib/compiler_rt/paritydi2_test.zig | 2 +- lib/compiler_rt/paritysi2_test.zig | 2 +- lib/compiler_rt/parityti2_test.zig | 2 +- lib/compiler_rt/popcountdi2_test.zig | 2 +- lib/compiler_rt/popcountsi2_test.zig | 2 +- lib/compiler_rt/popcountti2_test.zig | 2 +- lib/compiler_rt/udivmodei4.zig | 2 +- lib/std/Random.zig | 2 +- lib/std/Random/Ascon.zig | 7 +++---- lib/std/Random/ChaCha.zig | 7 +++---- lib/std/Random/Isaac64.zig | 5 ++--- lib/std/Random/Pcg.zig | 7 +++---- lib/std/Random/RomuTrio.zig | 7 +++---- lib/std/Random/Sfc64.zig | 5 ++--- lib/std/Random/Xoroshiro128.zig | 7 +++---- lib/std/Random/Xoshiro256.zig | 7 +++---- lib/std/Random/benchmark.zig | 18 +++++++++--------- lib/std/Random/ziggurat.zig | 6 +++--- lib/std/Thread/RwLock.zig | 2 +- lib/std/crypto/benchmark.zig | 2 +- lib/std/crypto/kyber_d00.zig | 2 +- lib/std/crypto/tlcsprng.zig | 4 ++-- lib/std/hash/benchmark.zig | 2 +- lib/std/hash_map.zig | 4 ++-- lib/std/heap/arena_allocator.zig | 2 +- lib/std/io/test.zig | 2 +- lib/std/math/big/rational.zig | 2 +- lib/std/mem.zig | 2 +- lib/std/priority_dequeue.zig | 14 +++++++------- lib/std/sort.zig | 2 +- lib/std/treap.zig | 8 ++++---- src/reduce.zig | 4 ++-- src/resinator/compile.zig | 2 +- 34 files changed, 71 insertions(+), 79 deletions(-) diff --git a/lib/build_runner.zig b/lib/build_runner.zig index 5c1daaaf42..d4a503a5c5 100644 --- a/lib/build_runner.zig +++ b/lib/build_runner.zig @@ -420,7 +420,7 @@ fn runStepNames( const starting_steps = try arena.dupe(*Step, step_stack.keys()); - var rng = std.rand.DefaultPrng.init(seed); + var rng = std.Random.DefaultPrng.init(seed); const rand = rng.random(); rand.shuffle(*Step, starting_steps); @@ -836,7 +836,7 @@ fn constructGraphAndCheckForDependencyLoop( b: *std.Build, s: *Step, step_stack: *std.AutoArrayHashMapUnmanaged(*Step, void), - rand: std.rand.Random, + rand: std.Random, ) !void { switch (s.state) { .precheck_started => { diff --git a/lib/compiler_rt/paritydi2_test.zig b/lib/compiler_rt/paritydi2_test.zig index fdcbe3ac68..998c8c5c92 100644 --- a/lib/compiler_rt/paritydi2_test.zig +++ b/lib/compiler_rt/paritydi2_test.zig @@ -26,7 +26,7 @@ test "paritydi2" { try test__paritydi2(@bitCast(@as(u64, 0xffffffff_fffffffe))); try test__paritydi2(@bitCast(@as(u64, 0xffffffff_ffffffff))); - const RndGen = std.rand.DefaultPrng; + const RndGen = std.Random.DefaultPrng; var rnd = RndGen.init(42); var i: u32 = 0; while (i < 10_000) : (i += 1) { diff --git a/lib/compiler_rt/paritysi2_test.zig b/lib/compiler_rt/paritysi2_test.zig index ec1820c4fd..31ca63183b 100644 --- a/lib/compiler_rt/paritysi2_test.zig +++ b/lib/compiler_rt/paritysi2_test.zig @@ -26,7 +26,7 @@ test "paritysi2" { try test__paritysi2(@bitCast(@as(u32, 0xfffffffe))); try test__paritysi2(@bitCast(@as(u32, 0xffffffff))); - const RndGen = std.rand.DefaultPrng; + const RndGen = std.Random.DefaultPrng; var rnd = RndGen.init(42); var i: u32 = 0; while (i < 10_000) : (i += 1) { diff --git a/lib/compiler_rt/parityti2_test.zig b/lib/compiler_rt/parityti2_test.zig index 587cc1890f..c579e0e17c 100644 --- a/lib/compiler_rt/parityti2_test.zig +++ b/lib/compiler_rt/parityti2_test.zig @@ -26,7 +26,7 @@ test "parityti2" { try test__parityti2(@bitCast(@as(u128, 0xffffffff_ffffffff_ffffffff_fffffffe))); try test__parityti2(@bitCast(@as(u128, 0xffffffff_ffffffff_ffffffff_ffffffff))); - const RndGen = std.rand.DefaultPrng; + const RndGen = std.Random.DefaultPrng; var rnd = RndGen.init(42); var i: u32 = 0; while (i < 10_000) : (i += 1) { diff --git a/lib/compiler_rt/popcountdi2_test.zig b/lib/compiler_rt/popcountdi2_test.zig index b3967c410b..02a9c370a6 100644 --- a/lib/compiler_rt/popcountdi2_test.zig +++ b/lib/compiler_rt/popcountdi2_test.zig @@ -25,7 +25,7 @@ test "popcountdi2" { try test__popcountdi2(@as(i64, @bitCast(@as(u64, 0xffffffff_fffffffe)))); try test__popcountdi2(@as(i64, @bitCast(@as(u64, 0xffffffff_ffffffff)))); - const RndGen = std.rand.DefaultPrng; + const RndGen = std.Random.DefaultPrng; var rnd = RndGen.init(42); var i: u32 = 0; while (i < 10_000) : (i += 1) { diff --git a/lib/compiler_rt/popcountsi2_test.zig b/lib/compiler_rt/popcountsi2_test.zig index bf30e069aa..4232bcaf7f 100644 --- a/lib/compiler_rt/popcountsi2_test.zig +++ b/lib/compiler_rt/popcountsi2_test.zig @@ -25,7 +25,7 @@ test "popcountsi2" { try test__popcountsi2(@as(i32, @bitCast(@as(u32, 0xfffffffe)))); try test__popcountsi2(@as(i32, @bitCast(@as(u32, 0xffffffff)))); - const RndGen = std.rand.DefaultPrng; + const RndGen = std.Random.DefaultPrng; var rnd = RndGen.init(42); var i: u32 = 0; while (i < 10_000) : (i += 1) { diff --git a/lib/compiler_rt/popcountti2_test.zig b/lib/compiler_rt/popcountti2_test.zig index 4d242a8328..611897bd0b 100644 --- a/lib/compiler_rt/popcountti2_test.zig +++ b/lib/compiler_rt/popcountti2_test.zig @@ -25,7 +25,7 @@ test "popcountti2" { try test__popcountti2(@as(i128, @bitCast(@as(u128, 0xffffffff_ffffffff_ffffffff_fffffffe)))); try test__popcountti2(@as(i128, @bitCast(@as(u128, 0xffffffff_ffffffff_ffffffff_ffffffff)))); - const RndGen = std.rand.DefaultPrng; + const RndGen = std.Random.DefaultPrng; var rnd = RndGen.init(42); var i: u32 = 0; while (i < 10_000) : (i += 1) { diff --git a/lib/compiler_rt/udivmodei4.zig b/lib/compiler_rt/udivmodei4.zig index 194f45a23d..ef248181fd 100644 --- a/lib/compiler_rt/udivmodei4.zig +++ b/lib/compiler_rt/udivmodei4.zig @@ -132,7 +132,7 @@ test "__udivei4/__umodei4" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; - const RndGen = std.rand.DefaultPrng; + const RndGen = std.Random.DefaultPrng; var rnd = RndGen.init(42); var i: usize = 10000; while (i > 0) : (i -= 1) { diff --git a/lib/std/Random.zig b/lib/std/Random.zig index 8f4ee0872c..140f24da81 100644 --- a/lib/std/Random.zig +++ b/lib/std/Random.zig @@ -380,7 +380,7 @@ pub fn shuffleWithIndex(r: Random, comptime T: type, buf: []T, comptime Index: t /// /// This is useful for selecting an item from a slice where weights are not equal. /// `T` must be a numeric type capable of holding the sum of `proportions`. -pub fn weightedIndex(r: std.rand.Random, comptime T: type, proportions: []const T) usize { +pub fn weightedIndex(r: Random, comptime T: type, proportions: []const T) usize { // This implementation works by summing the proportions and picking a // random point in [0, sum). We then loop over the proportions, // accumulating until our accumulator is greater than the random point. diff --git a/lib/std/Random/Ascon.zig b/lib/std/Random/Ascon.zig index 6a3cb13165..6464fbe2d1 100644 --- a/lib/std/Random/Ascon.zig +++ b/lib/std/Random/Ascon.zig @@ -10,7 +10,6 @@ const std = @import("std"); const mem = std.mem; -const Random = std.rand.Random; const Self = @This(); const Ascon = std.crypto.core.Ascon(.little); @@ -39,9 +38,9 @@ pub fn addEntropy(self: *Self, bytes: []const u8) void { self.state.permute(); } -/// Returns a `std.rand.Random` structure backed by the current RNG. -pub fn random(self: *Self) Random { - return Random.init(self, fill); +/// Returns a `std.Random` structure backed by the current RNG. +pub fn random(self: *Self) std.Random { + return std.Random.init(self, fill); } /// Fills the buffer with random bytes. diff --git a/lib/std/Random/ChaCha.zig b/lib/std/Random/ChaCha.zig index 75f62c9a47..5783ee4152 100644 --- a/lib/std/Random/ChaCha.zig +++ b/lib/std/Random/ChaCha.zig @@ -5,7 +5,6 @@ const std = @import("std"); const mem = std.mem; -const Random = std.rand.Random; const Self = @This(); const Cipher = std.crypto.stream.chacha.ChaCha8IETF; @@ -53,9 +52,9 @@ pub fn addEntropy(self: *Self, bytes: []const u8) void { self.refill(); } -/// Returns a `std.rand.Random` structure backed by the current RNG. -pub fn random(self: *Self) Random { - return Random.init(self, fill); +/// Returns a `std.Random` structure backed by the current RNG. +pub fn random(self: *Self) std.Random { + return std.Random.init(self, fill); } // Refills the buffer with random bytes, overwriting the previous key. diff --git a/lib/std/Random/Isaac64.zig b/lib/std/Random/Isaac64.zig index 8684ba8e22..a3dceabd5c 100644 --- a/lib/std/Random/Isaac64.zig +++ b/lib/std/Random/Isaac64.zig @@ -4,7 +4,6 @@ //! https://doc.rust-lang.org/rand/src/rand/prng/isaac64.rs.html const std = @import("std"); -const Random = std.rand.Random; const mem = std.mem; const Isaac64 = @This(); @@ -30,8 +29,8 @@ pub fn init(init_s: u64) Isaac64 { return isaac; } -pub fn random(self: *Isaac64) Random { - return Random.init(self, fill); +pub fn random(self: *Isaac64) std.Random { + return std.Random.init(self, fill); } fn step(self: *Isaac64, mix: u64, base: usize, comptime m1: usize, comptime m2: usize) void { diff --git a/lib/std/Random/Pcg.zig b/lib/std/Random/Pcg.zig index d7d233659f..1ff65f0f44 100644 --- a/lib/std/Random/Pcg.zig +++ b/lib/std/Random/Pcg.zig @@ -3,7 +3,6 @@ //! PRNG const std = @import("std"); -const Random = std.rand.Random; const Pcg = @This(); const default_multiplier = 6364136223846793005; @@ -21,8 +20,8 @@ pub fn init(init_s: u64) Pcg { return pcg; } -pub fn random(self: *Pcg) Random { - return Random.init(self, fill); +pub fn random(self: *Pcg) std.Random { + return std.Random.init(self, fill); } fn next(self: *Pcg) u32 { @@ -37,7 +36,7 @@ fn next(self: *Pcg) u32 { fn seed(self: *Pcg, init_s: u64) void { // Pcg requires 128-bits of seed. - var gen = std.rand.SplitMix64.init(init_s); + var gen = std.Random.SplitMix64.init(init_s); self.seedTwo(gen.next(), gen.next()); } diff --git a/lib/std/Random/RomuTrio.zig b/lib/std/Random/RomuTrio.zig index 4caf5f0ce8..9cc8cf13e1 100644 --- a/lib/std/Random/RomuTrio.zig +++ b/lib/std/Random/RomuTrio.zig @@ -3,7 +3,6 @@ // Beware: this PRNG is trivially predictable. While fast, it should *never* be used for cryptographic purposes. const std = @import("std"); -const Random = std.rand.Random; const math = std.math; const RomuTrio = @This(); @@ -17,8 +16,8 @@ pub fn init(init_s: u64) RomuTrio { return x; } -pub fn random(self: *RomuTrio) Random { - return Random.init(self, fill); +pub fn random(self: *RomuTrio) std.Random { + return std.Random.init(self, fill); } fn next(self: *RomuTrio) u64 { @@ -42,7 +41,7 @@ pub fn seedWithBuf(self: *RomuTrio, buf: [24]u8) void { pub fn seed(self: *RomuTrio, init_s: u64) void { // RomuTrio requires 192-bits of seed. - var gen = std.rand.SplitMix64.init(init_s); + var gen = std.Random.SplitMix64.init(init_s); self.x_state = gen.next(); self.y_state = gen.next(); diff --git a/lib/std/Random/Sfc64.zig b/lib/std/Random/Sfc64.zig index b4a8988e4d..004167952e 100644 --- a/lib/std/Random/Sfc64.zig +++ b/lib/std/Random/Sfc64.zig @@ -3,7 +3,6 @@ //! See http://pracrand.sourceforge.net/ const std = @import("std"); -const Random = std.rand.Random; const math = std.math; const Sfc64 = @This(); @@ -23,8 +22,8 @@ pub fn init(init_s: u64) Sfc64 { return x; } -pub fn random(self: *Sfc64) Random { - return Random.init(self, fill); +pub fn random(self: *Sfc64) std.Random { + return std.Random.init(self, fill); } fn next(self: *Sfc64) u64 { diff --git a/lib/std/Random/Xoroshiro128.zig b/lib/std/Random/Xoroshiro128.zig index 0272419ba2..6966a4fc5a 100644 --- a/lib/std/Random/Xoroshiro128.zig +++ b/lib/std/Random/Xoroshiro128.zig @@ -3,7 +3,6 @@ //! PRNG const std = @import("std"); -const Random = std.rand.Random; const math = std.math; const Xoroshiro128 = @This(); @@ -16,8 +15,8 @@ pub fn init(init_s: u64) Xoroshiro128 { return x; } -pub fn random(self: *Xoroshiro128) Random { - return Random.init(self, fill); +pub fn random(self: *Xoroshiro128) std.Random { + return std.Random.init(self, fill); } pub fn next(self: *Xoroshiro128) u64 { @@ -59,7 +58,7 @@ pub fn jump(self: *Xoroshiro128) void { pub fn seed(self: *Xoroshiro128, init_s: u64) void { // Xoroshiro requires 128-bits of seed. - var gen = std.rand.SplitMix64.init(init_s); + var gen = std.Random.SplitMix64.init(init_s); self.s[0] = gen.next(); self.s[1] = gen.next(); diff --git a/lib/std/Random/Xoshiro256.zig b/lib/std/Random/Xoshiro256.zig index 85ae669ecd..bf917885f6 100644 --- a/lib/std/Random/Xoshiro256.zig +++ b/lib/std/Random/Xoshiro256.zig @@ -3,7 +3,6 @@ //! PRNG const std = @import("std"); -const Random = std.rand.Random; const math = std.math; const Xoshiro256 = @This(); @@ -18,8 +17,8 @@ pub fn init(init_s: u64) Xoshiro256 { return x; } -pub fn random(self: *Xoshiro256) Random { - return Random.init(self, fill); +pub fn random(self: *Xoshiro256) std.Random { + return std.Random.init(self, fill); } pub fn next(self: *Xoshiro256) u64 { @@ -57,7 +56,7 @@ pub fn jump(self: *Xoshiro256) void { pub fn seed(self: *Xoshiro256, init_s: u64) void { // Xoshiro requires 256-bits of seed. - var gen = std.rand.SplitMix64.init(init_s); + var gen = std.Random.SplitMix64.init(init_s); self.s[0] = gen.next(); self.s[1] = gen.next(); diff --git a/lib/std/Random/benchmark.zig b/lib/std/Random/benchmark.zig index 530556517c..f3ea468181 100644 --- a/lib/std/Random/benchmark.zig +++ b/lib/std/Random/benchmark.zig @@ -4,7 +4,7 @@ const std = @import("std"); const builtin = @import("builtin"); const time = std.time; const Timer = time.Timer; -const rand = std.rand; +const Random = std.Random; const KiB = 1024; const MiB = 1024 * KiB; @@ -19,32 +19,32 @@ const Rng = struct { const prngs = [_]Rng{ Rng{ - .ty = rand.Isaac64, + .ty = Random.Isaac64, .name = "isaac64", .init_u64 = 0, }, Rng{ - .ty = rand.Pcg, + .ty = Random.Pcg, .name = "pcg", .init_u64 = 0, }, Rng{ - .ty = rand.RomuTrio, + .ty = Random.RomuTrio, .name = "romutrio", .init_u64 = 0, }, Rng{ - .ty = std.rand.Sfc64, + .ty = Random.Sfc64, .name = "sfc64", .init_u64 = 0, }, Rng{ - .ty = std.rand.Xoroshiro128, + .ty = Random.Xoroshiro128, .name = "xoroshiro128", .init_u64 = 0, }, Rng{ - .ty = std.rand.Xoshiro256, + .ty = Random.Xoshiro256, .name = "xoshiro256", .init_u64 = 0, }, @@ -52,12 +52,12 @@ const prngs = [_]Rng{ const csprngs = [_]Rng{ Rng{ - .ty = rand.Ascon, + .ty = Random.Ascon, .name = "ascon", .init_u8s = &[_]u8{0} ** 32, }, Rng{ - .ty = rand.ChaCha, + .ty = Random.ChaCha, .name = "chacha", .init_u8s = &[_]u8{0} ** 32, }, diff --git a/lib/std/Random/ziggurat.zig b/lib/std/Random/ziggurat.zig index 87045e4077..2bed6a065b 100644 --- a/lib/std/Random/ziggurat.zig +++ b/lib/std/Random/ziggurat.zig @@ -10,7 +10,7 @@ const std = @import("../std.zig"); const builtin = @import("builtin"); const math = std.math; -const Random = std.rand.Random; +const Random = std.Random; pub fn next_f64(random: Random, comptime tables: ZigTable) f64 { while (true) { @@ -127,7 +127,7 @@ pub fn norm_zero_case(random: Random, u: f64) f64 { } test "normal dist sanity" { - var prng = std.rand.DefaultPrng.init(0); + var prng = Random.DefaultPrng.init(0); const random = prng.random(); var i: usize = 0; @@ -156,7 +156,7 @@ pub fn exp_zero_case(random: Random, _: f64) f64 { } test "exp dist smoke test" { - var prng = std.rand.DefaultPrng.init(0); + var prng = Random.DefaultPrng.init(0); const random = prng.random(); var i: usize = 0; diff --git a/lib/std/Thread/RwLock.zig b/lib/std/Thread/RwLock.zig index a05d68df88..e0923c40ad 100644 --- a/lib/std/Thread/RwLock.zig +++ b/lib/std/Thread/RwLock.zig @@ -328,7 +328,7 @@ test "RwLock - concurrent access" { } fn writer(self: *Self, thread_idx: usize) !void { - var prng = std.rand.DefaultPrng.init(thread_idx); + var prng = std.Random.DefaultPrng.init(thread_idx); var rnd = prng.random(); while (true) { diff --git a/lib/std/crypto/benchmark.zig b/lib/std/crypto/benchmark.zig index 17f11382ca..ee08cdf8ab 100644 --- a/lib/std/crypto/benchmark.zig +++ b/lib/std/crypto/benchmark.zig @@ -10,7 +10,7 @@ const crypto = std.crypto; const KiB = 1024; const MiB = 1024 * KiB; -var prng = std.rand.DefaultPrng.init(0); +var prng = std.Random.DefaultPrng.init(0); const random = prng.random(); const Crypto = struct { diff --git a/lib/std/crypto/kyber_d00.zig b/lib/std/crypto/kyber_d00.zig index ad8e060765..00246bbf40 100644 --- a/lib/std/crypto/kyber_d00.zig +++ b/lib/std/crypto/kyber_d00.zig @@ -110,7 +110,7 @@ const assert = std.debug.assert; const crypto = std.crypto; const math = std.math; const mem = std.mem; -const RndGen = std.rand.DefaultPrng; +const RndGen = std.Random.DefaultPrng; const sha3 = crypto.hash.sha3; // Q is the parameter q ≡ 3329 = 2¹¹ + 2¹⁰ + 2⁸ + 1. diff --git a/lib/std/crypto/tlcsprng.zig b/lib/std/crypto/tlcsprng.zig index bbca32024e..973a0f8bb4 100644 --- a/lib/std/crypto/tlcsprng.zig +++ b/lib/std/crypto/tlcsprng.zig @@ -10,7 +10,7 @@ const os = std.os; /// We use this as a layer of indirection because global const pointers cannot /// point to thread-local variables. -pub const interface = std.rand.Random{ +pub const interface = std.Random{ .ptr = undefined, .fillFn = tlsCsprngFill, }; @@ -43,7 +43,7 @@ const maybe_have_wipe_on_fork = builtin.os.isAtLeast(.linux, .{ }) orelse true; const is_haiku = builtin.os.tag == .haiku; -const Rng = std.rand.DefaultCsprng; +const Rng = std.Random.DefaultCsprng; const Context = struct { init_state: enum(u8) { uninitialized = 0, initialized, failed }, diff --git a/lib/std/hash/benchmark.zig b/lib/std/hash/benchmark.zig index a56bd0b5a8..35e96a655b 100644 --- a/lib/std/hash/benchmark.zig +++ b/lib/std/hash/benchmark.zig @@ -10,7 +10,7 @@ const KiB = 1024; const MiB = 1024 * KiB; const GiB = 1024 * MiB; -var prng = std.rand.DefaultPrng.init(0); +var prng = std.Random.DefaultPrng.init(0); const random = prng.random(); const Hash = struct { diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig index ad84254792..83c5b7690f 100644 --- a/lib/std/hash_map.zig +++ b/lib/std/hash_map.zig @@ -1884,7 +1884,7 @@ test "std.hash_map put and remove loop in random order" { while (i < size) : (i += 1) { try keys.append(i); } - var prng = std.rand.DefaultPrng.init(0); + var prng = std.Random.DefaultPrng.init(0); const random = prng.random(); while (i < iterations) : (i += 1) { @@ -1916,7 +1916,7 @@ test "std.hash_map remove one million elements in random order" { keys.append(i) catch unreachable; } - var prng = std.rand.DefaultPrng.init(0); + var prng = std.Random.DefaultPrng.init(0); const random = prng.random(); random.shuffle(u32, keys.items); diff --git a/lib/std/heap/arena_allocator.zig b/lib/std/heap/arena_allocator.zig index 09f2e609f4..bde62ce8c2 100644 --- a/lib/std/heap/arena_allocator.zig +++ b/lib/std/heap/arena_allocator.zig @@ -250,7 +250,7 @@ test "ArenaAllocator (reset with preheating)" { var arena_allocator = ArenaAllocator.init(std.testing.allocator); defer arena_allocator.deinit(); // provides some variance in the allocated data - var rng_src = std.rand.DefaultPrng.init(19930913); + var rng_src = std.Random.DefaultPrng.init(19930913); const random = rng_src.random(); var rounds: usize = 25; while (rounds > 0) { diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig index 79ea020092..2f9464eef4 100644 --- a/lib/std/io/test.zig +++ b/lib/std/io/test.zig @@ -1,6 +1,6 @@ const std = @import("std"); const io = std.io; -const DefaultPrng = std.rand.DefaultPrng; +const DefaultPrng = std.Random.DefaultPrng; const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const expectError = std.testing.expectError; diff --git a/lib/std/math/big/rational.zig b/lib/std/math/big/rational.zig index 5529a6ef26..b095d005f0 100644 --- a/lib/std/math/big/rational.zig +++ b/lib/std/math/big/rational.zig @@ -594,7 +594,7 @@ test "big.rational toFloat" { test "big.rational set/to Float round-trip" { var a = try Rational.init(testing.allocator); defer a.deinit(); - var prng = std.rand.DefaultPrng.init(0x5EED); + var prng = std.Random.DefaultPrng.init(0x5EED); const random = prng.random(); var i: usize = 0; while (i < 512) : (i += 1) { diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 55c51d5959..feb41aedeb 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -4423,7 +4423,7 @@ test "read/write(Var)PackedInt" { const foreign_endian: Endian = if (native_endian == .big) .little else .big; const expect = std.testing.expect; - var prng = std.rand.DefaultPrng.init(1234); + var prng = std.Random.DefaultPrng.init(1234); const random = prng.random(); @setEvalBranchQuota(10_000); diff --git a/lib/std/priority_dequeue.zig b/lib/std/priority_dequeue.zig index dc3981b65e..1b4a82aac3 100644 --- a/lib/std/priority_dequeue.zig +++ b/lib/std/priority_dequeue.zig @@ -866,7 +866,7 @@ test "std.PriorityDequeue: shrinkAndFree" { } test "std.PriorityDequeue: fuzz testing min" { - var prng = std.rand.DefaultPrng.init(0x12345678); + var prng = std.Random.DefaultPrng.init(0x12345678); const random = prng.random(); const test_case_count = 100; @@ -878,7 +878,7 @@ test "std.PriorityDequeue: fuzz testing min" { } } -fn fuzzTestMin(rng: std.rand.Random, comptime queue_size: usize) !void { +fn fuzzTestMin(rng: std.Random, comptime queue_size: usize) !void { const allocator = testing.allocator; const items = try generateRandomSlice(allocator, rng, queue_size); @@ -895,7 +895,7 @@ fn fuzzTestMin(rng: std.rand.Random, comptime queue_size: usize) !void { } test "std.PriorityDequeue: fuzz testing max" { - var prng = std.rand.DefaultPrng.init(0x87654321); + var prng = std.Random.DefaultPrng.init(0x87654321); const random = prng.random(); const test_case_count = 100; @@ -907,7 +907,7 @@ test "std.PriorityDequeue: fuzz testing max" { } } -fn fuzzTestMax(rng: std.rand.Random, queue_size: usize) !void { +fn fuzzTestMax(rng: std.Random, queue_size: usize) !void { const allocator = testing.allocator; const items = try generateRandomSlice(allocator, rng, queue_size); @@ -924,7 +924,7 @@ fn fuzzTestMax(rng: std.rand.Random, queue_size: usize) !void { } test "std.PriorityDequeue: fuzz testing min and max" { - var prng = std.rand.DefaultPrng.init(0x87654321); + var prng = std.Random.DefaultPrng.init(0x87654321); const random = prng.random(); const test_case_count = 100; @@ -936,7 +936,7 @@ test "std.PriorityDequeue: fuzz testing min and max" { } } -fn fuzzTestMinMax(rng: std.rand.Random, queue_size: usize) !void { +fn fuzzTestMinMax(rng: std.Random, queue_size: usize) !void { const allocator = testing.allocator; const items = try generateRandomSlice(allocator, rng, queue_size); @@ -963,7 +963,7 @@ fn fuzzTestMinMax(rng: std.rand.Random, queue_size: usize) !void { } } -fn generateRandomSlice(allocator: std.mem.Allocator, rng: std.rand.Random, size: usize) ![]u32 { +fn generateRandomSlice(allocator: std.mem.Allocator, rng: std.Random, size: usize) ![]u32 { var array = std.ArrayList(u32).init(allocator); try array.ensureTotalCapacity(size); diff --git a/lib/std/sort.zig b/lib/std/sort.zig index 2781867a54..a697046ea6 100644 --- a/lib/std/sort.zig +++ b/lib/std/sort.zig @@ -379,7 +379,7 @@ test "sort with context in the middle of a slice" { } test "sort fuzz testing" { - var prng = std.rand.DefaultPrng.init(0x12345678); + var prng = std.Random.DefaultPrng.init(0x12345678); const random = prng.random(); const test_case_count = 10; diff --git a/lib/std/treap.zig b/lib/std/treap.zig index a555b49495..a7633d082a 100644 --- a/lib/std/treap.zig +++ b/lib/std/treap.zig @@ -18,7 +18,7 @@ pub fn Treap(comptime Key: type, comptime compareFn: anytype) type { /// A customized pseudo random number generator for the treap. /// This just helps reducing the memory size of the treap itself - /// as std.rand.DefaultPrng requires larger state (while producing better entropy for randomness to be fair). + /// as std.Random.DefaultPrng requires larger state (while producing better entropy for randomness to be fair). const Prng = struct { xorshift: usize = 0, @@ -305,7 +305,7 @@ pub fn Treap(comptime Key: type, comptime compareFn: anytype) type { // https://lemire.me/blog/2017/09/18/visiting-all-values-in-an-array-exactly-once-in-random-order/ fn SliceIterRandomOrder(comptime T: type) type { return struct { - rng: std.rand.Random, + rng: std.Random, slice: []T, index: usize = undefined, offset: usize = undefined, @@ -313,7 +313,7 @@ fn SliceIterRandomOrder(comptime T: type) type { const Self = @This(); - pub fn init(slice: []T, rng: std.rand.Random) Self { + pub fn init(slice: []T, rng: std.Random) Self { return Self{ .rng = rng, .slice = slice, @@ -353,7 +353,7 @@ test "std.Treap: insert, find, replace, remove" { var treap = TestTreap{}; var nodes: [10]TestNode = undefined; - var prng = std.rand.DefaultPrng.init(0xdeadbeef); + var prng = std.Random.DefaultPrng.init(0xdeadbeef); var iter = SliceIterRandomOrder(TestNode).init(&nodes, prng.random()); // insert check diff --git a/src/reduce.zig b/src/reduce.zig index a0b1bc8a18..027557bea5 100644 --- a/src/reduce.zig +++ b/src/reduce.zig @@ -136,7 +136,7 @@ pub fn main(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { var more_fixups: Ast.Fixups = .{}; defer more_fixups.deinit(gpa); - var rng = std.rand.DefaultPrng.init(seed); + var rng = std.Random.DefaultPrng.init(seed); // 1. Walk the AST of the source file looking for independent // reductions and collecting them all into an array list. @@ -274,7 +274,7 @@ pub fn main(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { return std.process.cleanExit(); } -fn sortTransformations(transformations: []Walk.Transformation, rng: std.rand.Random) void { +fn sortTransformations(transformations: []Walk.Transformation, rng: std.Random) void { rng.shuffle(Walk.Transformation, transformations); // Stable sort based on priority to keep randomness as the secondary sort. // TODO: introduce transformation priorities diff --git a/src/resinator/compile.zig b/src/resinator/compile.zig index 4de218da4f..0c71b02027 100644 --- a/src/resinator/compile.zig +++ b/src/resinator/compile.zig @@ -3356,7 +3356,7 @@ test "StringTable" { } break :ids buf; }; - var prng = std.rand.DefaultPrng.init(0); + var prng = std.Random.DefaultPrng.init(0); var random = prng.random(); random.shuffle(u16, &ids); From a9a5833f231f0dc323eb95a4f0e7bf5eb477a1c3 Mon Sep 17 00:00:00 2001 From: e4m2 Date: Thu, 8 Feb 2024 15:35:33 +0100 Subject: [PATCH 3/4] Update rand.zig source file name for CMake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c1ed1247de..b2c390f0d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -302,7 +302,7 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/lib/std/Progress.zig" "${CMAKE_SOURCE_DIR}/lib/std/pdb.zig" "${CMAKE_SOURCE_DIR}/lib/std/process.zig" - "${CMAKE_SOURCE_DIR}/lib/std/rand.zig" + "${CMAKE_SOURCE_DIR}/lib/std/Random.zig" "${CMAKE_SOURCE_DIR}/lib/std/sort.zig" "${CMAKE_SOURCE_DIR}/lib/compiler_rt.zig" "${CMAKE_SOURCE_DIR}/lib/compiler_rt/absv.zig" From 60639ec83d0ccb7a26a19ae64452b00141d48354 Mon Sep 17 00:00:00 2001 From: e4m2 Date: Thu, 8 Feb 2024 15:39:28 +0100 Subject: [PATCH 4/4] Fixup filename casing --- lib/std/Random.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/Random.zig b/lib/std/Random.zig index 140f24da81..681f70bc98 100644 --- a/lib/std/Random.zig +++ b/lib/std/Random.zig @@ -26,7 +26,7 @@ pub const Xoroshiro128 = @import("Random/Xoroshiro128.zig"); pub const Xoshiro256 = @import("Random/Xoshiro256.zig"); pub const Sfc64 = @import("Random/Sfc64.zig"); pub const RomuTrio = @import("Random/RomuTrio.zig"); -pub const SplitMix64 = @import("Random/Splitmix64.zig"); +pub const SplitMix64 = @import("Random/SplitMix64.zig"); pub const ziggurat = @import("Random/ziggurat.zig"); ptr: *anyopaque,