authorgravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2023-07-17 00:21:45+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-27 11:24:28-07:00
logbcf4a1391331e52e4a06528530316970ded75c74
tree484d6472f552780d6482b8457e56b29f9a06379d
parent1c02e58fc06aa3e429f963e600e126611df3626e

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.

21 files changed, 92 insertions(+), 136 deletions(-)

lib/compiler_rt/divc3.zig+1-2
...@@ -3,7 +3,6 @@ const isNan = std.math.isNan;...@@ -3,7 +3,6 @@ const isNan = std.math.isNan;
3const isInf = std.math.isInf;3const isInf = std.math.isInf;
4const scalbn = std.math.scalbn;4const scalbn = std.math.scalbn;
5const ilogb = std.math.ilogb;5const ilogb = std.math.ilogb;
6const fabs = std.math.fabs;
7const maxInt = std.math.maxInt;6const maxInt = std.math.maxInt;
8const minInt = std.math.minInt;7const minInt = std.math.minInt;
9const isFinite = std.math.isFinite;8const 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) {...@@ -16,7 +15,7 @@ pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) {
16 var d = d_in;15 var d = d_in;
1716
18 // logbw used to prevent under/over-flow17 // logbw used to prevent under/over-flow
19 const logbw = ilogb(@max(fabs(c), fabs(d)));18 const logbw = ilogb(@max(@abs(c), @abs(d)));
20 const logbw_finite = logbw != maxInt(i32) and logbw != minInt(i32);19 const logbw_finite = logbw != maxInt(i32) and logbw != minInt(i32);
21 const ilogbw = if (logbw_finite) b: {20 const ilogbw = if (logbw_finite) b: {
22 c = scalbn(c, -logbw);21 c = scalbn(c, -logbw);
lib/compiler_rt/divxf3_test.zig+3-3
...@@ -30,9 +30,9 @@ fn test__divxf3(a: f80, b: f80) !void {...@@ -30,9 +30,9 @@ fn test__divxf3(a: f80, b: f80) !void {
30 const x_minus_eps: f80 = @bitCast((@as(u80, @bitCast(x)) - 1) | integerBit);30 const x_minus_eps: f80 = @bitCast((@as(u80, @bitCast(x)) - 1) | integerBit);
3131
32 // Make sure result is more accurate than the adjacent floats32 // Make sure result is more accurate than the adjacent floats
33 const err_x = @fabs(@mulAdd(f80, x, b, -a));33 const err_x = @abs(@mulAdd(f80, x, b, -a));
34 const err_x_plus_eps = @fabs(@mulAdd(f80, x_plus_eps, b, -a));34 const err_x_plus_eps = @abs(@mulAdd(f80, x_plus_eps, b, -a));
35 const err_x_minus_eps = @fabs(@mulAdd(f80, x_minus_eps, b, -a));35 const err_x_minus_eps = @abs(@mulAdd(f80, x_minus_eps, b, -a));
3636
37 try testing.expect(err_x_minus_eps > err_x);37 try testing.expect(err_x_minus_eps > err_x);
38 try testing.expect(err_x_plus_eps > err_x);38 try testing.expect(err_x_plus_eps > err_x);
lib/compiler_rt/float_from_int.zig+1-1
...@@ -18,7 +18,7 @@ pub fn floatFromInt(comptime T: type, x: anytype) T {...@@ -18,7 +18,7 @@ pub fn floatFromInt(comptime T: type, x: anytype) T {
18 const max_exp = exp_bias;18 const max_exp = exp_bias;
1919
20 // Sign20 // Sign
21 var abs_val = math.absCast(x);21 var abs_val = if (@TypeOf(x) == comptime_int or @typeInfo(@TypeOf(x)).Int.signedness == .signed) @abs(x) else x;
22 const sign_bit = if (x < 0) @as(uT, 1) << (float_bits - 1) else 0;22 const sign_bit = if (x < 0) @as(uT, 1) << (float_bits - 1) else 0;
23 var result: uT = sign_bit;23 var result: uT = sign_bit;
2424
lib/std/Build/Step/ConfigHeader.zig+1-1
...@@ -539,7 +539,7 @@ fn replace_variables(...@@ -539,7 +539,7 @@ fn replace_variables(
539 .int => |i| {539 .int => |i| {
540 const buf = try std.fmt.allocPrint(allocator, "{s}{}{s}", .{ beginline, i, endline });540 const buf = try std.fmt.allocPrint(allocator, "{s}{}{s}", .{ beginline, i, endline });
541 const isNegative = i < 0;541 const isNegative = i < 0;
542 const digits = (if (0 < i) std.math.log10(std.math.absCast(i)) else 0) + 1;542 const digits = (if (0 < i) std.math.log10(@abs(i)) else 0) + 1;
543 last_index = start_index + @intFromBool(isNegative) + digits + 1;543 last_index = start_index + @intFromBool(isNegative) + digits + 1;
544544
545 allocator.free(content_buf);545 allocator.free(content_buf);
lib/std/dwarf/expressions.zig+1-1
...@@ -520,7 +520,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {...@@ -520,7 +520,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
520 if (self.stack.items.len == 0) return error.InvalidExpression;520 if (self.stack.items.len == 0) return error.InvalidExpression;
521 const value: isize = @bitCast(try self.stack.items[self.stack.items.len - 1].asIntegral());521 const value: isize = @bitCast(try self.stack.items[self.stack.items.len - 1].asIntegral());
522 self.stack.items[self.stack.items.len - 1] = .{522 self.stack.items[self.stack.items.len - 1] = .{
523 .generic = std.math.absCast(value),523 .generic = @abs(value),
524 };524 };
525 },525 },
526 OP.@"and" => {526 OP.@"and" => {
lib/std/fmt.zig+1-1
...@@ -1413,7 +1413,7 @@ pub fn formatInt(...@@ -1413,7 +1413,7 @@ pub fn formatInt(
1413 const min_int_bits = comptime @max(value_info.bits, 8);1413 const min_int_bits = comptime @max(value_info.bits, 8);
1414 const MinInt = std.meta.Int(.unsigned, min_int_bits);1414 const MinInt = std.meta.Int(.unsigned, min_int_bits);
14151415
1416 const abs_value = math.absCast(int_value);1416 const abs_value = @abs(int_value);
1417 // The worst case in terms of space needed is base 2, plus 1 for the sign1417 // The worst case in terms of space needed is base 2, plus 1 for the sign
1418 var buf: [1 + @max(@as(comptime_int, value_info.bits), 1)]u8 = undefined;1418 var buf: [1 + @max(@as(comptime_int, value_info.bits), 1)]u8 = undefined;
14191419
lib/std/io/fixed_buffer_stream.zig+1-1
...@@ -81,7 +81,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {...@@ -81,7 +81,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
8181
82 pub fn seekBy(self: *Self, amt: i64) SeekError!void {82 pub fn seekBy(self: *Self, amt: i64) SeekError!void {
83 if (amt < 0) {83 if (amt < 0) {
84 const abs_amt = std.math.absCast(amt);84 const abs_amt = @abs(amt);
85 const abs_amt_usize = std.math.cast(usize, abs_amt) orelse std.math.maxInt(usize);85 const abs_amt_usize = std.math.cast(usize, abs_amt) orelse std.math.maxInt(usize);
86 if (abs_amt_usize > self.pos) {86 if (abs_amt_usize > self.pos) {
87 self.pos = 0;87 self.pos = 0;
lib/std/math.zig+4-94
...@@ -130,7 +130,7 @@ pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool {...@@ -130,7 +130,7 @@ pub fn approxEqAbs(comptime T: type, x: T, y: T, tolerance: T) bool {
130 if (isNan(x) or isNan(y))130 if (isNan(x) or isNan(y))
131 return false;131 return false;
132132
133 return @fabs(x - y) <= tolerance;133 return @abs(x - y) <= tolerance;
134}134}
135135
136/// Performs an approximate comparison of two floating point values `x` and `y`.136/// 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 {...@@ -158,7 +158,7 @@ pub fn approxEqRel(comptime T: type, x: T, y: T, tolerance: T) bool {
158 if (isNan(x) or isNan(y))158 if (isNan(x) or isNan(y))
159 return false;159 return false;
160160
161 return @fabs(x - y) <= @max(@fabs(x), @fabs(y)) * tolerance;161 return @abs(x - y) <= @max(@abs(x), @abs(y)) * tolerance;
162}162}
163163
164test "approxEqAbs and approxEqRel" {164test "approxEqAbs and approxEqRel" {
...@@ -466,7 +466,7 @@ pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) !T {...@@ -466,7 +466,7 @@ pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) !T {
466/// Shifts left. Overflowed bits are truncated.466/// Shifts left. Overflowed bits are truncated.
467/// A negative shift amount results in a right shift.467/// A negative shift amount results in a right shift.
468pub fn shl(comptime T: type, a: T, shift_amt: anytype) T {468pub fn shl(comptime T: type, a: T, shift_amt: anytype) T {
469 const abs_shift_amt = absCast(shift_amt);469 const abs_shift_amt = @abs(shift_amt);
470470
471 const casted_shift_amt = blk: {471 const casted_shift_amt = blk: {
472 if (@typeInfo(T) == .Vector) {472 if (@typeInfo(T) == .Vector) {
...@@ -510,7 +510,7 @@ test "shl" {...@@ -510,7 +510,7 @@ test "shl" {
510/// Shifts right. Overflowed bits are truncated.510/// Shifts right. Overflowed bits are truncated.
511/// A negative shift amount results in a left shift.511/// A negative shift amount results in a left shift.
512pub fn shr(comptime T: type, a: T, shift_amt: anytype) T {512pub fn shr(comptime T: type, a: T, shift_amt: anytype) T {
513 const abs_shift_amt = absCast(shift_amt);513 const abs_shift_amt = @abs(shift_amt);
514514
515 const casted_shift_amt = blk: {515 const casted_shift_amt = blk: {
516 if (@typeInfo(T) == .Vector) {516 if (@typeInfo(T) == .Vector) {
...@@ -740,52 +740,6 @@ fn testOverflow() !void {...@@ -740,52 +740,6 @@ fn testOverflow() !void {
740 try testing.expect((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000);740 try testing.expect((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000);
741}741}
742742
743/// Returns the absolute value of x, where x is a value of a signed integer type.
744/// Does not convert and returns a value of a signed integer type.
745/// Use `absCast` if you want to convert the result and get an unsigned type.
746/// Use `@fabs` if you need the absolute value of a floating point value.
747pub fn absInt(x: anytype) !@TypeOf(x) {
748 const T = @TypeOf(x);
749 return switch (@typeInfo(T)) {
750 .Int => |info| {
751 comptime assert(info.signedness == .signed); // must pass a signed integer to absInt
752 if (x == minInt(T)) {
753 return error.Overflow;
754 } else {
755 @setRuntimeSafety(false);
756 return if (x < 0) -x else x;
757 }
758 },
759 .Vector => |vinfo| blk: {
760 switch (@typeInfo(vinfo.child)) {
761 .Int => |info| {
762 comptime assert(info.signedness == .signed); // must pass a signed integer to absInt
763 if (@reduce(.Or, x == @as(T, @splat(minInt(vinfo.child))))) {
764 return error.Overflow;
765 }
766 const zero: T = @splat(0);
767 break :blk @select(vinfo.child, x > zero, x, -x);
768 },
769 else => @compileError("Expected vector of ints, found " ++ @typeName(T)),
770 }
771 },
772 else => @compileError("Expected an int or vector, found " ++ @typeName(T)),
773 };
774}
775
776test "absInt" {
777 try testAbsInt();
778 try comptime testAbsInt();
779}
780fn testAbsInt() !void {
781 try testing.expect((absInt(@as(i32, -10)) catch unreachable) == 10);
782 try testing.expect((absInt(@as(i32, 10)) catch unreachable) == 10);
783 try testing.expectEqual(@Vector(3, i32){ 10, 10, 0 }, (absInt(@Vector(3, i32){ -10, 10, 0 }) catch unreachable));
784
785 try testing.expectError(error.Overflow, absInt(@as(i32, minInt(i32))));
786 try testing.expectError(error.Overflow, absInt(@Vector(3, i32){ 10, -10, minInt(i32) }));
787}
788
789/// Divide numerator by denominator, rounding toward zero. Returns an743/// Divide numerator by denominator, rounding toward zero. Returns an
790/// error on overflow or when denominator is zero.744/// error on overflow or when denominator is zero.
791pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T {745pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T {
...@@ -968,50 +922,6 @@ fn testRem() !void {...@@ -968,50 +922,6 @@ fn testRem() !void {
968 try testing.expectError(error.DivisionByZero, rem(f32, 10, 0));922 try testing.expectError(error.DivisionByZero, rem(f32, 10, 0));
969}923}
970924
971/// Returns the absolute value of a floating point number.
972/// Uses a dedicated hardware instruction when available.
973/// This is the same as calling the builtin @fabs
974pub inline fn fabs(value: anytype) @TypeOf(value) {
975 return @fabs(value);
976}
977
978/// Returns the absolute value of the integer parameter.
979/// Converts result type to unsigned if needed and returns a value of an unsigned integer type.
980/// Use `absInt` if you want to keep your integer type signed.
981pub fn absCast(x: anytype) switch (@typeInfo(@TypeOf(x))) {
982 .ComptimeInt => comptime_int,
983 .Int => |int_info| std.meta.Int(.unsigned, int_info.bits),
984 else => @compileError("absCast only accepts integers"),
985} {
986 switch (@typeInfo(@TypeOf(x))) {
987 .ComptimeInt => {
988 if (x < 0) {
989 return -x;
990 } else {
991 return x;
992 }
993 },
994 .Int => |int_info| {
995 if (int_info.signedness == .unsigned) return x;
996 const Uint = std.meta.Int(.unsigned, int_info.bits);
997 if (x < 0) {
998 return ~@as(Uint, @bitCast(x +% -1));
999 } else {
1000 return @as(Uint, @intCast(x));
1001 }
1002 },
1003 else => unreachable,
1004 }
1005}
1006
1007test "absCast" {
1008 try testing.expectEqual(@as(u1, 1), absCast(@as(i1, -1)));
1009 try testing.expectEqual(@as(u32, 999), absCast(@as(i32, -999)));
1010 try testing.expectEqual(@as(u32, 999), absCast(@as(i32, 999)));
1011 try testing.expectEqual(@as(u32, -minInt(i32)), absCast(@as(i32, minInt(i32))));
1012 try testing.expectEqual(999, absCast(-999));
1013}
1014
1015/// Returns the negation of the integer parameter.925/// Returns the negation of the integer parameter.
1016/// Result is a signed integer.926/// Result is a signed integer.
1017pub fn negateCast(x: anytype) !std.meta.Int(.signed, @bitSizeOf(@TypeOf(x))) {927pub fn negateCast(x: anytype) !std.meta.Int(.signed, @bitSizeOf(@TypeOf(x))) {
lib/std/math/asin.zig+2-2
...@@ -60,7 +60,7 @@ fn asin32(x: f32) f32 {...@@ -60,7 +60,7 @@ fn asin32(x: f32) f32 {
60 }60 }
6161
62 // 1 > |x| >= 0.562 // 1 > |x| >= 0.5
63 const z = (1 - @fabs(x)) * 0.5;63 const z = (1 - @abs(x)) * 0.5;
64 const s = @sqrt(z);64 const s = @sqrt(z);
65 const fx = pio2 - 2 * (s + s * r32(z));65 const fx = pio2 - 2 * (s + s * r32(z));
6666
...@@ -119,7 +119,7 @@ fn asin64(x: f64) f64 {...@@ -119,7 +119,7 @@ fn asin64(x: f64) f64 {
119 }119 }
120120
121 // 1 > |x| >= 0.5121 // 1 > |x| >= 0.5
122 const z = (1 - @fabs(x)) * 0.5;122 const z = (1 - @abs(x)) * 0.5;
123 const s = @sqrt(z);123 const s = @sqrt(z);
124 const r = r64(z);124 const r = r64(z);
125 var fx: f64 = undefined;125 var fx: f64 = undefined;
lib/std/math/atan.zig+2-2
...@@ -73,7 +73,7 @@ fn atan32(x_: f32) f32 {...@@ -73,7 +73,7 @@ fn atan32(x_: f32) f32 {
73 }73 }
74 id = null;74 id = null;
75 } else {75 } else {
76 x = @fabs(x);76 x = @abs(x);
77 // |x| < 1.187577 // |x| < 1.1875
78 if (ix < 0x3F980000) {78 if (ix < 0x3F980000) {
79 // 7/16 <= |x| < 11/1679 // 7/16 <= |x| < 11/16
...@@ -171,7 +171,7 @@ fn atan64(x_: f64) f64 {...@@ -171,7 +171,7 @@ fn atan64(x_: f64) f64 {
171 }171 }
172 id = null;172 id = null;
173 } else {173 } else {
174 x = @fabs(x);174 x = @abs(x);
175 // |x| < 1.1875175 // |x| < 1.1875
176 if (ix < 0x3FF30000) {176 if (ix < 0x3FF30000) {
177 // 7/16 <= |x| < 11/16177 // 7/16 <= |x| < 11/16
lib/std/math/atan2.zig+2-2
...@@ -108,7 +108,7 @@ fn atan2_32(y: f32, x: f32) f32 {...@@ -108,7 +108,7 @@ fn atan2_32(y: f32, x: f32) f32 {
108 if ((m & 2) != 0 and iy + (26 << 23) < ix) {108 if ((m & 2) != 0 and iy + (26 << 23) < ix) {
109 break :z 0.0;109 break :z 0.0;
110 } else {110 } else {
111 break :z math.atan(@fabs(y / x));111 break :z math.atan(@abs(y / x));
112 }112 }
113 };113 };
114114
...@@ -198,7 +198,7 @@ fn atan2_64(y: f64, x: f64) f64 {...@@ -198,7 +198,7 @@ fn atan2_64(y: f64, x: f64) f64 {
198 if ((m & 2) != 0 and iy +% (64 << 20) < ix) {198 if ((m & 2) != 0 and iy +% (64 << 20) < ix) {
199 break :z 0.0;199 break :z 0.0;
200 } else {200 } else {
201 break :z math.atan(@fabs(y / x));201 break :z math.atan(@abs(y / x));
202 }202 }
203 };203 };
204204
lib/std/math/big/int.zig+3-3
...@@ -29,7 +29,7 @@ pub fn calcLimbLen(scalar: anytype) usize {...@@ -29,7 +29,7 @@ pub fn calcLimbLen(scalar: anytype) usize {
29 return 1;29 return 1;
30 }30 }
3131
32 const w_value = std.math.absCast(scalar);32 const w_value = @abs(scalar);
33 return @as(usize, @intCast(@divFloor(@as(Limb, @intCast(math.log2(w_value))), limb_bits) + 1));33 return @as(usize, @intCast(@divFloor(@as(Limb, @intCast(math.log2(w_value))), limb_bits) + 1));
34}34}
3535
...@@ -240,7 +240,7 @@ pub const Mutable = struct {...@@ -240,7 +240,7 @@ pub const Mutable = struct {
240240
241 switch (@typeInfo(T)) {241 switch (@typeInfo(T)) {
242 .Int => |info| {242 .Int => |info| {
243 var w_value = std.math.absCast(value);243 var w_value = @abs(value);
244244
245 if (info.bits <= limb_bits) {245 if (info.bits <= limb_bits) {
246 self.limbs[0] = w_value;246 self.limbs[0] = w_value;
...@@ -255,7 +255,7 @@ pub const Mutable = struct {...@@ -255,7 +255,7 @@ pub const Mutable = struct {
255 }255 }
256 },256 },
257 .ComptimeInt => {257 .ComptimeInt => {
258 comptime var w_value = std.math.absCast(value);258 comptime var w_value = @abs(value);
259259
260 if (w_value <= maxInt(Limb)) {260 if (w_value <= maxInt(Limb)) {
261 self.limbs[0] = w_value;261 self.limbs[0] = w_value;
lib/std/math/complex/cosh.zig+4-4
...@@ -44,12 +44,12 @@ fn cosh32(z: Complex(f32)) Complex(f32) {...@@ -44,12 +44,12 @@ fn cosh32(z: Complex(f32)) Complex(f32) {
44 // |x|>= 9, so cosh(x) ~= exp(|x|)44 // |x|>= 9, so cosh(x) ~= exp(|x|)
45 if (ix < 0x42b17218) {45 if (ix < 0x42b17218) {
46 // x < 88.7: exp(|x|) won't overflow46 // x < 88.7: exp(|x|) won't overflow
47 const h = @exp(@fabs(x)) * 0.5;47 const h = @exp(@abs(x)) * 0.5;
48 return Complex(f32).init(math.copysign(h, x) * @cos(y), h * @sin(y));48 return Complex(f32).init(math.copysign(h, x) * @cos(y), h * @sin(y));
49 }49 }
50 // x < 192.7: scale to avoid overflow50 // x < 192.7: scale to avoid overflow
51 else if (ix < 0x4340b1e7) {51 else if (ix < 0x4340b1e7) {
52 const v = Complex(f32).init(@fabs(x), y);52 const v = Complex(f32).init(@abs(x), y);
53 const r = ldexp_cexp(v, -1);53 const r = ldexp_cexp(v, -1);
54 return Complex(f32).init(r.re, r.im * math.copysign(@as(f32, 1.0), x));54 return Complex(f32).init(r.re, r.im * math.copysign(@as(f32, 1.0), x));
55 }55 }
...@@ -112,12 +112,12 @@ fn cosh64(z: Complex(f64)) Complex(f64) {...@@ -112,12 +112,12 @@ fn cosh64(z: Complex(f64)) Complex(f64) {
112 // |x|>= 22, so cosh(x) ~= exp(|x|)112 // |x|>= 22, so cosh(x) ~= exp(|x|)
113 if (ix < 0x40862e42) {113 if (ix < 0x40862e42) {
114 // x < 710: exp(|x|) won't overflow114 // x < 710: exp(|x|) won't overflow
115 const h = @exp(@fabs(x)) * 0.5;115 const h = @exp(@abs(x)) * 0.5;
116 return Complex(f64).init(h * @cos(y), math.copysign(h, x) * @sin(y));116 return Complex(f64).init(h * @cos(y), math.copysign(h, x) * @sin(y));
117 }117 }
118 // x < 1455: scale to avoid overflow118 // x < 1455: scale to avoid overflow
119 else if (ix < 0x4096bbaa) {119 else if (ix < 0x4096bbaa) {
120 const v = Complex(f64).init(@fabs(x), y);120 const v = Complex(f64).init(@abs(x), y);
121 const r = ldexp_cexp(v, -1);121 const r = ldexp_cexp(v, -1);
122 return Complex(f64).init(r.re, r.im * math.copysign(@as(f64, 1.0), x));122 return Complex(f64).init(r.re, r.im * math.copysign(@as(f64, 1.0), x));
123 }123 }
lib/std/math/complex/sinh.zig+4-4
...@@ -44,12 +44,12 @@ fn sinh32(z: Complex(f32)) Complex(f32) {...@@ -44,12 +44,12 @@ fn sinh32(z: Complex(f32)) Complex(f32) {
44 // |x|>= 9, so cosh(x) ~= exp(|x|)44 // |x|>= 9, so cosh(x) ~= exp(|x|)
45 if (ix < 0x42b17218) {45 if (ix < 0x42b17218) {
46 // x < 88.7: exp(|x|) won't overflow46 // x < 88.7: exp(|x|) won't overflow
47 const h = @exp(@fabs(x)) * 0.5;47 const h = @exp(@abs(x)) * 0.5;
48 return Complex(f32).init(math.copysign(h, x) * @cos(y), h * @sin(y));48 return Complex(f32).init(math.copysign(h, x) * @cos(y), h * @sin(y));
49 }49 }
50 // x < 192.7: scale to avoid overflow50 // x < 192.7: scale to avoid overflow
51 else if (ix < 0x4340b1e7) {51 else if (ix < 0x4340b1e7) {
52 const v = Complex(f32).init(@fabs(x), y);52 const v = Complex(f32).init(@abs(x), y);
53 const r = ldexp_cexp(v, -1);53 const r = ldexp_cexp(v, -1);
54 return Complex(f32).init(r.re * math.copysign(@as(f32, 1.0), x), r.im);54 return Complex(f32).init(r.re * math.copysign(@as(f32, 1.0), x), r.im);
55 }55 }
...@@ -111,12 +111,12 @@ fn sinh64(z: Complex(f64)) Complex(f64) {...@@ -111,12 +111,12 @@ fn sinh64(z: Complex(f64)) Complex(f64) {
111 // |x|>= 22, so cosh(x) ~= exp(|x|)111 // |x|>= 22, so cosh(x) ~= exp(|x|)
112 if (ix < 0x40862e42) {112 if (ix < 0x40862e42) {
113 // x < 710: exp(|x|) won't overflow113 // x < 710: exp(|x|) won't overflow
114 const h = @exp(@fabs(x)) * 0.5;114 const h = @exp(@abs(x)) * 0.5;
115 return Complex(f64).init(math.copysign(h, x) * @cos(y), h * @sin(y));115 return Complex(f64).init(math.copysign(h, x) * @cos(y), h * @sin(y));
116 }116 }
117 // x < 1455: scale to avoid overflow117 // x < 1455: scale to avoid overflow
118 else if (ix < 0x4096bbaa) {118 else if (ix < 0x4096bbaa) {
119 const v = Complex(f64).init(@fabs(x), y);119 const v = Complex(f64).init(@abs(x), y);
120 const r = ldexp_cexp(v, -1);120 const r = ldexp_cexp(v, -1);
121 return Complex(f64).init(r.re * math.copysign(@as(f64, 1.0), x), r.im);121 return Complex(f64).init(r.re * math.copysign(@as(f64, 1.0), x), r.im);
122 }122 }
lib/std/math/complex/sqrt.zig+5-5
...@@ -43,7 +43,7 @@ fn sqrt32(z: Complex(f32)) Complex(f32) {...@@ -43,7 +43,7 @@ fn sqrt32(z: Complex(f32)) Complex(f32) {
43 // sqrt(-inf + i nan) = nan +- inf i43 // sqrt(-inf + i nan) = nan +- inf i
44 // sqrt(-inf + iy) = 0 + inf i44 // sqrt(-inf + iy) = 0 + inf i
45 if (math.signbit(x)) {45 if (math.signbit(x)) {
46 return Complex(f32).init(@fabs(x - y), math.copysign(x, y));46 return Complex(f32).init(@abs(x - y), math.copysign(x, y));
47 } else {47 } else {
48 return Complex(f32).init(x, math.copysign(y - y, y));48 return Complex(f32).init(x, math.copysign(y - y, y));
49 }49 }
...@@ -64,7 +64,7 @@ fn sqrt32(z: Complex(f32)) Complex(f32) {...@@ -64,7 +64,7 @@ fn sqrt32(z: Complex(f32)) Complex(f32) {
64 } else {64 } else {
65 const t = @sqrt((-dx + math.hypot(f64, dx, dy)) * 0.5);65 const t = @sqrt((-dx + math.hypot(f64, dx, dy)) * 0.5);
66 return Complex(f32).init(66 return Complex(f32).init(
67 @as(f32, @floatCast(@fabs(y) / (2.0 * t))),67 @as(f32, @floatCast(@abs(y) / (2.0 * t))),
68 @as(f32, @floatCast(math.copysign(t, y))),68 @as(f32, @floatCast(math.copysign(t, y))),
69 );69 );
70 }70 }
...@@ -94,7 +94,7 @@ fn sqrt64(z: Complex(f64)) Complex(f64) {...@@ -94,7 +94,7 @@ fn sqrt64(z: Complex(f64)) Complex(f64) {
94 // sqrt(-inf + i nan) = nan +- inf i94 // sqrt(-inf + i nan) = nan +- inf i
95 // sqrt(-inf + iy) = 0 + inf i95 // sqrt(-inf + iy) = 0 + inf i
96 if (math.signbit(x)) {96 if (math.signbit(x)) {
97 return Complex(f64).init(@fabs(x - y), math.copysign(x, y));97 return Complex(f64).init(@abs(x - y), math.copysign(x, y));
98 } else {98 } else {
99 return Complex(f64).init(x, math.copysign(y - y, y));99 return Complex(f64).init(x, math.copysign(y - y, y));
100 }100 }
...@@ -104,7 +104,7 @@ fn sqrt64(z: Complex(f64)) Complex(f64) {...@@ -104,7 +104,7 @@ fn sqrt64(z: Complex(f64)) Complex(f64) {
104104
105 // scale to avoid overflow105 // scale to avoid overflow
106 var scale = false;106 var scale = false;
107 if (@fabs(x) >= threshold or @fabs(y) >= threshold) {107 if (@abs(x) >= threshold or @abs(y) >= threshold) {
108 x *= 0.25;108 x *= 0.25;
109 y *= 0.25;109 y *= 0.25;
110 scale = true;110 scale = true;
...@@ -116,7 +116,7 @@ fn sqrt64(z: Complex(f64)) Complex(f64) {...@@ -116,7 +116,7 @@ fn sqrt64(z: Complex(f64)) Complex(f64) {
116 result = Complex(f64).init(t, y / (2.0 * t));116 result = Complex(f64).init(t, y / (2.0 * t));
117 } else {117 } else {
118 const t = @sqrt((-x + math.hypot(f64, x, y)) * 0.5);118 const t = @sqrt((-x + math.hypot(f64, x, y)) * 0.5);
119 result = Complex(f64).init(@fabs(y) / (2.0 * t), math.copysign(t, y));119 result = Complex(f64).init(@abs(y) / (2.0 * t), math.copysign(t, y));
120 }120 }
121121
122 if (scale) {122 if (scale) {
lib/std/math/complex/tanh.zig+2-2
...@@ -44,7 +44,7 @@ fn tanh32(z: Complex(f32)) Complex(f32) {...@@ -44,7 +44,7 @@ fn tanh32(z: Complex(f32)) Complex(f32) {
4444
45 // x >= 1145 // x >= 11
46 if (ix >= 0x41300000) {46 if (ix >= 0x41300000) {
47 const exp_mx = @exp(-@fabs(x));47 const exp_mx = @exp(-@abs(x));
48 return Complex(f32).init(math.copysign(@as(f32, 1.0), x), 4 * @sin(y) * @cos(y) * exp_mx * exp_mx);48 return Complex(f32).init(math.copysign(@as(f32, 1.0), x), 4 * @sin(y) * @cos(y) * exp_mx * exp_mx);
49 }49 }
5050
...@@ -87,7 +87,7 @@ fn tanh64(z: Complex(f64)) Complex(f64) {...@@ -87,7 +87,7 @@ fn tanh64(z: Complex(f64)) Complex(f64) {
8787
88 // x >= 2288 // x >= 22
89 if (ix >= 0x40360000) {89 if (ix >= 0x40360000) {
90 const exp_mx = @exp(-@fabs(x));90 const exp_mx = @exp(-@abs(x));
91 return Complex(f64).init(math.copysign(@as(f64, 1.0), x), 4 * @sin(y) * @cos(y) * exp_mx * exp_mx);91 return Complex(f64).init(math.copysign(@as(f64, 1.0), x), 4 * @sin(y) * @cos(y) * exp_mx * exp_mx);
92 }92 }
9393
lib/std/math/pow.zig+2-2
...@@ -82,7 +82,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {...@@ -82,7 +82,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {
82 }82 }
83 // pow(x, +inf) = +0 for |x| < 183 // pow(x, +inf) = +0 for |x| < 1
84 // pow(x, -inf) = +0 for |x| > 184 // pow(x, -inf) = +0 for |x| > 1
85 else if ((@fabs(x) < 1) == math.isPositiveInf(y)) {85 else if ((@abs(x) < 1) == math.isPositiveInf(y)) {
86 return 0;86 return 0;
87 }87 }
88 // pow(x, -inf) = +inf for |x| < 188 // pow(x, -inf) = +inf for |x| < 1
...@@ -115,7 +115,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {...@@ -115,7 +115,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {
115 return 1 / @sqrt(x);115 return 1 / @sqrt(x);
116 }116 }
117117
118 const r1 = math.modf(@fabs(y));118 const r1 = math.modf(@abs(y));
119 var yi = r1.ipart;119 var yi = r1.ipart;
120 var yf = r1.fpart;120 var yf = r1.fpart;
121121
lib/std/meta.zig+2-2
...@@ -1104,6 +1104,6 @@ pub fn isError(error_union: anytype) bool {...@@ -1104,6 +1104,6 @@ pub fn isError(error_union: anytype) bool {
1104}1104}
11051105
1106test "isError" {1106test "isError" {
1107 try std.testing.expect(isError(math.absInt(@as(i8, -128))));1107 try std.testing.expect(isError(math.divTrunc(u8, 5, 0)));
1108 try std.testing.expect(!isError(math.absInt(@as(i8, -127))));1108 try std.testing.expect(!isError(math.divTrunc(u8, 5, 5)));
1109}1109}
lib/std/rand/ziggurat.zig+1-1
...@@ -33,7 +33,7 @@ pub fn next_f64(random: Random, comptime tables: ZigTable) f64 {...@@ -33,7 +33,7 @@ pub fn next_f64(random: Random, comptime tables: ZigTable) f64 {
33 };33 };
3434
35 const x = u * tables.x[i];35 const x = u * tables.x[i];
36 const test_x = if (tables.is_symmetric) @fabs(x) else x;36 const test_x = if (tables.is_symmetric) @abs(x) else x;
3737
38 // equivalent to |u| < tables.x[i+1] / tables.x[i] (or u < tables.x[i+1] / tables.x[i])38 // equivalent to |u| < tables.x[i+1] / tables.x[i] (or u < tables.x[i+1] / tables.x[i])
39 if (test_x < tables.x[i + 1]) {39 if (test_x < tables.x[i + 1]) {
lib/std/zig/c_builtins.zig+9-3
...@@ -88,13 +88,19 @@ pub inline fn __builtin_log10f(val: f32) f32 {...@@ -88,13 +88,19 @@ pub inline fn __builtin_log10f(val: f32) f32 {
8888
89// Standard C Library bug: The absolute value of the most negative integer remains negative.89// Standard C Library bug: The absolute value of the most negative integer remains negative.
90pub inline fn __builtin_abs(val: c_int) c_int {90pub inline fn __builtin_abs(val: c_int) c_int {
91 return std.math.absInt(val) catch std.math.minInt(c_int);91 return if (val == std.math.minInt(c_int)) val else @intCast(@abs(val));
92}
93pub inline fn __builtin_labs(val: c_long) c_long {
94 return if (val == std.math.minInt(c_long)) val else @intCast(@abs(val));
95}
96pub inline fn __builtin_llabs(val: c_longlong) c_longlong {
97 return if (val == std.math.minInt(c_longlong)) val else @intCast(@abs(val));
92}98}
93pub inline fn __builtin_fabs(val: f64) f64 {99pub inline fn __builtin_fabs(val: f64) f64 {
94 return @fabs(val);100 return @abs(val);
95}101}
96pub inline fn __builtin_fabsf(val: f32) f32 {102pub inline fn __builtin_fabsf(val: f32) f32 {
97 return @fabs(val);103 return @abs(val);
98}104}
99105
100pub inline fn __builtin_floor(val: f64) f64 {106pub inline fn __builtin_floor(val: f64) f64 {
lib/zig.h+41
...@@ -946,6 +946,24 @@ typedef unsigned long zig_Builtin64;...@@ -946,6 +946,24 @@ typedef unsigned long zig_Builtin64;
946typedef unsigned long long zig_Builtin64;946typedef unsigned long long zig_Builtin64;
947#endif947#endif
948948
949#define zig_builtin8_rev(name, val) __builtin_##name(val)
950
951#define zig_builtin16_rev(name, val) __builtin_##name(val)
952
953#if INT_MIN <= INT32_MIN
954#define zig_builtin32_rev(name, val) __builtin_##name(val)
955#elif LONG_MIN <= INT32_MIN
956#define zig_builtin32_rev(name, val) __builtin_l##name(val)
957#endif
958
959#if INT_MIN <= INT64_MIN
960#define zig_builtin64_rev(name, val) __builtin_##name(val)
961#elif LONG_MIN <= INT64_MIN
962#define zig_builtin64_rev(name, val) __builtin_l##name(val)
963#elif LLONG_MIN <= INT64_MIN
964#define zig_builtin64_rev(name, val) __builtin_ll##name(val)
965#endif
966
949static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) {967static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) {
950 return zig_wrap_u8(val >> (8 - bits), bits);968 return zig_wrap_u8(val >> (8 - bits), bits);
951}969}
...@@ -1141,6 +1159,24 @@ zig_builtin_clz(16)...@@ -1141,6 +1159,24 @@ zig_builtin_clz(16)
1141zig_builtin_clz(32)1159zig_builtin_clz(32)
1142zig_builtin_clz(64)1160zig_builtin_clz(64)
11431161
1162#if zig_has_builtin(abs) || defined(zig_gnuc)
1163#define zig_builtin_abs(w) \
1164 static inline int##w##_t zig_abs_i##w(int##w##_t val) { \
1165 return zig_builtin##w##_rev(abs, val); \
1166 }
1167#else
1168#define zig_builtin_abs(w) \
1169 static inline int##w##_t zig_abs_i##w(int##w##_t val) { \
1170 if (val == INT##w##_MIN) return val; \
1171 int##w##_t tmp = val >> (w - 1); \
1172 return (val ^ tmp) - tmp; \
1173 }
1174#endif
1175zig_builtin_abs(8)
1176zig_builtin_abs(16)
1177zig_builtin_abs(32)
1178zig_builtin_abs(64)
1179
1144/* ======================== 128-bit Integer Support ========================= */1180/* ======================== 128-bit Integer Support ========================= */
11451181
1146#if !defined(zig_has_int128)1182#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) {...@@ -1466,6 +1502,11 @@ static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
1466 return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);1502 return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
1467}1503}
14681504
1505static inline zig_u128 zig_abs_i128(zig_i128 val) {
1506 zig_i128 tmp = zig_shr_i128(val, 127);
1507 return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp));
1508}
1509
1469#if zig_has_int1281510#if zig_has_int128
14701511
1471static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {1512static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {