You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.2 KiB
123 lines
3.2 KiB
const std = @import("std");
|
|
|
|
pub const Range = struct {
|
|
min: f32 = 0,
|
|
max: f32 = 1,
|
|
|
|
inline fn l(self: *const @This(), r: f32) f32 {
|
|
return lerp(self.min, self.max, r);
|
|
}
|
|
|
|
pub inline fn get(self: *const @This(), rand: std.rand.Random) f32 {
|
|
const r = rand.float(f32);
|
|
return self.l(r);
|
|
}
|
|
|
|
pub inline fn int(
|
|
self: *const @This(),
|
|
comptime Type: type,
|
|
rand: std.rand.Random,
|
|
) Type {
|
|
return @as(Type, @intFromFloat(self.get(rand)));
|
|
}
|
|
|
|
pub inline fn norm(self: *const @This(), rand: std.rand.Random) f32 {
|
|
return normRange(rand, self.min, self.max);
|
|
}
|
|
};
|
|
|
|
pub inline fn lerp(min: f32, max: f32, r: f32) f32 {
|
|
return @mulAdd(f32, (max - min), r, min);
|
|
}
|
|
|
|
pub inline fn lerpInt(comptime Type: type, min: f32, max: f32, r: f32) Type {
|
|
return @as(f32, @intFromFloat(lerp(min, max, r)));
|
|
}
|
|
|
|
pub inline fn norm(rand: std.rand.Random, median: f32, dev: f32) f32 {
|
|
const r = rand.floatNorm(f32) * dev + median;
|
|
return std.math.clamp(r, 0, 1);
|
|
}
|
|
|
|
pub inline fn oneNorm(rand: std.rand.Random) f32 {
|
|
return norm(rand, 0.5, 0.2);
|
|
}
|
|
|
|
pub inline fn biasNorm(rand: std.rand.Random, bias: f32) f32 {
|
|
return norm(rand, (0.5 + bias) / 2, 0.2);
|
|
}
|
|
|
|
pub inline fn normRange(rand: std.rand.Random, min: f32, max: f32) f32 {
|
|
const r = oneNorm(rand);
|
|
return lerp(min, max, r);
|
|
}
|
|
|
|
pub inline fn randomItem(
|
|
comptime Type: type,
|
|
rand: std.rand.Random,
|
|
slices: []const []const Type,
|
|
) Type {
|
|
var limit: usize = 0;
|
|
for (slices) |slice| {
|
|
limit += slice.len;
|
|
}
|
|
|
|
var index = rand.uintLessThan(usize, limit);
|
|
for (slices) |slice| {
|
|
if (index >= slice.len) {
|
|
index -= slice.len;
|
|
} else {
|
|
return slice[index];
|
|
}
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
pub fn readFileAlloc(alloc: std.mem.Allocator, path: []const u8) ![]const u8 {
|
|
const max_size = 1024 * 1024 * 12;
|
|
return try std.fs.cwd().readFileAlloc(alloc, path, max_size);
|
|
}
|
|
|
|
pub fn free(allocator: std.mem.Allocator, obj: anytype) void {
|
|
const Type = @TypeOf(obj);
|
|
|
|
switch (@typeInfo(Type)) {
|
|
.Array => for (obj) |item| {
|
|
free(allocator, item);
|
|
},
|
|
.Struct => |info| inline for (info.fields) |field| {
|
|
free(allocator, @field(obj, field.name));
|
|
},
|
|
.Union => |info| if (info.tag_type) |Tag| {
|
|
inline for (info.fields) |field| {
|
|
if (obj == @field(Tag, field.name)) {
|
|
free(allocator, @field(obj, field.name));
|
|
}
|
|
}
|
|
},
|
|
.Pointer => |info| switch (info.size) {
|
|
.Slice => {
|
|
if (Type == []const u8) {
|
|
allocator.free(obj);
|
|
} else {
|
|
for (obj) |item| {
|
|
free(allocator, item);
|
|
}
|
|
allocator.free(obj);
|
|
}
|
|
},
|
|
.One => {
|
|
free(allocator, obj.*);
|
|
allocator.destroy(obj);
|
|
},
|
|
else => {},
|
|
},
|
|
.Optional => {
|
|
if (obj) |v| {
|
|
free(allocator, v);
|
|
}
|
|
},
|
|
else => {},
|
|
}
|
|
}
|
|
|