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;
33const isInf = std.math.isInf;
44const scalbn = std.math.scalbn;
55const ilogb = std.math.ilogb;
6const fabs = std.math.fabs;
76const maxInt = std.math.maxInt;
87const minInt = std.math.minInt;
98const 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) {
1615 var d = d_in;
1716
1817 // 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)));
2019 const logbw_finite = logbw != maxInt(i32) and logbw != minInt(i32);
2120 const ilogbw = if (logbw_finite) b: {
2221 c = scalbn(c, -logbw);
lib/compiler_rt/divxf3_test.zig+3-3
......@@ -30,9 +30,9 @@ fn test__divxf3(a: f80, b: f80) !void {
3030 const x_minus_eps: f80 = @bitCast((@as(u80, @bitCast(x)) - 1) | integerBit);
3131
3232 // Make sure result is more accurate than the adjacent floats
33 const err_x = @fabs(@mulAdd(f80, x, b, -a));
34 const err_x_plus_eps = @fabs(@mulAdd(f80, x_plus_eps, b, -a));
35 const err_x_minus_eps = @fabs(@mulAdd(f80, x_minus_eps, b, -a));
33 const err_x = @abs(@mulAdd(f80, x, b, -a));
34 const err_x_plus_eps = @abs(@mulAdd(f80, x_plus_eps, b, -a));
35 const err_x_minus_eps = @abs(@mulAdd(f80, x_minus_eps, b, -a));
3636
3737 try testing.expect(err_x_minus_eps > err_x);
3838 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 {
1818 const max_exp = exp_bias;
1919
2020 // 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;
2222 const sign_bit = if (x < 0) @as(uT, 1) << (float_bits - 1) else 0;
2323 var result: uT = sign_bit;
2424
lib/std/Build/Step/ConfigHeader.zig+1-1
......@@ -539,7 +539,7 @@ fn replace_variables(
539539 .int => |i| {
540540 const buf = try std.fmt.allocPrint(allocator, "{s}{}{s}", .{ beginline, i, endline });
541541 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;
543543 last_index = start_index + @intFromBool(isNegative) + digits + 1;
544544
545545 allocator.free(content_buf);
lib/std/dwarf/expressions.zig+1-1
......@@ -520,7 +520,7 @@ pub fn StackMachine(comptime options: ExpressionOptions) type {
520520 if (self.stack.items.len == 0) return error.InvalidExpression;
521521 const value: isize = @bitCast(try self.stack.items[self.stack.items.len - 1].asIntegral());
522522 self.stack.items[self.stack.items.len - 1] = .{
523 .generic = std.math.absCast(value),
523 .generic = @abs(value),
524524 };
525525 },
526526 OP.@"and" => {
lib/std/fmt.zig+1-1
......@@ -1413,7 +1413,7 @@ pub fn formatInt(
14131413 const min_int_bits = comptime @max(value_info.bits, 8);
14141414 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);
14171417 // The worst case in terms of space needed is base 2, plus 1 for the sign
14181418 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 {
8181
8282 pub fn seekBy(self: *Self, amt: i64) SeekError!void {
8383 if (amt < 0) {
84 const abs_amt = std.math.absCast(amt);
84 const abs_amt = @abs(amt);
8585 const abs_amt_usize = std.math.cast(usize, abs_amt) orelse std.math.maxInt(usize);
8686 if (abs_amt_usize > self.pos) {
8787 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 {
130130 if (isNan(x) or isNan(y))
131131 return false;
132132
133 return @fabs(x - y) <= tolerance;
133 return @abs(x - y) <= tolerance;
134134}
135135
136136/// 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 {
158158 if (isNan(x) or isNan(y))
159159 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;
162162}
163163
164164test "approxEqAbs and approxEqRel" {
......@@ -466,7 +466,7 @@ pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) !T {
466466/// Shifts left. Overflowed bits are truncated.
467467/// A negative shift amount results in a right shift.
468468pub 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
471471 const casted_shift_amt = blk: {
472472 if (@typeInfo(T) == .Vector) {
......@@ -510,7 +510,7 @@ test "shl" {
510510/// Shifts right. Overflowed bits are truncated.
511511/// A negative shift amount results in a left shift.
512512pub 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
515515 const casted_shift_amt = blk: {
516516 if (@typeInfo(T) == .Vector) {
......@@ -740,52 +740,6 @@ fn testOverflow() !void {
740740 try testing.expect((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000);
741741}
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
789743/// Divide numerator by denominator, rounding toward zero. Returns an
790744/// error on overflow or when denominator is zero.
791745pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T {
......@@ -968,50 +922,6 @@ fn testRem() !void {
968922 try testing.expectError(error.DivisionByZero, rem(f32, 10, 0));
969923}
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
1015925/// Returns the negation of the integer parameter.
1016926/// Result is a signed integer.
1017927pub 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 {
6060 }
6161
6262 // 1 > |x| >= 0.5
63 const z = (1 - @fabs(x)) * 0.5;
63 const z = (1 - @abs(x)) * 0.5;
6464 const s = @sqrt(z);
6565 const fx = pio2 - 2 * (s + s * r32(z));
6666
......@@ -119,7 +119,7 @@ fn asin64(x: f64) f64 {
119119 }
120120
121121 // 1 > |x| >= 0.5
122 const z = (1 - @fabs(x)) * 0.5;
122 const z = (1 - @abs(x)) * 0.5;
123123 const s = @sqrt(z);
124124 const r = r64(z);
125125 var fx: f64 = undefined;
lib/std/math/atan.zig+2-2
......@@ -73,7 +73,7 @@ fn atan32(x_: f32) f32 {
7373 }
7474 id = null;
7575 } else {
76 x = @fabs(x);
76 x = @abs(x);
7777 // |x| < 1.1875
7878 if (ix < 0x3F980000) {
7979 // 7/16 <= |x| < 11/16
......@@ -171,7 +171,7 @@ fn atan64(x_: f64) f64 {
171171 }
172172 id = null;
173173 } else {
174 x = @fabs(x);
174 x = @abs(x);
175175 // |x| < 1.1875
176176 if (ix < 0x3FF30000) {
177177 // 7/16 <= |x| < 11/16
lib/std/math/atan2.zig+2-2
......@@ -108,7 +108,7 @@ fn atan2_32(y: f32, x: f32) f32 {
108108 if ((m & 2) != 0 and iy + (26 << 23) < ix) {
109109 break :z 0.0;
110110 } else {
111 break :z math.atan(@fabs(y / x));
111 break :z math.atan(@abs(y / x));
112112 }
113113 };
114114
......@@ -198,7 +198,7 @@ fn atan2_64(y: f64, x: f64) f64 {
198198 if ((m & 2) != 0 and iy +% (64 << 20) < ix) {
199199 break :z 0.0;
200200 } else {
201 break :z math.atan(@fabs(y / x));
201 break :z math.atan(@abs(y / x));
202202 }
203203 };
204204
lib/std/math/big/int.zig+3-3
......@@ -29,7 +29,7 @@ pub fn calcLimbLen(scalar: anytype) usize {
2929 return 1;
3030 }
3131
32 const w_value = std.math.absCast(scalar);
32 const w_value = @abs(scalar);
3333 return @as(usize, @intCast(@divFloor(@as(Limb, @intCast(math.log2(w_value))), limb_bits) + 1));
3434}
3535
......@@ -240,7 +240,7 @@ pub const Mutable = struct {
240240
241241 switch (@typeInfo(T)) {
242242 .Int => |info| {
243 var w_value = std.math.absCast(value);
243 var w_value = @abs(value);
244244
245245 if (info.bits <= limb_bits) {
246246 self.limbs[0] = w_value;
......@@ -255,7 +255,7 @@ pub const Mutable = struct {
255255 }
256256 },
257257 .ComptimeInt => {
258 comptime var w_value = std.math.absCast(value);
258 comptime var w_value = @abs(value);
259259
260260 if (w_value <= maxInt(Limb)) {
261261 self.limbs[0] = w_value;
lib/std/math/complex/cosh.zig+4-4
......@@ -44,12 +44,12 @@ fn cosh32(z: Complex(f32)) Complex(f32) {
4444 // |x|>= 9, so cosh(x) ~= exp(|x|)
4545 if (ix < 0x42b17218) {
4646 // x < 88.7: exp(|x|) won't overflow
47 const h = @exp(@fabs(x)) * 0.5;
47 const h = @exp(@abs(x)) * 0.5;
4848 return Complex(f32).init(math.copysign(h, x) * @cos(y), h * @sin(y));
4949 }
5050 // x < 192.7: scale to avoid overflow
5151 else if (ix < 0x4340b1e7) {
52 const v = Complex(f32).init(@fabs(x), y);
52 const v = Complex(f32).init(@abs(x), y);
5353 const r = ldexp_cexp(v, -1);
5454 return Complex(f32).init(r.re, r.im * math.copysign(@as(f32, 1.0), x));
5555 }
......@@ -112,12 +112,12 @@ fn cosh64(z: Complex(f64)) Complex(f64) {
112112 // |x|>= 22, so cosh(x) ~= exp(|x|)
113113 if (ix < 0x40862e42) {
114114 // x < 710: exp(|x|) won't overflow
115 const h = @exp(@fabs(x)) * 0.5;
115 const h = @exp(@abs(x)) * 0.5;
116116 return Complex(f64).init(h * @cos(y), math.copysign(h, x) * @sin(y));
117117 }
118118 // x < 1455: scale to avoid overflow
119119 else if (ix < 0x4096bbaa) {
120 const v = Complex(f64).init(@fabs(x), y);
120 const v = Complex(f64).init(@abs(x), y);
121121 const r = ldexp_cexp(v, -1);
122122 return Complex(f64).init(r.re, r.im * math.copysign(@as(f64, 1.0), x));
123123 }
lib/std/math/complex/sinh.zig+4-4
......@@ -44,12 +44,12 @@ fn sinh32(z: Complex(f32)) Complex(f32) {
4444 // |x|>= 9, so cosh(x) ~= exp(|x|)
4545 if (ix < 0x42b17218) {
4646 // x < 88.7: exp(|x|) won't overflow
47 const h = @exp(@fabs(x)) * 0.5;
47 const h = @exp(@abs(x)) * 0.5;
4848 return Complex(f32).init(math.copysign(h, x) * @cos(y), h * @sin(y));
4949 }
5050 // x < 192.7: scale to avoid overflow
5151 else if (ix < 0x4340b1e7) {
52 const v = Complex(f32).init(@fabs(x), y);
52 const v = Complex(f32).init(@abs(x), y);
5353 const r = ldexp_cexp(v, -1);
5454 return Complex(f32).init(r.re * math.copysign(@as(f32, 1.0), x), r.im);
5555 }
......@@ -111,12 +111,12 @@ fn sinh64(z: Complex(f64)) Complex(f64) {
111111 // |x|>= 22, so cosh(x) ~= exp(|x|)
112112 if (ix < 0x40862e42) {
113113 // x < 710: exp(|x|) won't overflow
114 const h = @exp(@fabs(x)) * 0.5;
114 const h = @exp(@abs(x)) * 0.5;
115115 return Complex(f64).init(math.copysign(h, x) * @cos(y), h * @sin(y));
116116 }
117117 // x < 1455: scale to avoid overflow
118118 else if (ix < 0x4096bbaa) {
119 const v = Complex(f64).init(@fabs(x), y);
119 const v = Complex(f64).init(@abs(x), y);
120120 const r = ldexp_cexp(v, -1);
121121 return Complex(f64).init(r.re * math.copysign(@as(f64, 1.0), x), r.im);
122122 }
lib/std/math/complex/sqrt.zig+5-5
......@@ -43,7 +43,7 @@ fn sqrt32(z: Complex(f32)) Complex(f32) {
4343 // sqrt(-inf + i nan) = nan +- inf i
4444 // sqrt(-inf + iy) = 0 + inf i
4545 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));
4747 } else {
4848 return Complex(f32).init(x, math.copysign(y - y, y));
4949 }
......@@ -64,7 +64,7 @@ fn sqrt32(z: Complex(f32)) Complex(f32) {
6464 } else {
6565 const t = @sqrt((-dx + math.hypot(f64, dx, dy)) * 0.5);
6666 return Complex(f32).init(
67 @as(f32, @floatCast(@fabs(y) / (2.0 * t))),
67 @as(f32, @floatCast(@abs(y) / (2.0 * t))),
6868 @as(f32, @floatCast(math.copysign(t, y))),
6969 );
7070 }
......@@ -94,7 +94,7 @@ fn sqrt64(z: Complex(f64)) Complex(f64) {
9494 // sqrt(-inf + i nan) = nan +- inf i
9595 // sqrt(-inf + iy) = 0 + inf i
9696 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));
9898 } else {
9999 return Complex(f64).init(x, math.copysign(y - y, y));
100100 }
......@@ -104,7 +104,7 @@ fn sqrt64(z: Complex(f64)) Complex(f64) {
104104
105105 // scale to avoid overflow
106106 var scale = false;
107 if (@fabs(x) >= threshold or @fabs(y) >= threshold) {
107 if (@abs(x) >= threshold or @abs(y) >= threshold) {
108108 x *= 0.25;
109109 y *= 0.25;
110110 scale = true;
......@@ -116,7 +116,7 @@ fn sqrt64(z: Complex(f64)) Complex(f64) {
116116 result = Complex(f64).init(t, y / (2.0 * t));
117117 } else {
118118 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));
120120 }
121121
122122 if (scale) {
lib/std/math/complex/tanh.zig+2-2
......@@ -44,7 +44,7 @@ fn tanh32(z: Complex(f32)) Complex(f32) {
4444
4545 // x >= 11
4646 if (ix >= 0x41300000) {
47 const exp_mx = @exp(-@fabs(x));
47 const exp_mx = @exp(-@abs(x));
4848 return Complex(f32).init(math.copysign(@as(f32, 1.0), x), 4 * @sin(y) * @cos(y) * exp_mx * exp_mx);
4949 }
5050
......@@ -87,7 +87,7 @@ fn tanh64(z: Complex(f64)) Complex(f64) {
8787
8888 // x >= 22
8989 if (ix >= 0x40360000) {
90 const exp_mx = @exp(-@fabs(x));
90 const exp_mx = @exp(-@abs(x));
9191 return Complex(f64).init(math.copysign(@as(f64, 1.0), x), 4 * @sin(y) * @cos(y) * exp_mx * exp_mx);
9292 }
9393
lib/std/math/pow.zig+2-2
......@@ -82,7 +82,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {
8282 }
8383 // pow(x, +inf) = +0 for |x| < 1
8484 // 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)) {
8686 return 0;
8787 }
8888 // pow(x, -inf) = +inf for |x| < 1
......@@ -115,7 +115,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {
115115 return 1 / @sqrt(x);
116116 }
117117
118 const r1 = math.modf(@fabs(y));
118 const r1 = math.modf(@abs(y));
119119 var yi = r1.ipart;
120120 var yf = r1.fpart;
121121
lib/std/meta.zig+2-2
......@@ -1104,6 +1104,6 @@ pub fn isError(error_union: anytype) bool {
11041104}
11051105
11061106test "isError" {
1107 try std.testing.expect(isError(math.absInt(@as(i8, -128))));
1108 try std.testing.expect(!isError(math.absInt(@as(i8, -127))));
1107 try std.testing.expect(isError(math.divTrunc(u8, 5, 0)));
1108 try std.testing.expect(!isError(math.divTrunc(u8, 5, 5)));
11091109}
lib/std/rand/ziggurat.zig+1-1
......@@ -33,7 +33,7 @@ pub fn next_f64(random: Random, comptime tables: ZigTable) f64 {
3333 };
3434
3535 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
3838 // equivalent to |u| < tables.x[i+1] / tables.x[i] (or u < tables.x[i+1] / tables.x[i])
3939 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 {
8888
8989// Standard C Library bug: The absolute value of the most negative integer remains negative.
9090pub 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));
9298}
9399pub inline fn __builtin_fabs(val: f64) f64 {
94 return @fabs(val);
100 return @abs(val);
95101}
96102pub inline fn __builtin_fabsf(val: f32) f32 {
97 return @fabs(val);
103 return @abs(val);
98104}
99105
100106pub inline fn __builtin_floor(val: f64) f64 {
lib/zig.h+41
......@@ -946,6 +946,24 @@ typedef unsigned long zig_Builtin64;
946946typedef unsigned long long zig_Builtin64;
947947#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
949967static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) {
950968 return zig_wrap_u8(val >> (8 - bits), bits);
951969}
......@@ -1141,6 +1159,24 @@ zig_builtin_clz(16)
11411159zig_builtin_clz(32)
11421160zig_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
11441180/* ======================== 128-bit Integer Support ========================= */
11451181
11461182#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) {
14661502 return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
14671503}
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
14691510#if zig_has_int128
14701511
14711512static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {