mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
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.
This commit is contained in:
parent
1c02e58fc0
commit
bcf4a13913
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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" => {
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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))) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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)));
|
||||
}
|
||||
|
||||
@ -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]) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
41
lib/zig.h
41
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) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user