From bcf4a1391331e52e4a06528530316970ded75c74 Mon Sep 17 00:00:00 2001 From: antlilja Date: Mon, 17 Jul 2023 00:21:45 +0200 Subject: [PATCH] Remove `@fabs`, fabs and absCast/Int from std lib Replaces occurences of @fabs absCast and absInt with new @abs builtin. Also removes the std.math.fabs alias from math.zig. --- lib/compiler_rt/divc3.zig | 3 +- lib/compiler_rt/divxf3_test.zig | 6 +- lib/compiler_rt/float_from_int.zig | 2 +- lib/std/Build/Step/ConfigHeader.zig | 2 +- lib/std/dwarf/expressions.zig | 2 +- lib/std/fmt.zig | 2 +- lib/std/io/fixed_buffer_stream.zig | 2 +- lib/std/math.zig | 98 ++--------------------------- lib/std/math/asin.zig | 4 +- lib/std/math/atan.zig | 4 +- lib/std/math/atan2.zig | 4 +- lib/std/math/big/int.zig | 6 +- lib/std/math/complex/cosh.zig | 8 +-- lib/std/math/complex/sinh.zig | 8 +-- lib/std/math/complex/sqrt.zig | 10 +-- lib/std/math/complex/tanh.zig | 4 +- lib/std/math/pow.zig | 4 +- lib/std/meta.zig | 4 +- lib/std/rand/ziggurat.zig | 2 +- lib/std/zig/c_builtins.zig | 12 +++- lib/zig.h | 41 ++++++++++++ 21 files changed, 92 insertions(+), 136 deletions(-) diff --git a/lib/compiler_rt/divc3.zig b/lib/compiler_rt/divc3.zig index c4241c1483..92d2b39f66 100644 --- a/lib/compiler_rt/divc3.zig +++ b/lib/compiler_rt/divc3.zig @@ -3,7 +3,6 @@ const isNan = std.math.isNan; const isInf = std.math.isInf; const scalbn = std.math.scalbn; const ilogb = std.math.ilogb; -const fabs = std.math.fabs; const maxInt = std.math.maxInt; const minInt = std.math.minInt; const isFinite = std.math.isFinite; @@ -16,7 +15,7 @@ pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) { var d = d_in; // logbw used to prevent under/over-flow - const logbw = ilogb(@max(fabs(c), fabs(d))); + const logbw = ilogb(@max(@abs(c), @abs(d))); const logbw_finite = logbw != maxInt(i32) and logbw != minInt(i32); const ilogbw = if (logbw_finite) b: { c = scalbn(c, -logbw); diff --git a/lib/compiler_rt/divxf3_test.zig b/lib/compiler_rt/divxf3_test.zig index 98118602fd..0aec97b54d 100644 --- a/lib/compiler_rt/divxf3_test.zig +++ b/lib/compiler_rt/divxf3_test.zig @@ -30,9 +30,9 @@ fn test__divxf3(a: f80, b: f80) !void { const x_minus_eps: f80 = @bitCast((@as(u80, @bitCast(x)) - 1) | integerBit); // Make sure result is more accurate than the adjacent floats - const err_x = @fabs(@mulAdd(f80, x, b, -a)); - const err_x_plus_eps = @fabs(@mulAdd(f80, x_plus_eps, b, -a)); - const err_x_minus_eps = @fabs(@mulAdd(f80, x_minus_eps, b, -a)); + const err_x = @abs(@mulAdd(f80, x, b, -a)); + const err_x_plus_eps = @abs(@mulAdd(f80, x_plus_eps, b, -a)); + const err_x_minus_eps = @abs(@mulAdd(f80, x_minus_eps, b, -a)); try testing.expect(err_x_minus_eps > err_x); try testing.expect(err_x_plus_eps > err_x); diff --git a/lib/compiler_rt/float_from_int.zig b/lib/compiler_rt/float_from_int.zig index cb3fa67987..5ef511a4bf 100644 --- a/lib/compiler_rt/float_from_int.zig +++ b/lib/compiler_rt/float_from_int.zig @@ -18,7 +18,7 @@ pub fn floatFromInt(comptime T: type, x: anytype) T { const max_exp = exp_bias; // Sign - var abs_val = math.absCast(x); + var abs_val = if (@TypeOf(x) == comptime_int or @typeInfo(@TypeOf(x)).Int.signedness == .signed) @abs(x) else x; const sign_bit = if (x < 0) @as(uT, 1) << (float_bits - 1) else 0; var result: uT = sign_bit; diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig index 35e92ee04e..95386f45f0 100644 --- a/lib/std/Build/Step/ConfigHeader.zig +++ b/lib/std/Build/Step/ConfigHeader.zig @@ -539,7 +539,7 @@ fn replace_variables( .int => |i| { const buf = try std.fmt.allocPrint(allocator, "{s}{}{s}", .{ beginline, i, endline }); const isNegative = i < 0; - const digits = (if (0 < i) std.math.log10(std.math.absCast(i)) else 0) + 1; + const digits = (if (0 < i) std.math.log10(@abs(i)) else 0) + 1; last_index = start_index + @intFromBool(isNegative) + digits + 1; allocator.free(content_buf); diff --git a/lib/std/dwarf/expressions.zig b/lib/std/dwarf/expressions.zig index a57c9add90..f89edc08a1 100644 --- a/lib/std/dwarf/expressions.zig +++ b/lib/std/dwarf/expressions.zig @@ -520,7 +520,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type { if (self.stack.items.len == 0) return error.InvalidExpression; const value: isize = @bitCast(try self.stack.items[self.stack.items.len - 1].asIntegral()); self.stack.items[self.stack.items.len - 1] = .{ - .generic = std.math.absCast(value), + .generic = @abs(value), }; }, OP.@"and" => { diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 2f041aeb95..8a72047652 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -1413,7 +1413,7 @@ pub fn formatInt( const min_int_bits = comptime @max(value_info.bits, 8); const MinInt = std.meta.Int(.unsigned, min_int_bits); - const abs_value = math.absCast(int_value); + const abs_value = @abs(int_value); // The worst case in terms of space needed is base 2, plus 1 for the sign var buf: [1 + @max(@as(comptime_int, value_info.bits), 1)]u8 = undefined; diff --git a/lib/std/io/fixed_buffer_stream.zig b/lib/std/io/fixed_buffer_stream.zig index 27b978744c..f62ac415a4 100644 --- a/lib/std/io/fixed_buffer_stream.zig +++ b/lib/std/io/fixed_buffer_stream.zig @@ -81,7 +81,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type { pub fn seekBy(self: *Self, amt: i64) SeekError!void { if (amt < 0) { - const abs_amt = std.math.absCast(amt); + const abs_amt = @abs(amt); const abs_amt_usize = std.math.cast(usize, abs_amt) orelse std.math.maxInt(usize); if (abs_amt_usize > self.pos) { self.pos = 0; diff --git a/lib/std/math.zig b/lib/std/math.zig index 7e835059a3..f5ee7019cd 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -130,7 +130,7 @@ pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool { if (isNan(x) or isNan(y)) return false; - return @fabs(x - y) <= tolerance; + return @abs(x - y) <= tolerance; } /// Performs an approximate comparison of two floating point values `x` and `y`. @@ -158,7 +158,7 @@ pub fn approxEqRel(comptime T: type, x: T, y: T, tolerance: T) bool { if (isNan(x) or isNan(y)) return false; - return @fabs(x - y) <= @max(@fabs(x), @fabs(y)) * tolerance; + return @abs(x - y) <= @max(@abs(x), @abs(y)) * tolerance; } test "approxEqAbs and approxEqRel" { @@ -466,7 +466,7 @@ pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) !T { /// Shifts left. Overflowed bits are truncated. /// A negative shift amount results in a right shift. pub fn shl(comptime T: type, a: T, shift_amt: anytype) T { - const abs_shift_amt = absCast(shift_amt); + const abs_shift_amt = @abs(shift_amt); const casted_shift_amt = blk: { if (@typeInfo(T) == .Vector) { @@ -510,7 +510,7 @@ test "shl" { /// Shifts right. Overflowed bits are truncated. /// A negative shift amount results in a left shift. pub fn shr(comptime T: type, a: T, shift_amt: anytype) T { - const abs_shift_amt = absCast(shift_amt); + const abs_shift_amt = @abs(shift_amt); const casted_shift_amt = blk: { if (@typeInfo(T) == .Vector) { @@ -740,52 +740,6 @@ fn testOverflow() !void { try testing.expect((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000); } -/// Returns the absolute value of x, where x is a value of a signed integer type. -/// Does not convert and returns a value of a signed integer type. -/// Use `absCast` if you want to convert the result and get an unsigned type. -/// Use `@fabs` if you need the absolute value of a floating point value. -pub fn absInt(x: anytype) !@TypeOf(x) { - const T = @TypeOf(x); - return switch (@typeInfo(T)) { - .Int => |info| { - comptime assert(info.signedness == .signed); // must pass a signed integer to absInt - if (x == minInt(T)) { - return error.Overflow; - } else { - @setRuntimeSafety(false); - return if (x < 0) -x else x; - } - }, - .Vector => |vinfo| blk: { - switch (@typeInfo(vinfo.child)) { - .Int => |info| { - comptime assert(info.signedness == .signed); // must pass a signed integer to absInt - if (@reduce(.Or, x == @as(T, @splat(minInt(vinfo.child))))) { - return error.Overflow; - } - const zero: T = @splat(0); - break :blk @select(vinfo.child, x > zero, x, -x); - }, - else => @compileError("Expected vector of ints, found " ++ @typeName(T)), - } - }, - else => @compileError("Expected an int or vector, found " ++ @typeName(T)), - }; -} - -test "absInt" { - try testAbsInt(); - try comptime testAbsInt(); -} -fn testAbsInt() !void { - try testing.expect((absInt(@as(i32, -10)) catch unreachable) == 10); - try testing.expect((absInt(@as(i32, 10)) catch unreachable) == 10); - try testing.expectEqual(@Vector(3, i32){ 10, 10, 0 }, (absInt(@Vector(3, i32){ -10, 10, 0 }) catch unreachable)); - - try testing.expectError(error.Overflow, absInt(@as(i32, minInt(i32)))); - try testing.expectError(error.Overflow, absInt(@Vector(3, i32){ 10, -10, minInt(i32) })); -} - /// Divide numerator by denominator, rounding toward zero. Returns an /// error on overflow or when denominator is zero. pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T { @@ -968,50 +922,6 @@ fn testRem() !void { try testing.expectError(error.DivisionByZero, rem(f32, 10, 0)); } -/// Returns the absolute value of a floating point number. -/// Uses a dedicated hardware instruction when available. -/// This is the same as calling the builtin @fabs -pub inline fn fabs(value: anytype) @TypeOf(value) { - return @fabs(value); -} - -/// Returns the absolute value of the integer parameter. -/// Converts result type to unsigned if needed and returns a value of an unsigned integer type. -/// Use `absInt` if you want to keep your integer type signed. -pub fn absCast(x: anytype) switch (@typeInfo(@TypeOf(x))) { - .ComptimeInt => comptime_int, - .Int => |int_info| std.meta.Int(.unsigned, int_info.bits), - else => @compileError("absCast only accepts integers"), -} { - switch (@typeInfo(@TypeOf(x))) { - .ComptimeInt => { - if (x < 0) { - return -x; - } else { - return x; - } - }, - .Int => |int_info| { - if (int_info.signedness == .unsigned) return x; - const Uint = std.meta.Int(.unsigned, int_info.bits); - if (x < 0) { - return ~@as(Uint, @bitCast(x +% -1)); - } else { - return @as(Uint, @intCast(x)); - } - }, - else => unreachable, - } -} - -test "absCast" { - try testing.expectEqual(@as(u1, 1), absCast(@as(i1, -1))); - try testing.expectEqual(@as(u32, 999), absCast(@as(i32, -999))); - try testing.expectEqual(@as(u32, 999), absCast(@as(i32, 999))); - try testing.expectEqual(@as(u32, -minInt(i32)), absCast(@as(i32, minInt(i32)))); - try testing.expectEqual(999, absCast(-999)); -} - /// Returns the negation of the integer parameter. /// Result is a signed integer. pub fn negateCast(x: anytype) !std.meta.Int(.signed, @bitSizeOf(@TypeOf(x))) { diff --git a/lib/std/math/asin.zig b/lib/std/math/asin.zig index ac1d01ff55..dedd4d7e72 100644 --- a/lib/std/math/asin.zig +++ b/lib/std/math/asin.zig @@ -60,7 +60,7 @@ fn asin32(x: f32) f32 { } // 1 > |x| >= 0.5 - const z = (1 - @fabs(x)) * 0.5; + const z = (1 - @abs(x)) * 0.5; const s = @sqrt(z); const fx = pio2 - 2 * (s + s * r32(z)); @@ -119,7 +119,7 @@ fn asin64(x: f64) f64 { } // 1 > |x| >= 0.5 - const z = (1 - @fabs(x)) * 0.5; + const z = (1 - @abs(x)) * 0.5; const s = @sqrt(z); const r = r64(z); var fx: f64 = undefined; diff --git a/lib/std/math/atan.zig b/lib/std/math/atan.zig index 75be6ea746..2b57ceb074 100644 --- a/lib/std/math/atan.zig +++ b/lib/std/math/atan.zig @@ -73,7 +73,7 @@ fn atan32(x_: f32) f32 { } id = null; } else { - x = @fabs(x); + x = @abs(x); // |x| < 1.1875 if (ix < 0x3F980000) { // 7/16 <= |x| < 11/16 @@ -171,7 +171,7 @@ fn atan64(x_: f64) f64 { } id = null; } else { - x = @fabs(x); + x = @abs(x); // |x| < 1.1875 if (ix < 0x3FF30000) { // 7/16 <= |x| < 11/16 diff --git a/lib/std/math/atan2.zig b/lib/std/math/atan2.zig index 026c76b5b2..b3ed7b7bca 100644 --- a/lib/std/math/atan2.zig +++ b/lib/std/math/atan2.zig @@ -108,7 +108,7 @@ fn atan2_32(y: f32, x: f32) f32 { if ((m & 2) != 0 and iy + (26 << 23) < ix) { break :z 0.0; } else { - break :z math.atan(@fabs(y / x)); + break :z math.atan(@abs(y / x)); } }; @@ -198,7 +198,7 @@ fn atan2_64(y: f64, x: f64) f64 { if ((m & 2) != 0 and iy +% (64 << 20) < ix) { break :z 0.0; } else { - break :z math.atan(@fabs(y / x)); + break :z math.atan(@abs(y / x)); } }; diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index f6cd79a756..3e6d52e9f7 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -29,7 +29,7 @@ pub fn calcLimbLen(scalar: anytype) usize { return 1; } - const w_value = std.math.absCast(scalar); + const w_value = @abs(scalar); return @as(usize, @intCast(@divFloor(@as(Limb, @intCast(math.log2(w_value))), limb_bits) + 1)); } @@ -240,7 +240,7 @@ pub const Mutable = struct { switch (@typeInfo(T)) { .Int => |info| { - var w_value = std.math.absCast(value); + var w_value = @abs(value); if (info.bits <= limb_bits) { self.limbs[0] = w_value; @@ -255,7 +255,7 @@ pub const Mutable = struct { } }, .ComptimeInt => { - comptime var w_value = std.math.absCast(value); + comptime var w_value = @abs(value); if (w_value <= maxInt(Limb)) { self.limbs[0] = w_value; diff --git a/lib/std/math/complex/cosh.zig b/lib/std/math/complex/cosh.zig index a6650feab4..b83562601d 100644 --- a/lib/std/math/complex/cosh.zig +++ b/lib/std/math/complex/cosh.zig @@ -44,12 +44,12 @@ fn cosh32(z: Complex(f32)) Complex(f32) { // |x|>= 9, so cosh(x) ~= exp(|x|) if (ix < 0x42b17218) { // x < 88.7: exp(|x|) won't overflow - const h = @exp(@fabs(x)) * 0.5; + const h = @exp(@abs(x)) * 0.5; return Complex(f32).init(math.copysign(h, x) * @cos(y), h * @sin(y)); } // x < 192.7: scale to avoid overflow else if (ix < 0x4340b1e7) { - const v = Complex(f32).init(@fabs(x), y); + const v = Complex(f32).init(@abs(x), y); const r = ldexp_cexp(v, -1); return Complex(f32).init(r.re, r.im * math.copysign(@as(f32, 1.0), x)); } @@ -112,12 +112,12 @@ fn cosh64(z: Complex(f64)) Complex(f64) { // |x|>= 22, so cosh(x) ~= exp(|x|) if (ix < 0x40862e42) { // x < 710: exp(|x|) won't overflow - const h = @exp(@fabs(x)) * 0.5; + const h = @exp(@abs(x)) * 0.5; return Complex(f64).init(h * @cos(y), math.copysign(h, x) * @sin(y)); } // x < 1455: scale to avoid overflow else if (ix < 0x4096bbaa) { - const v = Complex(f64).init(@fabs(x), y); + const v = Complex(f64).init(@abs(x), y); const r = ldexp_cexp(v, -1); return Complex(f64).init(r.re, r.im * math.copysign(@as(f64, 1.0), x)); } diff --git a/lib/std/math/complex/sinh.zig b/lib/std/math/complex/sinh.zig index 24d55ab9ab..c5aad570f8 100644 --- a/lib/std/math/complex/sinh.zig +++ b/lib/std/math/complex/sinh.zig @@ -44,12 +44,12 @@ fn sinh32(z: Complex(f32)) Complex(f32) { // |x|>= 9, so cosh(x) ~= exp(|x|) if (ix < 0x42b17218) { // x < 88.7: exp(|x|) won't overflow - const h = @exp(@fabs(x)) * 0.5; + const h = @exp(@abs(x)) * 0.5; return Complex(f32).init(math.copysign(h, x) * @cos(y), h * @sin(y)); } // x < 192.7: scale to avoid overflow else if (ix < 0x4340b1e7) { - const v = Complex(f32).init(@fabs(x), y); + const v = Complex(f32).init(@abs(x), y); const r = ldexp_cexp(v, -1); return Complex(f32).init(r.re * math.copysign(@as(f32, 1.0), x), r.im); } @@ -111,12 +111,12 @@ fn sinh64(z: Complex(f64)) Complex(f64) { // |x|>= 22, so cosh(x) ~= exp(|x|) if (ix < 0x40862e42) { // x < 710: exp(|x|) won't overflow - const h = @exp(@fabs(x)) * 0.5; + const h = @exp(@abs(x)) * 0.5; return Complex(f64).init(math.copysign(h, x) * @cos(y), h * @sin(y)); } // x < 1455: scale to avoid overflow else if (ix < 0x4096bbaa) { - const v = Complex(f64).init(@fabs(x), y); + const v = Complex(f64).init(@abs(x), y); const r = ldexp_cexp(v, -1); return Complex(f64).init(r.re * math.copysign(@as(f64, 1.0), x), r.im); } diff --git a/lib/std/math/complex/sqrt.zig b/lib/std/math/complex/sqrt.zig index fe2e8e6531..5ecbd564f7 100644 --- a/lib/std/math/complex/sqrt.zig +++ b/lib/std/math/complex/sqrt.zig @@ -43,7 +43,7 @@ fn sqrt32(z: Complex(f32)) Complex(f32) { // sqrt(-inf + i nan) = nan +- inf i // sqrt(-inf + iy) = 0 + inf i if (math.signbit(x)) { - return Complex(f32).init(@fabs(x - y), math.copysign(x, y)); + return Complex(f32).init(@abs(x - y), math.copysign(x, y)); } else { return Complex(f32).init(x, math.copysign(y - y, y)); } @@ -64,7 +64,7 @@ fn sqrt32(z: Complex(f32)) Complex(f32) { } else { const t = @sqrt((-dx + math.hypot(f64, dx, dy)) * 0.5); return Complex(f32).init( - @as(f32, @floatCast(@fabs(y) / (2.0 * t))), + @as(f32, @floatCast(@abs(y) / (2.0 * t))), @as(f32, @floatCast(math.copysign(t, y))), ); } @@ -94,7 +94,7 @@ fn sqrt64(z: Complex(f64)) Complex(f64) { // sqrt(-inf + i nan) = nan +- inf i // sqrt(-inf + iy) = 0 + inf i if (math.signbit(x)) { - return Complex(f64).init(@fabs(x - y), math.copysign(x, y)); + return Complex(f64).init(@abs(x - y), math.copysign(x, y)); } else { return Complex(f64).init(x, math.copysign(y - y, y)); } @@ -104,7 +104,7 @@ fn sqrt64(z: Complex(f64)) Complex(f64) { // scale to avoid overflow var scale = false; - if (@fabs(x) >= threshold or @fabs(y) >= threshold) { + if (@abs(x) >= threshold or @abs(y) >= threshold) { x *= 0.25; y *= 0.25; scale = true; @@ -116,7 +116,7 @@ fn sqrt64(z: Complex(f64)) Complex(f64) { result = Complex(f64).init(t, y / (2.0 * t)); } else { const t = @sqrt((-x + math.hypot(f64, x, y)) * 0.5); - result = Complex(f64).init(@fabs(y) / (2.0 * t), math.copysign(t, y)); + result = Complex(f64).init(@abs(y) / (2.0 * t), math.copysign(t, y)); } if (scale) { diff --git a/lib/std/math/complex/tanh.zig b/lib/std/math/complex/tanh.zig index 076fcd195f..65074f28e1 100644 --- a/lib/std/math/complex/tanh.zig +++ b/lib/std/math/complex/tanh.zig @@ -44,7 +44,7 @@ fn tanh32(z: Complex(f32)) Complex(f32) { // x >= 11 if (ix >= 0x41300000) { - const exp_mx = @exp(-@fabs(x)); + const exp_mx = @exp(-@abs(x)); return Complex(f32).init(math.copysign(@as(f32, 1.0), x), 4 * @sin(y) * @cos(y) * exp_mx * exp_mx); } @@ -87,7 +87,7 @@ fn tanh64(z: Complex(f64)) Complex(f64) { // x >= 22 if (ix >= 0x40360000) { - const exp_mx = @exp(-@fabs(x)); + const exp_mx = @exp(-@abs(x)); return Complex(f64).init(math.copysign(@as(f64, 1.0), x), 4 * @sin(y) * @cos(y) * exp_mx * exp_mx); } diff --git a/lib/std/math/pow.zig b/lib/std/math/pow.zig index 927a4d68f4..b095ff1df7 100644 --- a/lib/std/math/pow.zig +++ b/lib/std/math/pow.zig @@ -82,7 +82,7 @@ pub fn pow(comptime T: type, x: T, y: T) T { } // pow(x, +inf) = +0 for |x| < 1 // pow(x, -inf) = +0 for |x| > 1 - else if ((@fabs(x) < 1) == math.isPositiveInf(y)) { + else if ((@abs(x) < 1) == math.isPositiveInf(y)) { return 0; } // pow(x, -inf) = +inf for |x| < 1 @@ -115,7 +115,7 @@ pub fn pow(comptime T: type, x: T, y: T) T { return 1 / @sqrt(x); } - const r1 = math.modf(@fabs(y)); + const r1 = math.modf(@abs(y)); var yi = r1.ipart; var yf = r1.fpart; diff --git a/lib/std/meta.zig b/lib/std/meta.zig index c8ef19c017..d65d53f8f6 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -1104,6 +1104,6 @@ pub fn isError(error_union: anytype) bool { } test "isError" { - try std.testing.expect(isError(math.absInt(@as(i8, -128)))); - try std.testing.expect(!isError(math.absInt(@as(i8, -127)))); + try std.testing.expect(isError(math.divTrunc(u8, 5, 0))); + try std.testing.expect(!isError(math.divTrunc(u8, 5, 5))); } diff --git a/lib/std/rand/ziggurat.zig b/lib/std/rand/ziggurat.zig index 09d695b88d..64417c1f3f 100644 --- a/lib/std/rand/ziggurat.zig +++ b/lib/std/rand/ziggurat.zig @@ -33,7 +33,7 @@ pub fn next_f64(random: Random, comptime tables: ZigTable) f64 { }; const x = u * tables.x[i]; - const test_x = if (tables.is_symmetric) @fabs(x) else x; + const test_x = if (tables.is_symmetric) @abs(x) else x; // equivalent to |u| < tables.x[i+1] / tables.x[i] (or u < tables.x[i+1] / tables.x[i]) if (test_x < tables.x[i + 1]) { diff --git a/lib/std/zig/c_builtins.zig b/lib/std/zig/c_builtins.zig index 33336543fa..e2b4c4302b 100644 --- a/lib/std/zig/c_builtins.zig +++ b/lib/std/zig/c_builtins.zig @@ -88,13 +88,19 @@ pub inline fn __builtin_log10f(val: f32) f32 { // Standard C Library bug: The absolute value of the most negative integer remains negative. pub inline fn __builtin_abs(val: c_int) c_int { - return std.math.absInt(val) catch std.math.minInt(c_int); + return if (val == std.math.minInt(c_int)) val else @intCast(@abs(val)); +} +pub inline fn __builtin_labs(val: c_long) c_long { + return if (val == std.math.minInt(c_long)) val else @intCast(@abs(val)); +} +pub inline fn __builtin_llabs(val: c_longlong) c_longlong { + return if (val == std.math.minInt(c_longlong)) val else @intCast(@abs(val)); } pub inline fn __builtin_fabs(val: f64) f64 { - return @fabs(val); + return @abs(val); } pub inline fn __builtin_fabsf(val: f32) f32 { - return @fabs(val); + return @abs(val); } pub inline fn __builtin_floor(val: f64) f64 { diff --git a/lib/zig.h b/lib/zig.h index 5ac70d2a24..233c2961cb 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -946,6 +946,24 @@ typedef unsigned long zig_Builtin64; typedef unsigned long long zig_Builtin64; #endif +#define zig_builtin8_rev(name, val) __builtin_##name(val) + +#define zig_builtin16_rev(name, val) __builtin_##name(val) + +#if INT_MIN <= INT32_MIN +#define zig_builtin32_rev(name, val) __builtin_##name(val) +#elif LONG_MIN <= INT32_MIN +#define zig_builtin32_rev(name, val) __builtin_l##name(val) +#endif + +#if INT_MIN <= INT64_MIN +#define zig_builtin64_rev(name, val) __builtin_##name(val) +#elif LONG_MIN <= INT64_MIN +#define zig_builtin64_rev(name, val) __builtin_l##name(val) +#elif LLONG_MIN <= INT64_MIN +#define zig_builtin64_rev(name, val) __builtin_ll##name(val) +#endif + static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) { return zig_wrap_u8(val >> (8 - bits), bits); } @@ -1141,6 +1159,24 @@ zig_builtin_clz(16) zig_builtin_clz(32) zig_builtin_clz(64) +#if zig_has_builtin(abs) || defined(zig_gnuc) +#define zig_builtin_abs(w) \ + static inline int##w##_t zig_abs_i##w(int##w##_t val) { \ + return zig_builtin##w##_rev(abs, val); \ + } +#else +#define zig_builtin_abs(w) \ + static inline int##w##_t zig_abs_i##w(int##w##_t val) { \ + if (val == INT##w##_MIN) return val; \ + int##w##_t tmp = val >> (w - 1); \ + return (val ^ tmp) - tmp; \ + } +#endif +zig_builtin_abs(8) +zig_builtin_abs(16) +zig_builtin_abs(32) +zig_builtin_abs(64) + /* ======================== 128-bit Integer Support ========================= */ #if !defined(zig_has_int128) @@ -1466,6 +1502,11 @@ static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); } +static inline zig_u128 zig_abs_i128(zig_i128 val) { + zig_i128 tmp = zig_shr_i128(val, 127); + return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp)); +} + #if zig_has_int128 static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {