pub const CheckedArithmeticError = error { IntOverflow, }; pub fn Float(comptime bits: comptime_int) type { return @Type(.{.Float = .{.bits = bits}}); } pub fn Signed(comptime bits: comptime_int) type { return @Type(.{.Int = .{ .signedness = .signed, .bits = bits, }}); } pub fn Unsigned(comptime bits: comptime_int) type { return @Type(.{.Int = .{ .signedness = .unsigned, .bits = bits, }}); } pub const Vector2 = extern struct { x: f32, y: f32, pub const zero = Vector2{.x = 0, .y = 0}; }; pub fn checked_add(a: anytype, b: anytype) CheckedArithmeticError!@TypeOf(a + b) { const result = @addWithOverflow(a, b); if (result.@"1" != 0) return error.IntOverflow; return result.@"0"; } pub fn checked_mul(a: anytype, b: anytype) CheckedArithmeticError!@TypeOf(a * b) { const result = @mulWithOverflow(a, b); if (result.@"1" != 0) return error.IntOverflow; return result.@"0"; } pub fn checked_sub(a: anytype, b: anytype) CheckedArithmeticError!@TypeOf(a - b) { const result = @subWithOverflow(a, b); if (result.@"1" != 0) return error.IntOverflow; return result.@"0"; } pub fn clamp(comptime Scalar: type, value: Scalar, min_value: Scalar, max_value: Scalar) Scalar { return max(Scalar, min_value, min(Scalar, max_value, value)); } pub fn max(comptime Scalar: type, this: Scalar, that: Scalar) Scalar { return if (this > that) this else that; } pub fn max_int(comptime Int: type) Int { const info = @typeInfo(Int); const bit_count = info.Int.bits; if (bit_count == 0) return 0; return (1 << (bit_count - @boolToInt(info.Int.signedness == .signed))) - 1; } pub fn min(comptime Scalar: type, this: Scalar, that: Scalar) Scalar { return if (this < that) this else that; }