| author | |
| committer | |
| log | 937138cb90ae9327b0f7a932910c8d6080984f5c |
| tree | 458e4beacf025609f843d2db1188f5b9bd8488d5 |
| parent | ab3ac1e6701431ae7dea99b23852e36b369d6b87 |
| parent | 9763573ebb4f05eaa1c0bd5598f8dd6aee20ae9c |
| signature |
Replace @fabs builtin with new @abs builtin51 files changed, 937 insertions(+), 309 deletions(-)
doc/langref.html.in+7-4| ... | @@ -9421,14 +9421,17 @@ fn doTheTest() !void { | ... | @@ -9421,14 +9421,17 @@ fn doTheTest() !void { |
| 9421 | Supports {#link|Floats#} and {#link|Vectors#} of floats. | 9421 | Supports {#link|Floats#} and {#link|Vectors#} of floats. |
| 9422 | </p> | 9422 | </p> |
| 9423 | {#header_close#} | 9423 | {#header_close#} |
| 9424 | {#header_open|@fabs#} | 9424 | {#header_open|@abs#} |
| 9425 | <pre>{#syntax#}@fabs(value: anytype) @TypeOf(value){#endsyntax#}</pre> | 9425 | <pre>{#syntax#}@abs(value: anytype) anytype{#endsyntax#}</pre> |
| 9426 | <p> | 9426 | <p> |
| 9427 | Returns the absolute value of a floating point number. Uses a dedicated hardware instruction | 9427 | Returns the absolute value of an integer or a floating point number. Uses a dedicated hardware instruction |
| 9428 | when available. | 9428 | when available. |
| 9429 | |||
| 9430 | The return type is always an unsigned integer of the same bit width as the operand if the operand is an integer. | ||
| 9431 | Unsigned integer operands are supported. The builtin cannot overflow for signed integer operands. | ||
| 9429 | </p> | 9432 | </p> |
| 9430 | <p> | 9433 | <p> |
| 9431 | Supports {#link|Floats#} and {#link|Vectors#} of floats. | 9434 | Supports {#link|Floats#}, {#link|Integers#} and {#link|Vectors#} of floats or integers. |
| 9432 | </p> | 9435 | </p> |
| 9433 | {#header_close#} | 9436 | {#header_close#} |
| 9434 | {#header_open|@floor#} | 9437 | {#header_open|@floor#} |
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; |
| 3 | const isInf = std.math.isInf; | 3 | const isInf = std.math.isInf; |
| 4 | const scalbn = std.math.scalbn; | 4 | const scalbn = std.math.scalbn; |
| 5 | const ilogb = std.math.ilogb; | 5 | const ilogb = std.math.ilogb; |
| 6 | const fabs = std.math.fabs; | ||
| 7 | const maxInt = std.math.maxInt; | 6 | const maxInt = std.math.maxInt; |
| 8 | const minInt = std.math.minInt; | 7 | const minInt = std.math.minInt; |
| 9 | const isFinite = std.math.isFinite; | 8 | 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) { | ... | @@ -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; |
| 17 | 16 | ||
| 18 | // logbw used to prevent under/over-flow | 17 | // 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); |
| 31 | 31 | ||
| 32 | // Make sure result is more accurate than the adjacent floats | 32 | // 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)); |
| 36 | 36 | ||
| 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; |
| 19 | 19 | ||
| 20 | // Sign | 20 | // 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; |
| 24 | 24 |
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; |
| 544 | 544 | ||
| 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); |
| 1415 | 1415 | ||
| 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 sign | 1417 | // 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; |
| 1419 | 1419 |
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 { |
| 81 | 81 | ||
| 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; |
| 132 | 132 | ||
| 133 | return @fabs(x - y) <= tolerance; | 133 | return @abs(x - y) <= tolerance; |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 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; |
| 160 | 160 | ||
| 161 | return @fabs(x - y) <= @max(@fabs(x), @fabs(y)) * tolerance; | 161 | return @abs(x - y) <= @max(@abs(x), @abs(y)) * tolerance; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | test "approxEqAbs and approxEqRel" { | 164 | test "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. |
| 468 | pub fn shl(comptime T: type, a: T, shift_amt: anytype) T { | 468 | pub 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); |
| 470 | 470 | ||
| 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. |
| 512 | pub fn shr(comptime T: type, a: T, shift_amt: anytype) T { | 512 | pub 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); |
| 514 | 514 | ||
| 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 | } |
| 742 | 742 | ||
| 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. | ||
| 747 | pub 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 | |||
| 776 | test "absInt" { | ||
| 777 | try testAbsInt(); | ||
| 778 | try comptime testAbsInt(); | ||
| 779 | } | ||
| 780 | fn 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 an | 743 | /// 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. |
| 791 | pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T { | 745 | pub 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 | } |
| 970 | 924 | ||
| 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 | ||
| 974 | pub 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. | ||
| 981 | pub 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 | |||
| 1007 | test "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. |
| 1017 | pub fn negateCast(x: anytype) !std.meta.Int(.signed, @bitSizeOf(@TypeOf(x))) { | 927 | pub 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 | } |
| 61 | 61 | ||
| 62 | // 1 > |x| >= 0.5 | 62 | // 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)); |
| 66 | 66 | ||
| ... | @@ -119,7 +119,7 @@ fn asin64(x: f64) f64 { | ... | @@ -119,7 +119,7 @@ fn asin64(x: f64) f64 { |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | // 1 > |x| >= 0.5 | 121 | // 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.1875 | 77 | // |x| < 1.1875 |
| 78 | if (ix < 0x3F980000) { | 78 | if (ix < 0x3F980000) { |
| 79 | // 7/16 <= |x| < 11/16 | 79 | // 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.1875 | 175 | // |x| < 1.1875 |
| 176 | if (ix < 0x3FF30000) { | 176 | if (ix < 0x3FF30000) { |
| 177 | // 7/16 <= |x| < 11/16 | 177 | // 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 | }; |
| 114 | 114 | ||
| ... | @@ -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 | }; |
| 204 | 204 |
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 | } |
| 31 | 31 | ||
| 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 | } |
| 35 | 35 | ||
| ... | @@ -240,7 +240,7 @@ pub const Mutable = struct { | ... | @@ -240,7 +240,7 @@ pub const Mutable = struct { |
| 240 | 240 | ||
| 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); |
| 244 | 244 | ||
| 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); |
| 259 | 259 | ||
| 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 overflow | 46 | // 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 overflow | 50 | // 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 overflow | 114 | // 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 overflow | 118 | // 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 overflow | 46 | // 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 overflow | 50 | // 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 overflow | 113 | // 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 overflow | 117 | // 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 i | 43 | // sqrt(-inf + i nan) = nan +- inf i |
| 44 | // sqrt(-inf + iy) = 0 + inf i | 44 | // 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 i | 94 | // sqrt(-inf + i nan) = nan +- inf i |
| 95 | // sqrt(-inf + iy) = 0 + inf i | 95 | // 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) { |
| 104 | 104 | ||
| 105 | // scale to avoid overflow | 105 | // 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 | } |
| 121 | 121 | ||
| 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) { |
| 44 | 44 | ||
| 45 | // x >= 11 | 45 | // 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 | } |
| 50 | 50 | ||
| ... | @@ -87,7 +87,7 @@ fn tanh64(z: Complex(f64)) Complex(f64) { | ... | @@ -87,7 +87,7 @@ fn tanh64(z: Complex(f64)) Complex(f64) { |
| 87 | 87 | ||
| 88 | // x >= 22 | 88 | // 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 | } |
| 93 | 93 |
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| < 1 | 83 | // pow(x, +inf) = +0 for |x| < 1 |
| 84 | // pow(x, -inf) = +0 for |x| > 1 | 84 | // 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| < 1 | 88 | // 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 | } |
| 117 | 117 | ||
| 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; |
| 121 | 121 |
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 | } |
| 1105 | 1105 | ||
| 1106 | test "isError" { | 1106 | test "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 | }; |
| 34 | 34 | ||
| 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; |
| 37 | 37 | ||
| 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 { |
| 88 | 88 | ||
| 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. |
| 90 | pub inline fn __builtin_abs(val: c_int) c_int { | 90 | pub 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 | } | ||
| 93 | pub inline fn __builtin_labs(val: c_long) c_long { | ||
| 94 | return if (val == std.math.minInt(c_long)) val else @intCast(@abs(val)); | ||
| 95 | } | ||
| 96 | pub 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 | } |
| 93 | pub inline fn __builtin_fabs(val: f64) f64 { | 99 | pub inline fn __builtin_fabs(val: f64) f64 { |
| 94 | return @fabs(val); | 100 | return @abs(val); |
| 95 | } | 101 | } |
| 96 | pub inline fn __builtin_fabsf(val: f32) f32 { | 102 | pub inline fn __builtin_fabsf(val: f32) f32 { |
| 97 | return @fabs(val); | 103 | return @abs(val); |
| 98 | } | 104 | } |
| 99 | 105 | ||
| 100 | pub inline fn __builtin_floor(val: f64) f64 { | 106 | pub inline fn __builtin_floor(val: f64) f64 { |
lib/std/zig/render.zig+2| ... | @@ -1503,6 +1503,8 @@ fn renderBuiltinCall( | ... | @@ -1503,6 +1503,8 @@ fn renderBuiltinCall( |
| 1503 | try ais.writer().writeAll("@ptrFromInt"); | 1503 | try ais.writer().writeAll("@ptrFromInt"); |
| 1504 | } else if (mem.eql(u8, slice, "@ptrToInt")) { | 1504 | } else if (mem.eql(u8, slice, "@ptrToInt")) { |
| 1505 | try ais.writer().writeAll("@intFromPtr"); | 1505 | try ais.writer().writeAll("@intFromPtr"); |
| 1506 | } else if (mem.eql(u8, slice, "@fabs")) { | ||
| 1507 | try ais.writer().writeAll("@abs"); | ||
| 1506 | } else { | 1508 | } else { |
| 1507 | try renderToken(ais, tree, builtin_token, .none); // @name | 1509 | try renderToken(ais, tree, builtin_token, .none); // @name |
| 1508 | } | 1510 | } |
lib/zig.h+41| ... | @@ -946,6 +946,24 @@ typedef unsigned long zig_Builtin64; | ... | @@ -946,6 +946,24 @@ typedef unsigned long zig_Builtin64; |
| 946 | typedef unsigned long long zig_Builtin64; | 946 | typedef unsigned long long zig_Builtin64; |
| 947 | #endif | 947 | #endif |
| 948 | 948 | ||
| 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 | |||
| 949 | static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) { | 967 | static 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) |
| 1141 | zig_builtin_clz(32) | 1159 | zig_builtin_clz(32) |
| 1142 | zig_builtin_clz(64) | 1160 | zig_builtin_clz(64) |
| 1143 | 1161 | ||
| 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 | ||
| 1175 | zig_builtin_abs(8) | ||
| 1176 | zig_builtin_abs(16) | ||
| 1177 | zig_builtin_abs(32) | ||
| 1178 | zig_builtin_abs(64) | ||
| 1179 | |||
| 1144 | /* ======================== 128-bit Integer Support ========================= */ | 1180 | /* ======================== 128-bit Integer Support ========================= */ |
| 1145 | 1181 | ||
| 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 | } |
| 1468 | 1504 | ||
| 1505 | static 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_int128 | 1510 | #if zig_has_int128 |
| 1470 | 1511 | ||
| 1471 | static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { | 1512 | static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { |
src/Air.zig+6-5| ... | @@ -356,9 +356,10 @@ pub const Inst = struct { | ... | @@ -356,9 +356,10 @@ pub const Inst = struct { |
| 356 | /// Base 10 logarithm of a floating point number. | 356 | /// Base 10 logarithm of a floating point number. |
| 357 | /// Uses the `un_op` field. | 357 | /// Uses the `un_op` field. |
| 358 | log10, | 358 | log10, |
| 359 | /// Aboslute value of a floating point number. | 359 | /// Aboslute value of an integer, floating point number or vector. |
| 360 | /// Uses the `un_op` field. | 360 | /// Result type is always unsigned if the operand is an integer. |
| 361 | fabs, | 361 | /// Uses the `ty_op` field. |
| 362 | abs, | ||
| 362 | /// Floor: rounds a floating pointer number down to the nearest integer. | 363 | /// Floor: rounds a floating pointer number down to the nearest integer. |
| 363 | /// Uses the `un_op` field. | 364 | /// Uses the `un_op` field. |
| 364 | floor, | 365 | floor, |
| ... | @@ -1279,7 +1280,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) | ... | @@ -1279,7 +1280,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1279 | .log, | 1280 | .log, |
| 1280 | .log2, | 1281 | .log2, |
| 1281 | .log10, | 1282 | .log10, |
| 1282 | .fabs, | ||
| 1283 | .floor, | 1283 | .floor, |
| 1284 | .ceil, | 1284 | .ceil, |
| 1285 | .round, | 1285 | .round, |
| ... | @@ -1384,6 +1384,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) | ... | @@ -1384,6 +1384,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1384 | .addrspace_cast, | 1384 | .addrspace_cast, |
| 1385 | .c_va_arg, | 1385 | .c_va_arg, |
| 1386 | .c_va_copy, | 1386 | .c_va_copy, |
| 1387 | .abs, | ||
| 1387 | => return air.getRefType(datas[inst].ty_op.ty), | 1388 | => return air.getRefType(datas[inst].ty_op.ty), |
| 1388 | 1389 | ||
| 1389 | .loop, | 1390 | .loop, |
| ... | @@ -1697,7 +1698,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { | ... | @@ -1697,7 +1698,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { |
| 1697 | .log, | 1698 | .log, |
| 1698 | .log2, | 1699 | .log2, |
| 1699 | .log10, | 1700 | .log10, |
| 1700 | .fabs, | 1701 | .abs, |
| 1701 | .floor, | 1702 | .floor, |
| 1702 | .ceil, | 1703 | .ceil, |
| 1703 | .round, | 1704 | .round, |
src/AstGen.zig+2-2| ... | @@ -2601,7 +2601,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As | ... | @@ -2601,7 +2601,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2601 | .log, | 2601 | .log, |
| 2602 | .log2, | 2602 | .log2, |
| 2603 | .log10, | 2603 | .log10, |
| 2604 | .fabs, | 2604 | .abs, |
| 2605 | .floor, | 2605 | .floor, |
| 2606 | .ceil, | 2606 | .ceil, |
| 2607 | .trunc, | 2607 | .trunc, |
| ... | @@ -8385,7 +8385,7 @@ fn builtinCall( | ... | @@ -8385,7 +8385,7 @@ fn builtinCall( |
| 8385 | .log => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log), | 8385 | .log => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log), |
| 8386 | .log2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log2), | 8386 | .log2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log2), |
| 8387 | .log10 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log10), | 8387 | .log10 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log10), |
| 8388 | .fabs => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .fabs), | 8388 | .abs => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .abs), |
| 8389 | .floor => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .floor), | 8389 | .floor => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .floor), |
| 8390 | .ceil => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ceil), | 8390 | .ceil => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ceil), |
| 8391 | .trunc => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .trunc), | 8391 | .trunc => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .trunc), |
src/AstRlAnnotate.zig+1-1| ... | @@ -929,7 +929,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. | ... | @@ -929,7 +929,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. |
| 929 | .log, | 929 | .log, |
| 930 | .log2, | 930 | .log2, |
| 931 | .log10, | 931 | .log10, |
| 932 | .fabs, | 932 | .abs, |
| 933 | .floor, | 933 | .floor, |
| 934 | .ceil, | 934 | .ceil, |
| 935 | .trunc, | 935 | .trunc, |
src/Autodoc.zig+1-1| ... | @@ -1669,7 +1669,7 @@ fn walkInstruction( | ... | @@ -1669,7 +1669,7 @@ fn walkInstruction( |
| 1669 | .log, | 1669 | .log, |
| 1670 | .log2, | 1670 | .log2, |
| 1671 | .log10, | 1671 | .log10, |
| 1672 | .fabs, | 1672 | .abs, |
| 1673 | .floor, | 1673 | .floor, |
| 1674 | .ceil, | 1674 | .ceil, |
| 1675 | .trunc, | 1675 | .trunc, |
src/BuiltinFn.zig+3-3| ... | @@ -102,7 +102,7 @@ pub const Tag = enum { | ... | @@ -102,7 +102,7 @@ pub const Tag = enum { |
| 102 | log, | 102 | log, |
| 103 | log2, | 103 | log2, |
| 104 | log10, | 104 | log10, |
| 105 | fabs, | 105 | abs, |
| 106 | floor, | 106 | floor, |
| 107 | ceil, | 107 | ceil, |
| 108 | trunc, | 108 | trunc, |
| ... | @@ -874,9 +874,9 @@ pub const list = list: { | ... | @@ -874,9 +874,9 @@ pub const list = list: { |
| 874 | }, | 874 | }, |
| 875 | }, | 875 | }, |
| 876 | .{ | 876 | .{ |
| 877 | "@fabs", | 877 | "@abs", |
| 878 | .{ | 878 | .{ |
| 879 | .tag = .fabs, | 879 | .tag = .abs, |
| 880 | .param_count = 1, | 880 | .param_count = 1, |
| 881 | }, | 881 | }, |
| 882 | }, | 882 | }, |
src/Liveness.zig+2-2| ... | @@ -384,6 +384,7 @@ pub fn categorizeOperand( | ... | @@ -384,6 +384,7 @@ pub fn categorizeOperand( |
| 384 | .addrspace_cast, | 384 | .addrspace_cast, |
| 385 | .c_va_arg, | 385 | .c_va_arg, |
| 386 | .c_va_copy, | 386 | .c_va_copy, |
| 387 | .abs, | ||
| 387 | => { | 388 | => { |
| 388 | const o = air_datas[inst].ty_op; | 389 | const o = air_datas[inst].ty_op; |
| 389 | if (o.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none); | 390 | if (o.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none); |
| ... | @@ -420,7 +421,6 @@ pub fn categorizeOperand( | ... | @@ -420,7 +421,6 @@ pub fn categorizeOperand( |
| 420 | .log, | 421 | .log, |
| 421 | .log2, | 422 | .log2, |
| 422 | .log10, | 423 | .log10, |
| 423 | .fabs, | ||
| 424 | .floor, | 424 | .floor, |
| 425 | .ceil, | 425 | .ceil, |
| 426 | .round, | 426 | .round, |
| ... | @@ -1027,6 +1027,7 @@ fn analyzeInst( | ... | @@ -1027,6 +1027,7 @@ fn analyzeInst( |
| 1027 | .addrspace_cast, | 1027 | .addrspace_cast, |
| 1028 | .c_va_arg, | 1028 | .c_va_arg, |
| 1029 | .c_va_copy, | 1029 | .c_va_copy, |
| 1030 | .abs, | ||
| 1030 | => { | 1031 | => { |
| 1031 | const o = inst_datas[inst].ty_op; | 1032 | const o = inst_datas[inst].ty_op; |
| 1032 | return analyzeOperands(a, pass, data, inst, .{ o.operand, .none, .none }); | 1033 | return analyzeOperands(a, pass, data, inst, .{ o.operand, .none, .none }); |
| ... | @@ -1054,7 +1055,6 @@ fn analyzeInst( | ... | @@ -1054,7 +1055,6 @@ fn analyzeInst( |
| 1054 | .log, | 1055 | .log, |
| 1055 | .log2, | 1056 | .log2, |
| 1056 | .log10, | 1057 | .log10, |
| 1057 | .fabs, | ||
| 1058 | .floor, | 1058 | .floor, |
| 1059 | .ceil, | 1059 | .ceil, |
| 1060 | .round, | 1060 | .round, |
src/Liveness/Verify.zig+1-1| ... | @@ -110,6 +110,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { | ... | @@ -110,6 +110,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { |
| 110 | .addrspace_cast, | 110 | .addrspace_cast, |
| 111 | .c_va_arg, | 111 | .c_va_arg, |
| 112 | .c_va_copy, | 112 | .c_va_copy, |
| 113 | .abs, | ||
| 113 | => { | 114 | => { |
| 114 | const ty_op = data[inst].ty_op; | 115 | const ty_op = data[inst].ty_op; |
| 115 | try self.verifyInstOperands(inst, .{ ty_op.operand, .none, .none }); | 116 | try self.verifyInstOperands(inst, .{ ty_op.operand, .none, .none }); |
| ... | @@ -136,7 +137,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { | ... | @@ -136,7 +137,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { |
| 136 | .log, | 137 | .log, |
| 137 | .log2, | 138 | .log2, |
| 138 | .log10, | 139 | .log10, |
| 139 | .fabs, | ||
| 140 | .floor, | 140 | .floor, |
| 141 | .ceil, | 141 | .ceil, |
| 142 | .round, | 142 | .round, |
src/Sema.zig+77-50| ... | @@ -1156,6 +1156,7 @@ fn analyzeBodyInner( | ... | @@ -1156,6 +1156,7 @@ fn analyzeBodyInner( |
| 1156 | .clz => try sema.zirBitCount(block, inst, .clz, Value.clz), | 1156 | .clz => try sema.zirBitCount(block, inst, .clz, Value.clz), |
| 1157 | .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz), | 1157 | .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz), |
| 1158 | .pop_count => try sema.zirBitCount(block, inst, .popcount, Value.popCount), | 1158 | .pop_count => try sema.zirBitCount(block, inst, .popcount, Value.popCount), |
| 1159 | .abs => try sema.zirAbs(block, inst), | ||
| 1159 | 1160 | ||
| 1160 | .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt), | 1161 | .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt), |
| 1161 | .sin => try sema.zirUnaryMath(block, inst, .sin, Value.sin), | 1162 | .sin => try sema.zirUnaryMath(block, inst, .sin, Value.sin), |
| ... | @@ -1166,7 +1167,6 @@ fn analyzeBodyInner( | ... | @@ -1166,7 +1167,6 @@ fn analyzeBodyInner( |
| 1166 | .log => try sema.zirUnaryMath(block, inst, .log, Value.log), | 1167 | .log => try sema.zirUnaryMath(block, inst, .log, Value.log), |
| 1167 | .log2 => try sema.zirUnaryMath(block, inst, .log2, Value.log2), | 1168 | .log2 => try sema.zirUnaryMath(block, inst, .log2, Value.log2), |
| 1168 | .log10 => try sema.zirUnaryMath(block, inst, .log10, Value.log10), | 1169 | .log10 => try sema.zirUnaryMath(block, inst, .log10, Value.log10), |
| 1169 | .fabs => try sema.zirUnaryMath(block, inst, .fabs, Value.fabs), | ||
| 1170 | .floor => try sema.zirUnaryMath(block, inst, .floor, Value.floor), | 1170 | .floor => try sema.zirUnaryMath(block, inst, .floor, Value.floor), |
| 1171 | .ceil => try sema.zirUnaryMath(block, inst, .ceil, Value.ceil), | 1171 | .ceil => try sema.zirUnaryMath(block, inst, .ceil, Value.ceil), |
| 1172 | .round => try sema.zirUnaryMath(block, inst, .round, Value.round), | 1172 | .round => try sema.zirUnaryMath(block, inst, .round, Value.round), |
| ... | @@ -20178,6 +20178,69 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -20178,6 +20178,69 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 20178 | return block.addUnOp(.error_name, operand); | 20178 | return block.addUnOp(.error_name, operand); |
| 20179 | } | 20179 | } |
| 20180 | 20180 | ||
| 20181 | fn zirAbs( | ||
| 20182 | sema: *Sema, | ||
| 20183 | block: *Block, | ||
| 20184 | inst: Zir.Inst.Index, | ||
| 20185 | ) CompileError!Air.Inst.Ref { | ||
| 20186 | const mod = sema.mod; | ||
| 20187 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | ||
| 20188 | const operand = try sema.resolveInst(inst_data.operand); | ||
| 20189 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | ||
| 20190 | const operand_ty = sema.typeOf(operand); | ||
| 20191 | const scalar_ty = operand_ty.scalarType(mod); | ||
| 20192 | |||
| 20193 | const result_ty = switch (scalar_ty.zigTypeTag(mod)) { | ||
| 20194 | .ComptimeFloat, .Float, .ComptimeInt => operand_ty, | ||
| 20195 | .Int => if (scalar_ty.isSignedInt(mod)) try operand_ty.toUnsigned(mod) else return operand, | ||
| 20196 | else => return sema.fail( | ||
| 20197 | block, | ||
| 20198 | operand_src, | ||
| 20199 | "expected integer, float, or vector of either integers or floats, found '{}'", | ||
| 20200 | .{operand_ty.fmt(mod)}, | ||
| 20201 | ), | ||
| 20202 | }; | ||
| 20203 | |||
| 20204 | return (try sema.maybeConstantUnaryMath(operand, result_ty, Value.abs)) orelse { | ||
| 20205 | try sema.requireRuntimeBlock(block, operand_src, null); | ||
| 20206 | return block.addTyOp(.abs, result_ty, operand); | ||
| 20207 | }; | ||
| 20208 | } | ||
| 20209 | |||
| 20210 | fn maybeConstantUnaryMath( | ||
| 20211 | sema: *Sema, | ||
| 20212 | operand: Air.Inst.Ref, | ||
| 20213 | result_ty: Type, | ||
| 20214 | comptime eval: fn (Value, Type, Allocator, *Module) Allocator.Error!Value, | ||
| 20215 | ) CompileError!?Air.Inst.Ref { | ||
| 20216 | const mod = sema.mod; | ||
| 20217 | switch (result_ty.zigTypeTag(mod)) { | ||
| 20218 | .Vector => if (try sema.resolveMaybeUndefVal(operand)) |val| { | ||
| 20219 | const scalar_ty = result_ty.scalarType(mod); | ||
| 20220 | const vec_len = result_ty.vectorLen(mod); | ||
| 20221 | if (val.isUndef(mod)) | ||
| 20222 | return try mod.undefRef(result_ty); | ||
| 20223 | |||
| 20224 | const elems = try sema.arena.alloc(InternPool.Index, vec_len); | ||
| 20225 | for (elems, 0..) |*elem, i| { | ||
| 20226 | const elem_val = try val.elemValue(sema.mod, i); | ||
| 20227 | elem.* = try (try eval(elem_val, scalar_ty, sema.arena, sema.mod)).intern(scalar_ty, mod); | ||
| 20228 | } | ||
| 20229 | return Air.internedToRef((try mod.intern(.{ .aggregate = .{ | ||
| 20230 | .ty = result_ty.toIntern(), | ||
| 20231 | .storage = .{ .elems = elems }, | ||
| 20232 | } }))); | ||
| 20233 | }, | ||
| 20234 | else => if (try sema.resolveMaybeUndefVal(operand)) |operand_val| { | ||
| 20235 | if (operand_val.isUndef(mod)) | ||
| 20236 | return try mod.undefRef(result_ty); | ||
| 20237 | const result_val = try eval(operand_val, result_ty, sema.arena, sema.mod); | ||
| 20238 | return Air.internedToRef(result_val.toIntern()); | ||
| 20239 | }, | ||
| 20240 | } | ||
| 20241 | return null; | ||
| 20242 | } | ||
| 20243 | |||
| 20181 | fn zirUnaryMath( | 20244 | fn zirUnaryMath( |
| 20182 | sema: *Sema, | 20245 | sema: *Sema, |
| 20183 | block: *Block, | 20246 | block: *Block, |
| ... | @@ -20193,58 +20256,22 @@ fn zirUnaryMath( | ... | @@ -20193,58 +20256,22 @@ fn zirUnaryMath( |
| 20193 | const operand = try sema.resolveInst(inst_data.operand); | 20256 | const operand = try sema.resolveInst(inst_data.operand); |
| 20194 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 20257 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 20195 | const operand_ty = sema.typeOf(operand); | 20258 | const operand_ty = sema.typeOf(operand); |
| 20259 | const scalar_ty = operand_ty.scalarType(mod); | ||
| 20196 | 20260 | ||
| 20197 | switch (operand_ty.zigTypeTag(mod)) { | 20261 | switch (scalar_ty.zigTypeTag(mod)) { |
| 20198 | .ComptimeFloat, .Float => {}, | 20262 | .ComptimeFloat, .Float => {}, |
| 20199 | .Vector => { | 20263 | else => return sema.fail( |
| 20200 | const scalar_ty = operand_ty.scalarType(mod); | 20264 | block, |
| 20201 | switch (scalar_ty.zigTypeTag(mod)) { | 20265 | operand_src, |
| 20202 | .ComptimeFloat, .Float => {}, | 20266 | "expected vector of floats or float type, found '{}'", |
| 20203 | else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{scalar_ty.fmt(sema.mod)}), | 20267 | .{operand_ty.fmt(sema.mod)}, |
| 20204 | } | 20268 | ), |
| 20205 | }, | ||
| 20206 | else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{operand_ty.fmt(sema.mod)}), | ||
| 20207 | } | 20269 | } |
| 20208 | 20270 | ||
| 20209 | switch (operand_ty.zigTypeTag(mod)) { | 20271 | return (try sema.maybeConstantUnaryMath(operand, operand_ty, eval)) orelse { |
| 20210 | .Vector => { | 20272 | try sema.requireRuntimeBlock(block, operand_src, null); |
| 20211 | const scalar_ty = operand_ty.scalarType(mod); | 20273 | return block.addUnOp(air_tag, operand); |
| 20212 | const vec_len = operand_ty.vectorLen(mod); | 20274 | }; |
| 20213 | const result_ty = try mod.vectorType(.{ | ||
| 20214 | .len = vec_len, | ||
| 20215 | .child = scalar_ty.toIntern(), | ||
| 20216 | }); | ||
| 20217 | if (try sema.resolveMaybeUndefVal(operand)) |val| { | ||
| 20218 | if (val.isUndef(mod)) | ||
| 20219 | return mod.undefRef(result_ty); | ||
| 20220 | |||
| 20221 | const elems = try sema.arena.alloc(InternPool.Index, vec_len); | ||
| 20222 | for (elems, 0..) |*elem, i| { | ||
| 20223 | const elem_val = try val.elemValue(sema.mod, i); | ||
| 20224 | elem.* = try (try eval(elem_val, scalar_ty, sema.arena, sema.mod)).intern(scalar_ty, mod); | ||
| 20225 | } | ||
| 20226 | return Air.internedToRef((try mod.intern(.{ .aggregate = .{ | ||
| 20227 | .ty = result_ty.toIntern(), | ||
| 20228 | .storage = .{ .elems = elems }, | ||
| 20229 | } }))); | ||
| 20230 | } | ||
| 20231 | |||
| 20232 | try sema.requireRuntimeBlock(block, operand_src, null); | ||
| 20233 | return block.addUnOp(air_tag, operand); | ||
| 20234 | }, | ||
| 20235 | .ComptimeFloat, .Float => { | ||
| 20236 | if (try sema.resolveMaybeUndefVal(operand)) |operand_val| { | ||
| 20237 | if (operand_val.isUndef(mod)) | ||
| 20238 | return mod.undefRef(operand_ty); | ||
| 20239 | const result_val = try eval(operand_val, operand_ty, sema.arena, sema.mod); | ||
| 20240 | return Air.internedToRef(result_val.toIntern()); | ||
| 20241 | } | ||
| 20242 | |||
| 20243 | try sema.requireRuntimeBlock(block, operand_src, null); | ||
| 20244 | return block.addUnOp(air_tag, operand); | ||
| 20245 | }, | ||
| 20246 | else => unreachable, | ||
| 20247 | } | ||
| 20248 | } | 20275 | } |
| 20249 | 20276 | ||
| 20250 | fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 20277 | fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -37503,7 +37530,7 @@ fn float128IntPartToBigInt( | ... | @@ -37503,7 +37530,7 @@ fn float128IntPartToBigInt( |
| 37503 | float: f128, | 37530 | float: f128, |
| 37504 | ) !std.math.big.int.Managed { | 37531 | ) !std.math.big.int.Managed { |
| 37505 | const is_negative = std.math.signbit(float); | 37532 | const is_negative = std.math.signbit(float); |
| 37506 | const floored = @floor(@fabs(float)); | 37533 | const floored = @floor(@abs(float)); |
| 37507 | 37534 | ||
| 37508 | var rational = try std.math.big.Rational.init(arena); | 37535 | var rational = try std.math.big.Rational.init(arena); |
| 37509 | defer rational.q.deinit(); | 37536 | defer rational.q.deinit(); |
src/Zir.zig+5-5| ... | @@ -846,8 +846,8 @@ pub const Inst = struct { | ... | @@ -846,8 +846,8 @@ pub const Inst = struct { |
| 846 | log2, | 846 | log2, |
| 847 | /// Implement builtin `@log10`. Uses `un_node`. | 847 | /// Implement builtin `@log10`. Uses `un_node`. |
| 848 | log10, | 848 | log10, |
| 849 | /// Implement builtin `@fabs`. Uses `un_node`. | 849 | /// Implement builtin `@abs`. Uses `un_node`. |
| 850 | fabs, | 850 | abs, |
| 851 | /// Implement builtin `@floor`. Uses `un_node`. | 851 | /// Implement builtin `@floor`. Uses `un_node`. |
| 852 | floor, | 852 | floor, |
| 853 | /// Implement builtin `@ceil`. Uses `un_node`. | 853 | /// Implement builtin `@ceil`. Uses `un_node`. |
| ... | @@ -1198,7 +1198,7 @@ pub const Inst = struct { | ... | @@ -1198,7 +1198,7 @@ pub const Inst = struct { |
| 1198 | .log, | 1198 | .log, |
| 1199 | .log2, | 1199 | .log2, |
| 1200 | .log10, | 1200 | .log10, |
| 1201 | .fabs, | 1201 | .abs, |
| 1202 | .floor, | 1202 | .floor, |
| 1203 | .ceil, | 1203 | .ceil, |
| 1204 | .trunc, | 1204 | .trunc, |
| ... | @@ -1493,7 +1493,7 @@ pub const Inst = struct { | ... | @@ -1493,7 +1493,7 @@ pub const Inst = struct { |
| 1493 | .log, | 1493 | .log, |
| 1494 | .log2, | 1494 | .log2, |
| 1495 | .log10, | 1495 | .log10, |
| 1496 | .fabs, | 1496 | .abs, |
| 1497 | .floor, | 1497 | .floor, |
| 1498 | .ceil, | 1498 | .ceil, |
| 1499 | .trunc, | 1499 | .trunc, |
| ... | @@ -1756,7 +1756,7 @@ pub const Inst = struct { | ... | @@ -1756,7 +1756,7 @@ pub const Inst = struct { |
| 1756 | .log = .un_node, | 1756 | .log = .un_node, |
| 1757 | .log2 = .un_node, | 1757 | .log2 = .un_node, |
| 1758 | .log10 = .un_node, | 1758 | .log10 = .un_node, |
| 1759 | .fabs = .un_node, | 1759 | .abs = .un_node, |
| 1760 | .floor = .un_node, | 1760 | .floor = .un_node, |
| 1761 | .ceil = .un_node, | 1761 | .ceil = .un_node, |
| 1762 | .trunc = .un_node, | 1762 | .trunc = .un_node, |
src/arch/aarch64/CodeGen.zig+7-1| ... | @@ -713,7 +713,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -713,7 +713,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 713 | .log, | 713 | .log, |
| 714 | .log2, | 714 | .log2, |
| 715 | .log10, | 715 | .log10, |
| 716 | .fabs, | ||
| 717 | .floor, | 716 | .floor, |
| 718 | .ceil, | 717 | .ceil, |
| 719 | .round, | 718 | .round, |
| ... | @@ -788,6 +787,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -788,6 +787,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 788 | .clz => try self.airClz(inst), | 787 | .clz => try self.airClz(inst), |
| 789 | .ctz => try self.airCtz(inst), | 788 | .ctz => try self.airCtz(inst), |
| 790 | .popcount => try self.airPopcount(inst), | 789 | .popcount => try self.airPopcount(inst), |
| 790 | .abs => try self.airAbs(inst), | ||
| 791 | .byte_swap => try self.airByteSwap(inst), | 791 | .byte_swap => try self.airByteSwap(inst), |
| 792 | .bit_reverse => try self.airBitReverse(inst), | 792 | .bit_reverse => try self.airBitReverse(inst), |
| 793 | .tag_name => try self.airTagName(inst), | 793 | .tag_name => try self.airTagName(inst), |
| ... | @@ -3550,6 +3550,12 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3550,6 +3550,12 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 3550 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 3550 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3551 | } | 3551 | } |
| 3552 | 3552 | ||
| 3553 | fn airAbs(self: *Self, inst: Air.Inst.Index) !void { | ||
| 3554 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | ||
| 3555 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airAbs for {}", .{self.target.cpu.arch}); | ||
| 3556 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | ||
| 3557 | } | ||
| 3558 | |||
| 3553 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { | 3559 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 3554 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3560 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3555 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airByteSwap for {}", .{self.target.cpu.arch}); | 3561 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airByteSwap for {}", .{self.target.cpu.arch}); |
src/arch/arm/CodeGen.zig+8-1| ... | @@ -699,7 +699,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -699,7 +699,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 699 | .log, | 699 | .log, |
| 700 | .log2, | 700 | .log2, |
| 701 | .log10, | 701 | .log10, |
| 702 | .fabs, | ||
| 703 | .floor, | 702 | .floor, |
| 704 | .ceil, | 703 | .ceil, |
| 705 | .round, | 704 | .round, |
| ... | @@ -774,6 +773,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -774,6 +773,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 774 | .clz => try self.airClz(inst), | 773 | .clz => try self.airClz(inst), |
| 775 | .ctz => try self.airCtz(inst), | 774 | .ctz => try self.airCtz(inst), |
| 776 | .popcount => try self.airPopcount(inst), | 775 | .popcount => try self.airPopcount(inst), |
| 776 | .abs => try self.airAbs(inst), | ||
| 777 | .byte_swap => try self.airByteSwap(inst), | 777 | .byte_swap => try self.airByteSwap(inst), |
| 778 | .bit_reverse => try self.airBitReverse(inst), | 778 | .bit_reverse => try self.airBitReverse(inst), |
| 779 | .tag_name => try self.airTagName(inst), | 779 | .tag_name => try self.airTagName(inst), |
| ... | @@ -2591,6 +2591,13 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2591,6 +2591,13 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 2591 | // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 2591 | // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2592 | } | 2592 | } |
| 2593 | 2593 | ||
| 2594 | fn airAbs(self: *Self, inst: Air.Inst.Index) !void { | ||
| 2595 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | ||
| 2596 | _ = ty_op; | ||
| 2597 | return self.fail("TODO implement airAbs for {}", .{self.target.cpu.arch}); | ||
| 2598 | // return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | ||
| 2599 | } | ||
| 2600 | |||
| 2594 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { | 2601 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 2595 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2602 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2596 | _ = ty_op; | 2603 | _ = ty_op; |
src/arch/riscv64/CodeGen.zig+7-1| ... | @@ -523,7 +523,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -523,7 +523,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 523 | .log, | 523 | .log, |
| 524 | .log2, | 524 | .log2, |
| 525 | .log10, | 525 | .log10, |
| 526 | .fabs, | ||
| 527 | .floor, | 526 | .floor, |
| 528 | .ceil, | 527 | .ceil, |
| 529 | .round, | 528 | .round, |
| ... | @@ -607,6 +606,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -607,6 +606,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 607 | .clz => try self.airClz(inst), | 606 | .clz => try self.airClz(inst), |
| 608 | .ctz => try self.airCtz(inst), | 607 | .ctz => try self.airCtz(inst), |
| 609 | .popcount => try self.airPopcount(inst), | 608 | .popcount => try self.airPopcount(inst), |
| 609 | .abs => try self.airAbs(inst), | ||
| 610 | .byte_swap => try self.airByteSwap(inst), | 610 | .byte_swap => try self.airByteSwap(inst), |
| 611 | .bit_reverse => try self.airBitReverse(inst), | 611 | .bit_reverse => try self.airBitReverse(inst), |
| 612 | .tag_name => try self.airTagName(inst), | 612 | .tag_name => try self.airTagName(inst), |
| ... | @@ -1447,6 +1447,12 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1447,6 +1447,12 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 1447 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1447 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1448 | } | 1448 | } |
| 1449 | 1449 | ||
| 1450 | fn airAbs(self: *Self, inst: Air.Inst.Index) !void { | ||
| 1451 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | ||
| 1452 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airAbs for {}", .{self.target.cpu.arch}); | ||
| 1453 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | ||
| 1454 | } | ||
| 1455 | |||
| 1450 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { | 1456 | fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 1451 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1457 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1452 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airByteSwap for {}", .{self.target.cpu.arch}); | 1458 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airByteSwap for {}", .{self.target.cpu.arch}); |
src/arch/sparc64/CodeGen.zig+1-1| ... | @@ -543,7 +543,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -543,7 +543,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 543 | .log, | 543 | .log, |
| 544 | .log2, | 544 | .log2, |
| 545 | .log10, | 545 | .log10, |
| 546 | .fabs, | 546 | .abs, |
| 547 | .floor, | 547 | .floor, |
| 548 | .ceil, | 548 | .ceil, |
| 549 | .round, | 549 | .round, |
src/arch/wasm/CodeGen.zig+78-1| ... | @@ -1866,13 +1866,14 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -1866,13 +1866,14 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1866 | .log => func.airUnaryFloatOp(inst, .log), | 1866 | .log => func.airUnaryFloatOp(inst, .log), |
| 1867 | .log2 => func.airUnaryFloatOp(inst, .log2), | 1867 | .log2 => func.airUnaryFloatOp(inst, .log2), |
| 1868 | .log10 => func.airUnaryFloatOp(inst, .log10), | 1868 | .log10 => func.airUnaryFloatOp(inst, .log10), |
| 1869 | .fabs => func.airUnaryFloatOp(inst, .fabs), | ||
| 1870 | .floor => func.airUnaryFloatOp(inst, .floor), | 1869 | .floor => func.airUnaryFloatOp(inst, .floor), |
| 1871 | .ceil => func.airUnaryFloatOp(inst, .ceil), | 1870 | .ceil => func.airUnaryFloatOp(inst, .ceil), |
| 1872 | .round => func.airUnaryFloatOp(inst, .round), | 1871 | .round => func.airUnaryFloatOp(inst, .round), |
| 1873 | .trunc_float => func.airUnaryFloatOp(inst, .trunc), | 1872 | .trunc_float => func.airUnaryFloatOp(inst, .trunc), |
| 1874 | .neg => func.airUnaryFloatOp(inst, .neg), | 1873 | .neg => func.airUnaryFloatOp(inst, .neg), |
| 1875 | 1874 | ||
| 1875 | .abs => func.airAbs(inst), | ||
| 1876 | |||
| 1876 | .add_with_overflow => func.airAddSubWithOverflow(inst, .add), | 1877 | .add_with_overflow => func.airAddSubWithOverflow(inst, .add), |
| 1877 | .sub_with_overflow => func.airAddSubWithOverflow(inst, .sub), | 1878 | .sub_with_overflow => func.airAddSubWithOverflow(inst, .sub), |
| 1878 | .shl_with_overflow => func.airShlWithOverflow(inst), | 1879 | .shl_with_overflow => func.airShlWithOverflow(inst), |
| ... | @@ -2786,6 +2787,82 @@ const FloatOp = enum { | ... | @@ -2786,6 +2787,82 @@ const FloatOp = enum { |
| 2786 | } | 2787 | } |
| 2787 | }; | 2788 | }; |
| 2788 | 2789 | ||
| 2790 | fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ||
| 2791 | const mod = func.bin_file.base.options.module.?; | ||
| 2792 | const ty_op = func.air.instructions.items(.data)[inst].ty_op; | ||
| 2793 | const operand = try func.resolveInst(ty_op.operand); | ||
| 2794 | const ty = func.typeOf(ty_op.operand); | ||
| 2795 | const scalar_ty = ty.scalarType(mod); | ||
| 2796 | |||
| 2797 | switch (scalar_ty.zigTypeTag(mod)) { | ||
| 2798 | .Int => if (ty.zigTypeTag(mod) == .Vector) { | ||
| 2799 | return func.fail("TODO implement airAbs for {}", .{ty.fmt(mod)}); | ||
| 2800 | } else { | ||
| 2801 | const int_bits = ty.intInfo(mod).bits; | ||
| 2802 | const wasm_bits = toWasmBits(int_bits) orelse { | ||
| 2803 | return func.fail("TODO: airAbs for signed integers larger than '{d}' bits", .{int_bits}); | ||
| 2804 | }; | ||
| 2805 | |||
| 2806 | const op = try operand.toLocal(func, ty); | ||
| 2807 | |||
| 2808 | try func.emitWValue(op); | ||
| 2809 | switch (wasm_bits) { | ||
| 2810 | 32 => { | ||
| 2811 | if (wasm_bits != int_bits) { | ||
| 2812 | try func.addImm32(wasm_bits - int_bits); | ||
| 2813 | try func.addTag(.i32_shl); | ||
| 2814 | } | ||
| 2815 | try func.addImm32(31); | ||
| 2816 | try func.addTag(.i32_shr_s); | ||
| 2817 | |||
| 2818 | const tmp = try func.allocLocal(ty); | ||
| 2819 | try func.addLabel(.local_tee, tmp.local.value); | ||
| 2820 | |||
| 2821 | try func.emitWValue(op); | ||
| 2822 | try func.addTag(.i32_xor); | ||
| 2823 | try func.emitWValue(tmp); | ||
| 2824 | try func.addTag(.i32_sub); | ||
| 2825 | |||
| 2826 | if (int_bits != wasm_bits) { | ||
| 2827 | try func.emitWValue(WValue{ .imm32 = (@as(u32, 1) << @intCast(int_bits)) - 1 }); | ||
| 2828 | try func.addTag(.i32_and); | ||
| 2829 | } | ||
| 2830 | }, | ||
| 2831 | 64 => { | ||
| 2832 | if (wasm_bits != int_bits) { | ||
| 2833 | try func.addImm64(wasm_bits - int_bits); | ||
| 2834 | try func.addTag(.i64_shl); | ||
| 2835 | } | ||
| 2836 | try func.addImm64(63); | ||
| 2837 | try func.addTag(.i64_shr_s); | ||
| 2838 | |||
| 2839 | const tmp = try func.allocLocal(ty); | ||
| 2840 | try func.addLabel(.local_tee, tmp.local.value); | ||
| 2841 | |||
| 2842 | try func.emitWValue(op); | ||
| 2843 | try func.addTag(.i64_xor); | ||
| 2844 | try func.emitWValue(tmp); | ||
| 2845 | try func.addTag(.i64_sub); | ||
| 2846 | |||
| 2847 | if (int_bits != wasm_bits) { | ||
| 2848 | try func.emitWValue(WValue{ .imm64 = (@as(u64, 1) << @intCast(int_bits)) - 1 }); | ||
| 2849 | try func.addTag(.i64_and); | ||
| 2850 | } | ||
| 2851 | }, | ||
| 2852 | else => return func.fail("TODO: Implement airAbs for {}", .{ty.fmt(mod)}), | ||
| 2853 | } | ||
| 2854 | |||
| 2855 | const result = try (WValue{ .stack = {} }).toLocal(func, ty); | ||
| 2856 | func.finishAir(inst, result, &.{ty_op.operand}); | ||
| 2857 | }, | ||
| 2858 | .Float => { | ||
| 2859 | const result = try (try func.floatOp(.fabs, ty, &.{operand})).toLocal(func, ty); | ||
| 2860 | func.finishAir(inst, result, &.{ty_op.operand}); | ||
| 2861 | }, | ||
| 2862 | else => unreachable, | ||
| 2863 | } | ||
| 2864 | } | ||
| 2865 | |||
| 2789 | fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError!void { | 2866 | fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError!void { |
| 2790 | const un_op = func.air.instructions.items(.data)[inst].un_op; | 2867 | const un_op = func.air.instructions.items(.data)[inst].un_op; |
| 2791 | const operand = try func.resolveInst(un_op); | 2868 | const operand = try func.resolveInst(un_op); |
src/arch/x86_64/CodeGen.zig+75-22| ... | @@ -1809,11 +1809,13 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -1809,11 +1809,13 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 1809 | .round, | 1809 | .round, |
| 1810 | => try self.airUnaryMath(inst), | 1810 | => try self.airUnaryMath(inst), |
| 1811 | 1811 | ||
| 1812 | .floor => try self.airRound(inst, 0b1_0_01), | 1812 | .floor => try self.airRound(inst, 0b1_0_01), |
| 1813 | .ceil => try self.airRound(inst, 0b1_0_10), | 1813 | .ceil => try self.airRound(inst, 0b1_0_10), |
| 1814 | .trunc_float => try self.airRound(inst, 0b1_0_11), | 1814 | .trunc_float => try self.airRound(inst, 0b1_0_11), |
| 1815 | .sqrt => try self.airSqrt(inst), | 1815 | .sqrt => try self.airSqrt(inst), |
| 1816 | .neg, .fabs => try self.airFloatSign(inst), | 1816 | .neg => try self.airFloatSign(inst), |
| 1817 | |||
| 1818 | .abs => try self.airAbs(inst), | ||
| 1817 | 1819 | ||
| 1818 | .add_with_overflow => try self.airAddSubWithOverflow(inst), | 1820 | .add_with_overflow => try self.airAddSubWithOverflow(inst), |
| 1819 | .sub_with_overflow => try self.airAddSubWithOverflow(inst), | 1821 | .sub_with_overflow => try self.airAddSubWithOverflow(inst), |
| ... | @@ -4885,28 +4887,26 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4885,28 +4887,26 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 4885 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); | 4887 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); |
| 4886 | } | 4888 | } |
| 4887 | 4889 | ||
| 4888 | fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { | 4890 | fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) !void { |
| 4889 | const mod = self.bin_file.options.module.?; | 4891 | const mod = self.bin_file.options.module.?; |
| 4890 | const tag = self.air.instructions.items(.tag)[inst]; | 4892 | const tag = self.air.instructions.items(.tag)[inst]; |
| 4891 | const un_op = self.air.instructions.items(.data)[inst].un_op; | ||
| 4892 | const ty = self.typeOf(un_op); | ||
| 4893 | const abi_size: u32 = switch (ty.abiSize(mod)) { | 4893 | const abi_size: u32 = switch (ty.abiSize(mod)) { |
| 4894 | 1...16 => 16, | 4894 | 1...16 => 16, |
| 4895 | 17...32 => 32, | 4895 | 17...32 => 32, |
| 4896 | else => return self.fail("TODO implement airFloatSign for {}", .{ | 4896 | else => return self.fail("TODO implement floatSign for {}", .{ |
| 4897 | ty.fmt(mod), | 4897 | ty.fmt(mod), |
| 4898 | }), | 4898 | }), |
| 4899 | }; | 4899 | }; |
| 4900 | const scalar_bits = ty.scalarType(mod).floatBits(self.target.*); | 4900 | const scalar_bits = ty.scalarType(mod).floatBits(self.target.*); |
| 4901 | if (scalar_bits == 80) return self.fail("TODO implement airFloatSign for {}", .{ | 4901 | if (scalar_bits == 80) return self.fail("TODO implement floatSign for {}", .{ |
| 4902 | ty.fmt(mod), | 4902 | ty.fmt(mod), |
| 4903 | }); | 4903 | }); |
| 4904 | 4904 | ||
| 4905 | const src_mcv = try self.resolveInst(un_op); | 4905 | const src_mcv = try self.resolveInst(operand); |
| 4906 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; | 4906 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 4907 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); | 4907 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 4908 | 4908 | ||
| 4909 | const dst_mcv: MCValue = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv)) | 4909 | const dst_mcv: MCValue = if (src_mcv.isRegister() and self.reuseOperand(inst, operand, 0, src_mcv)) |
| 4910 | src_mcv | 4910 | src_mcv |
| 4911 | else if (self.hasFeature(.avx)) | 4911 | else if (self.hasFeature(.avx)) |
| 4912 | .{ .register = try self.register_manager.allocReg(inst, sse) } | 4912 | .{ .register = try self.register_manager.allocReg(inst, sse) } |
| ... | @@ -4923,7 +4923,7 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4923,7 +4923,7 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 4923 | 4923 | ||
| 4924 | const sign_val = switch (tag) { | 4924 | const sign_val = switch (tag) { |
| 4925 | .neg => try vec_ty.minInt(mod, vec_ty), | 4925 | .neg => try vec_ty.minInt(mod, vec_ty), |
| 4926 | .fabs => try vec_ty.maxInt(mod, vec_ty), | 4926 | .abs => try vec_ty.maxInt(mod, vec_ty), |
| 4927 | else => unreachable, | 4927 | else => unreachable, |
| 4928 | }; | 4928 | }; |
| 4929 | 4929 | ||
| ... | @@ -4939,24 +4939,24 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4939,24 +4939,24 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 4939 | switch (scalar_bits) { | 4939 | switch (scalar_bits) { |
| 4940 | 16, 128 => if (abi_size <= 16 or self.hasFeature(.avx2)) switch (tag) { | 4940 | 16, 128 => if (abi_size <= 16 or self.hasFeature(.avx2)) switch (tag) { |
| 4941 | .neg => .{ .vp_, .xor }, | 4941 | .neg => .{ .vp_, .xor }, |
| 4942 | .fabs => .{ .vp_, .@"and" }, | 4942 | .abs => .{ .vp_, .@"and" }, |
| 4943 | else => unreachable, | 4943 | else => unreachable, |
| 4944 | } else switch (tag) { | 4944 | } else switch (tag) { |
| 4945 | .neg => .{ .v_ps, .xor }, | 4945 | .neg => .{ .v_ps, .xor }, |
| 4946 | .fabs => .{ .v_ps, .@"and" }, | 4946 | .abs => .{ .v_ps, .@"and" }, |
| 4947 | else => unreachable, | 4947 | else => unreachable, |
| 4948 | }, | 4948 | }, |
| 4949 | 32 => switch (tag) { | 4949 | 32 => switch (tag) { |
| 4950 | .neg => .{ .v_ps, .xor }, | 4950 | .neg => .{ .v_ps, .xor }, |
| 4951 | .fabs => .{ .v_ps, .@"and" }, | 4951 | .abs => .{ .v_ps, .@"and" }, |
| 4952 | else => unreachable, | 4952 | else => unreachable, |
| 4953 | }, | 4953 | }, |
| 4954 | 64 => switch (tag) { | 4954 | 64 => switch (tag) { |
| 4955 | .neg => .{ .v_pd, .xor }, | 4955 | .neg => .{ .v_pd, .xor }, |
| 4956 | .fabs => .{ .v_pd, .@"and" }, | 4956 | .abs => .{ .v_pd, .@"and" }, |
| 4957 | else => unreachable, | 4957 | else => unreachable, |
| 4958 | }, | 4958 | }, |
| 4959 | 80 => return self.fail("TODO implement airFloatSign for {}", .{ | 4959 | 80 => return self.fail("TODO implement floatSign for {}", .{ |
| 4960 | ty.fmt(self.bin_file.options.module.?), | 4960 | ty.fmt(self.bin_file.options.module.?), |
| 4961 | }), | 4961 | }), |
| 4962 | else => unreachable, | 4962 | else => unreachable, |
| ... | @@ -4971,20 +4971,20 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4971,20 +4971,20 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 4971 | switch (scalar_bits) { | 4971 | switch (scalar_bits) { |
| 4972 | 16, 128 => switch (tag) { | 4972 | 16, 128 => switch (tag) { |
| 4973 | .neg => .{ .p_, .xor }, | 4973 | .neg => .{ .p_, .xor }, |
| 4974 | .fabs => .{ .p_, .@"and" }, | 4974 | .abs => .{ .p_, .@"and" }, |
| 4975 | else => unreachable, | 4975 | else => unreachable, |
| 4976 | }, | 4976 | }, |
| 4977 | 32 => switch (tag) { | 4977 | 32 => switch (tag) { |
| 4978 | .neg => .{ ._ps, .xor }, | 4978 | .neg => .{ ._ps, .xor }, |
| 4979 | .fabs => .{ ._ps, .@"and" }, | 4979 | .abs => .{ ._ps, .@"and" }, |
| 4980 | else => unreachable, | 4980 | else => unreachable, |
| 4981 | }, | 4981 | }, |
| 4982 | 64 => switch (tag) { | 4982 | 64 => switch (tag) { |
| 4983 | .neg => .{ ._pd, .xor }, | 4983 | .neg => .{ ._pd, .xor }, |
| 4984 | .fabs => .{ ._pd, .@"and" }, | 4984 | .abs => .{ ._pd, .@"and" }, |
| 4985 | else => unreachable, | 4985 | else => unreachable, |
| 4986 | }, | 4986 | }, |
| 4987 | 80 => return self.fail("TODO implement airFloatSign for {}", .{ | 4987 | 80 => return self.fail("TODO implement floatSign for {}", .{ |
| 4988 | ty.fmt(self.bin_file.options.module.?), | 4988 | ty.fmt(self.bin_file.options.module.?), |
| 4989 | }), | 4989 | }), |
| 4990 | else => unreachable, | 4990 | else => unreachable, |
| ... | @@ -4992,7 +4992,14 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4992,7 +4992,14 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 4992 | registerAlias(dst_reg, abi_size), | 4992 | registerAlias(dst_reg, abi_size), |
| 4993 | sign_mem, | 4993 | sign_mem, |
| 4994 | ); | 4994 | ); |
| 4995 | return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none }); | 4995 | return self.finishAir(inst, dst_mcv, .{ operand, .none, .none }); |
| 4996 | } | ||
| 4997 | |||
| 4998 | fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { | ||
| 4999 | const un_op = self.air.instructions.items(.data)[inst].un_op; | ||
| 5000 | const ty = self.typeOf(un_op); | ||
| 5001 | |||
| 5002 | return self.floatSign(inst, un_op, ty); | ||
| 4996 | } | 5003 | } |
| 4997 | 5004 | ||
| 4998 | fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void { | 5005 | fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void { |
| ... | @@ -5082,6 +5089,52 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4 | ... | @@ -5082,6 +5089,52 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4 |
| 5082 | } | 5089 | } |
| 5083 | } | 5090 | } |
| 5084 | 5091 | ||
| 5092 | fn airAbs(self: *Self, inst: Air.Inst.Index) !void { | ||
| 5093 | const mod = self.bin_file.options.module.?; | ||
| 5094 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | ||
| 5095 | const ty = self.typeOf(ty_op.operand); | ||
| 5096 | const scalar_ty = ty.scalarType(mod); | ||
| 5097 | |||
| 5098 | switch (scalar_ty.zigTypeTag(mod)) { | ||
| 5099 | .Int => if (ty.zigTypeTag(mod) == .Vector) { | ||
| 5100 | return self.fail("TODO implement airAbs for {}", .{ty.fmt(mod)}); | ||
| 5101 | } else { | ||
| 5102 | if (ty.abiSize(mod) > 8) { | ||
| 5103 | return self.fail("TODO implement abs for integer abi sizes larger than 8", .{}); | ||
| 5104 | } | ||
| 5105 | const src_mcv = try self.resolveInst(ty_op.operand); | ||
| 5106 | const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, src_mcv); | ||
| 5107 | |||
| 5108 | try self.genUnOpMir(.{ ._, .neg }, ty, dst_mcv); | ||
| 5109 | |||
| 5110 | const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2); | ||
| 5111 | switch (src_mcv) { | ||
| 5112 | .register => |val_reg| try self.asmCmovccRegisterRegister( | ||
| 5113 | registerAlias(dst_mcv.register, cmov_abi_size), | ||
| 5114 | registerAlias(val_reg, cmov_abi_size), | ||
| 5115 | .l, | ||
| 5116 | ), | ||
| 5117 | .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory( | ||
| 5118 | registerAlias(dst_mcv.register, cmov_abi_size), | ||
| 5119 | src_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)), | ||
| 5120 | .l, | ||
| 5121 | ), | ||
| 5122 | else => { | ||
| 5123 | const val_reg = try self.copyToTmpRegister(ty, src_mcv); | ||
| 5124 | try self.asmCmovccRegisterRegister( | ||
| 5125 | registerAlias(dst_mcv.register, cmov_abi_size), | ||
| 5126 | registerAlias(val_reg, cmov_abi_size), | ||
| 5127 | .l, | ||
| 5128 | ); | ||
| 5129 | }, | ||
| 5130 | } | ||
| 5131 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); | ||
| 5132 | }, | ||
| 5133 | .Float => return self.floatSign(inst, ty_op.operand, ty), | ||
| 5134 | else => unreachable, | ||
| 5135 | } | ||
| 5136 | } | ||
| 5137 | |||
| 5085 | fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | 5138 | fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5086 | const mod = self.bin_file.options.module.?; | 5139 | const mod = self.bin_file.options.module.?; |
| 5087 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 5140 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
src/arch/x86_64/encoder.zig+2-2| ... | @@ -105,7 +105,7 @@ pub const Instruction = struct { | ... | @@ -105,7 +105,7 @@ pub const Instruction = struct { |
| 105 | try writer.print("{s} ptr [rip", .{@tagName(rip.ptr_size)}); | 105 | try writer.print("{s} ptr [rip", .{@tagName(rip.ptr_size)}); |
| 106 | if (rip.disp != 0) try writer.print(" {c} 0x{x}", .{ | 106 | if (rip.disp != 0) try writer.print(" {c} 0x{x}", .{ |
| 107 | @as(u8, if (rip.disp < 0) '-' else '+'), | 107 | @as(u8, if (rip.disp < 0) '-' else '+'), |
| 108 | std.math.absCast(rip.disp), | 108 | @abs(rip.disp), |
| 109 | }); | 109 | }); |
| 110 | try writer.writeByte(']'); | 110 | try writer.writeByte(']'); |
| 111 | }, | 111 | }, |
| ... | @@ -140,7 +140,7 @@ pub const Instruction = struct { | ... | @@ -140,7 +140,7 @@ pub const Instruction = struct { |
| 140 | try writer.print(" {c} ", .{@as(u8, if (sib.disp < 0) '-' else '+')}) | 140 | try writer.print(" {c} ", .{@as(u8, if (sib.disp < 0) '-' else '+')}) |
| 141 | else if (sib.disp < 0) | 141 | else if (sib.disp < 0) |
| 142 | try writer.writeByte('-'); | 142 | try writer.writeByte('-'); |
| 143 | try writer.print("0x{x}", .{std.math.absCast(sib.disp)}); | 143 | try writer.print("0x{x}", .{@abs(sib.disp)}); |
| 144 | any = true; | 144 | any = true; |
| 145 | } | 145 | } |
| 146 | 146 |
src/codegen/c.zig+32-10| ... | @@ -2912,6 +2912,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -2912,6 +2912,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 2912 | }, | 2912 | }, |
| 2913 | .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none), | 2913 | .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none), |
| 2914 | .mod => try airBinBuiltinCall(f, inst, "mod", .none), | 2914 | .mod => try airBinBuiltinCall(f, inst, "mod", .none), |
| 2915 | .abs => try airAbs(f, inst), | ||
| 2915 | 2916 | ||
| 2916 | .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits), | 2917 | .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits), |
| 2917 | .sub_wrap => try airBinBuiltinCall(f, inst, "subw", .bits), | 2918 | .sub_wrap => try airBinBuiltinCall(f, inst, "subw", .bits), |
| ... | @@ -2931,7 +2932,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -2931,7 +2932,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 2931 | .log => try airUnFloatOp(f, inst, "log"), | 2932 | .log => try airUnFloatOp(f, inst, "log"), |
| 2932 | .log2 => try airUnFloatOp(f, inst, "log2"), | 2933 | .log2 => try airUnFloatOp(f, inst, "log2"), |
| 2933 | .log10 => try airUnFloatOp(f, inst, "log10"), | 2934 | .log10 => try airUnFloatOp(f, inst, "log10"), |
| 2934 | .fabs => try airUnFloatOp(f, inst, "fabs"), | ||
| 2935 | .floor => try airUnFloatOp(f, inst, "floor"), | 2935 | .floor => try airUnFloatOp(f, inst, "floor"), |
| 2936 | .ceil => try airUnFloatOp(f, inst, "ceil"), | 2936 | .ceil => try airUnFloatOp(f, inst, "ceil"), |
| 2937 | .round => try airUnFloatOp(f, inst, "round"), | 2937 | .round => try airUnFloatOp(f, inst, "round"), |
| ... | @@ -7076,23 +7076,35 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7076,23 +7076,35 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7076 | return local; | 7076 | return local; |
| 7077 | } | 7077 | } |
| 7078 | 7078 | ||
| 7079 | fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { | 7079 | fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7080 | const mod = f.object.dg.module; | 7080 | const mod = f.object.dg.module; |
| 7081 | const un_op = f.air.instructions.items(.data)[inst].un_op; | 7081 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 7082 | const operand = try f.resolveInst(ty_op.operand); | ||
| 7083 | const ty = f.typeOf(ty_op.operand); | ||
| 7084 | const scalar_ty = ty.scalarType(mod); | ||
| 7082 | 7085 | ||
| 7083 | const operand = try f.resolveInst(un_op); | 7086 | switch (scalar_ty.zigTypeTag(mod)) { |
| 7084 | try reap(f, inst, &.{un_op}); | 7087 | .Int => if (ty.zigTypeTag(mod) == .Vector) { |
| 7088 | return f.fail("TODO implement airAbs for '{}'", .{ty.fmt(mod)}); | ||
| 7089 | } else { | ||
| 7090 | return airUnBuiltinCall(f, inst, "abs", .none); | ||
| 7091 | }, | ||
| 7092 | .Float => return unFloatOp(f, inst, operand, ty, "fabs"), | ||
| 7093 | else => unreachable, | ||
| 7094 | } | ||
| 7095 | } | ||
| 7085 | 7096 | ||
| 7086 | const inst_ty = f.typeOfIndex(inst); | 7097 | fn unFloatOp(f: *Function, inst: Air.Inst.Index, operand: CValue, ty: Type, operation: []const u8) !CValue { |
| 7087 | const inst_scalar_ty = inst_ty.scalarType(mod); | 7098 | const mod = f.object.dg.module; |
| 7099 | const scalar_ty = ty.scalarType(mod); | ||
| 7088 | 7100 | ||
| 7089 | const writer = f.object.writer(); | 7101 | const writer = f.object.writer(); |
| 7090 | const local = try f.allocLocal(inst, inst_ty); | 7102 | const local = try f.allocLocal(inst, ty); |
| 7091 | const v = try Vectorize.start(f, inst, writer, inst_ty); | 7103 | const v = try Vectorize.start(f, inst, writer, ty); |
| 7092 | try f.writeCValue(writer, local, .Other); | 7104 | try f.writeCValue(writer, local, .Other); |
| 7093 | try v.elem(f, writer); | 7105 | try v.elem(f, writer); |
| 7094 | try writer.writeAll(" = zig_libc_name_"); | 7106 | try writer.writeAll(" = zig_libc_name_"); |
| 7095 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty); | 7107 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); |
| 7096 | try writer.writeByte('('); | 7108 | try writer.writeByte('('); |
| 7097 | try writer.writeAll(operation); | 7109 | try writer.writeAll(operation); |
| 7098 | try writer.writeAll(")("); | 7110 | try writer.writeAll(")("); |
| ... | @@ -7104,6 +7116,16 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal | ... | @@ -7104,6 +7116,16 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal |
| 7104 | return local; | 7116 | return local; |
| 7105 | } | 7117 | } |
| 7106 | 7118 | ||
| 7119 | fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { | ||
| 7120 | const un_op = f.air.instructions.items(.data)[inst].un_op; | ||
| 7121 | |||
| 7122 | const operand = try f.resolveInst(un_op); | ||
| 7123 | try reap(f, inst, &.{un_op}); | ||
| 7124 | |||
| 7125 | const inst_ty = f.typeOfIndex(inst); | ||
| 7126 | return unFloatOp(f, inst, operand, inst_ty, operation); | ||
| 7127 | } | ||
| 7128 | |||
| 7107 | fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { | 7129 | fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { |
| 7108 | const mod = f.object.dg.module; | 7130 | const mod = f.object.dg.module; |
| 7109 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; | 7131 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
src/codegen/llvm.zig+23-1| ... | @@ -4729,6 +4729,7 @@ pub const FuncGen = struct { | ... | @@ -4729,6 +4729,7 @@ pub const FuncGen = struct { |
| 4729 | .div_exact => try self.airDivExact(inst, .normal), | 4729 | .div_exact => try self.airDivExact(inst, .normal), |
| 4730 | .rem => try self.airRem(inst, .normal), | 4730 | .rem => try self.airRem(inst, .normal), |
| 4731 | .mod => try self.airMod(inst, .normal), | 4731 | .mod => try self.airMod(inst, .normal), |
| 4732 | .abs => try self.airAbs(inst), | ||
| 4732 | .ptr_add => try self.airPtrAdd(inst), | 4733 | .ptr_add => try self.airPtrAdd(inst), |
| 4733 | .ptr_sub => try self.airPtrSub(inst), | 4734 | .ptr_sub => try self.airPtrSub(inst), |
| 4734 | .shl => try self.airShl(inst), | 4735 | .shl => try self.airShl(inst), |
| ... | @@ -4766,7 +4767,6 @@ pub const FuncGen = struct { | ... | @@ -4766,7 +4767,6 @@ pub const FuncGen = struct { |
| 4766 | .log => try self.airUnaryOp(inst, .log), | 4767 | .log => try self.airUnaryOp(inst, .log), |
| 4767 | .log2 => try self.airUnaryOp(inst, .log2), | 4768 | .log2 => try self.airUnaryOp(inst, .log2), |
| 4768 | .log10 => try self.airUnaryOp(inst, .log10), | 4769 | .log10 => try self.airUnaryOp(inst, .log10), |
| 4769 | .fabs => try self.airUnaryOp(inst, .fabs), | ||
| 4770 | .floor => try self.airUnaryOp(inst, .floor), | 4770 | .floor => try self.airUnaryOp(inst, .floor), |
| 4771 | .ceil => try self.airUnaryOp(inst, .ceil), | 4771 | .ceil => try self.airUnaryOp(inst, .ceil), |
| 4772 | .round => try self.airUnaryOp(inst, .round), | 4772 | .round => try self.airUnaryOp(inst, .round), |
| ... | @@ -8237,6 +8237,28 @@ pub const FuncGen = struct { | ... | @@ -8237,6 +8237,28 @@ pub const FuncGen = struct { |
| 8237 | else if (is_signed_int) .ashr else .lshr, lhs, casted_rhs, ""); | 8237 | else if (is_signed_int) .ashr else .lshr, lhs, casted_rhs, ""); |
| 8238 | } | 8238 | } |
| 8239 | 8239 | ||
| 8240 | fn airAbs(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { | ||
| 8241 | const o = self.dg.object; | ||
| 8242 | const mod = o.module; | ||
| 8243 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | ||
| 8244 | const operand = try self.resolveInst(ty_op.operand); | ||
| 8245 | const operand_ty = self.typeOf(ty_op.operand); | ||
| 8246 | const scalar_ty = operand_ty.scalarType(mod); | ||
| 8247 | |||
| 8248 | switch (scalar_ty.zigTypeTag(mod)) { | ||
| 8249 | .Int => return self.wip.callIntrinsic( | ||
| 8250 | .normal, | ||
| 8251 | .none, | ||
| 8252 | .abs, | ||
| 8253 | &.{try o.lowerType(operand_ty)}, | ||
| 8254 | &.{ operand, try o.builder.intValue(.i1, 0) }, | ||
| 8255 | "", | ||
| 8256 | ), | ||
| 8257 | .Float => return self.buildFloatOp(.fabs, .normal, operand_ty, 1, .{operand}), | ||
| 8258 | else => unreachable, | ||
| 8259 | } | ||
| 8260 | } | ||
| 8261 | |||
| 8240 | fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { | 8262 | fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8241 | const o = self.dg.object; | 8263 | const o = self.dg.object; |
| 8242 | const mod = o.module; | 8264 | const mod = o.module; |
src/print_air.zig+1-1| ... | @@ -188,7 +188,7 @@ const Writer = struct { | ... | @@ -188,7 +188,7 @@ const Writer = struct { |
| 188 | .log, | 188 | .log, |
| 189 | .log2, | 189 | .log2, |
| 190 | .log10, | 190 | .log10, |
| 191 | .fabs, | 191 | .abs, |
| 192 | .floor, | 192 | .floor, |
| 193 | .ceil, | 193 | .ceil, |
| 194 | .round, | 194 | .round, |
src/print_zir.zig+1-1| ... | @@ -262,7 +262,7 @@ const Writer = struct { | ... | @@ -262,7 +262,7 @@ const Writer = struct { |
| 262 | .log, | 262 | .log, |
| 263 | .log2, | 263 | .log2, |
| 264 | .log10, | 264 | .log10, |
| 265 | .fabs, | 265 | .abs, |
| 266 | .floor, | 266 | .floor, |
| 267 | .ceil, | 267 | .ceil, |
| 268 | .trunc, | 268 | .trunc, |
src/type.zig+11| ... | @@ -3197,6 +3197,17 @@ pub const Type = struct { | ... | @@ -3197,6 +3197,17 @@ pub const Type = struct { |
| 3197 | }; | 3197 | }; |
| 3198 | } | 3198 | } |
| 3199 | 3199 | ||
| 3200 | pub fn toUnsigned(ty: Type, mod: *Module) !Type { | ||
| 3201 | return switch (ty.zigTypeTag(mod)) { | ||
| 3202 | .Int => mod.intType(.unsigned, ty.intInfo(mod).bits), | ||
| 3203 | .Vector => try mod.vectorType(.{ | ||
| 3204 | .len = ty.vectorLen(mod), | ||
| 3205 | .child = (try ty.childType(mod).toUnsigned(mod)).toIntern(), | ||
| 3206 | }), | ||
| 3207 | else => unreachable, | ||
| 3208 | }; | ||
| 3209 | } | ||
| 3210 | |||
| 3200 | pub const @"u1": Type = .{ .ip_index = .u1_type }; | 3211 | pub const @"u1": Type = .{ .ip_index = .u1_type }; |
| 3201 | pub const @"u8": Type = .{ .ip_index = .u8_type }; | 3212 | pub const @"u8": Type = .{ .ip_index = .u8_type }; |
| 3202 | pub const @"u16": Type = .{ .ip_index = .u16_type }; | 3213 | pub const @"u16": Type = .{ .ip_index = .u16_type }; |
src/value.zig+40-21| ... | @@ -1993,7 +1993,7 @@ pub const Value = struct { | ... | @@ -1993,7 +1993,7 @@ pub const Value = struct { |
| 1993 | return 1; | 1993 | return 1; |
| 1994 | } | 1994 | } |
| 1995 | 1995 | ||
| 1996 | const w_value = @fabs(scalar); | 1996 | const w_value = @abs(scalar); |
| 1997 | return @divFloor(@as(std.math.big.Limb, @intFromFloat(std.math.log2(w_value))), @typeInfo(std.math.big.Limb).Int.bits) + 1; | 1997 | return @divFloor(@as(std.math.big.Limb, @intFromFloat(std.math.log2(w_value))), @typeInfo(std.math.big.Limb).Int.bits) + 1; |
| 1998 | } | 1998 | } |
| 1999 | 1999 | ||
| ... | @@ -3710,36 +3710,55 @@ pub const Value = struct { | ... | @@ -3710,36 +3710,55 @@ pub const Value = struct { |
| 3710 | } })).toValue(); | 3710 | } })).toValue(); |
| 3711 | } | 3711 | } |
| 3712 | 3712 | ||
| 3713 | pub fn fabs(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 3713 | pub fn abs(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value { |
| 3714 | if (float_type.zigTypeTag(mod) == .Vector) { | 3714 | if (ty.zigTypeTag(mod) == .Vector) { |
| 3715 | const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod)); | 3715 | const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod)); |
| 3716 | const scalar_ty = float_type.scalarType(mod); | 3716 | const scalar_ty = ty.scalarType(mod); |
| 3717 | for (result_data, 0..) |*scalar, i| { | 3717 | for (result_data, 0..) |*scalar, i| { |
| 3718 | const elem_val = try val.elemValue(mod, i); | 3718 | const elem_val = try val.elemValue(mod, i); |
| 3719 | scalar.* = try (try fabsScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); | 3719 | scalar.* = try (try absScalar(elem_val, scalar_ty, mod, arena)).intern(scalar_ty, mod); |
| 3720 | } | 3720 | } |
| 3721 | return (try mod.intern(.{ .aggregate = .{ | 3721 | return (try mod.intern(.{ .aggregate = .{ |
| 3722 | .ty = float_type.toIntern(), | 3722 | .ty = ty.toIntern(), |
| 3723 | .storage = .{ .elems = result_data }, | 3723 | .storage = .{ .elems = result_data }, |
| 3724 | } })).toValue(); | 3724 | } })).toValue(); |
| 3725 | } | 3725 | } |
| 3726 | return fabsScalar(val, float_type, mod); | 3726 | return absScalar(val, ty, mod, arena); |
| 3727 | } | 3727 | } |
| 3728 | 3728 | ||
| 3729 | pub fn fabsScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value { | 3729 | pub fn absScalar(val: Value, ty: Type, mod: *Module, arena: Allocator) Allocator.Error!Value { |
| 3730 | const target = mod.getTarget(); | 3730 | switch (ty.zigTypeTag(mod)) { |
| 3731 | const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) { | 3731 | .Int => { |
| 3732 | 16 => .{ .f16 = @fabs(val.toFloat(f16, mod)) }, | 3732 | var buffer: Value.BigIntSpace = undefined; |
| 3733 | 32 => .{ .f32 = @fabs(val.toFloat(f32, mod)) }, | 3733 | var operand_bigint = try val.toBigInt(&buffer, mod).toManaged(arena); |
| 3734 | 64 => .{ .f64 = @fabs(val.toFloat(f64, mod)) }, | 3734 | operand_bigint.abs(); |
| 3735 | 80 => .{ .f80 = @fabs(val.toFloat(f80, mod)) }, | 3735 | |
| 3736 | 128 => .{ .f128 = @fabs(val.toFloat(f128, mod)) }, | 3736 | return mod.intValue_big(try ty.toUnsigned(mod), operand_bigint.toConst()); |
| 3737 | }, | ||
| 3738 | .ComptimeInt => { | ||
| 3739 | var buffer: Value.BigIntSpace = undefined; | ||
| 3740 | var operand_bigint = try val.toBigInt(&buffer, mod).toManaged(arena); | ||
| 3741 | operand_bigint.abs(); | ||
| 3742 | |||
| 3743 | return mod.intValue_big(ty, operand_bigint.toConst()); | ||
| 3744 | }, | ||
| 3745 | .ComptimeFloat, .Float => { | ||
| 3746 | const target = mod.getTarget(); | ||
| 3747 | const storage: InternPool.Key.Float.Storage = switch (ty.floatBits(target)) { | ||
| 3748 | 16 => .{ .f16 = @abs(val.toFloat(f16, mod)) }, | ||
| 3749 | 32 => .{ .f32 = @abs(val.toFloat(f32, mod)) }, | ||
| 3750 | 64 => .{ .f64 = @abs(val.toFloat(f64, mod)) }, | ||
| 3751 | 80 => .{ .f80 = @abs(val.toFloat(f80, mod)) }, | ||
| 3752 | 128 => .{ .f128 = @abs(val.toFloat(f128, mod)) }, | ||
| 3753 | else => unreachable, | ||
| 3754 | }; | ||
| 3755 | return (try mod.intern(.{ .float = .{ | ||
| 3756 | .ty = ty.toIntern(), | ||
| 3757 | .storage = storage, | ||
| 3758 | } })).toValue(); | ||
| 3759 | }, | ||
| 3737 | else => unreachable, | 3760 | else => unreachable, |
| 3738 | }; | 3761 | } |
| 3739 | return (try mod.intern(.{ .float = .{ | ||
| 3740 | .ty = float_type.toIntern(), | ||
| 3741 | .storage = storage, | ||
| 3742 | } })).toValue(); | ||
| 3743 | } | 3762 | } |
| 3744 | 3763 | ||
| 3745 | pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { | 3764 | pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value { |
stage1/zig.h+41| ... | @@ -946,6 +946,24 @@ typedef unsigned long zig_Builtin64; | ... | @@ -946,6 +946,24 @@ typedef unsigned long zig_Builtin64; |
| 946 | typedef unsigned long long zig_Builtin64; | 946 | typedef unsigned long long zig_Builtin64; |
| 947 | #endif | 947 | #endif |
| 948 | 948 | ||
| 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 | |||
| 949 | static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) { | 967 | static 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) |
| 1141 | zig_builtin_clz(32) | 1159 | zig_builtin_clz(32) |
| 1142 | zig_builtin_clz(64) | 1160 | zig_builtin_clz(64) |
| 1143 | 1161 | ||
| 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 | ||
| 1175 | zig_builtin_abs(8) | ||
| 1176 | zig_builtin_abs(16) | ||
| 1177 | zig_builtin_abs(32) | ||
| 1178 | zig_builtin_abs(64) | ||
| 1179 | |||
| 1144 | /* ======================== 128-bit Integer Support ========================= */ | 1180 | /* ======================== 128-bit Integer Support ========================= */ |
| 1145 | 1181 | ||
| 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 | } |
| 1468 | 1504 | ||
| 1505 | static 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_int128 | 1510 | #if zig_has_int128 |
| 1470 | 1511 | ||
| 1471 | static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { | 1512 | static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { |
stage1/zig1.wasm| Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ | |||
test/behavior.zig+1| ... | @@ -237,6 +237,7 @@ test { | ... | @@ -237,6 +237,7 @@ test { |
| 237 | _ = @import("behavior/void.zig"); | 237 | _ = @import("behavior/void.zig"); |
| 238 | _ = @import("behavior/while.zig"); | 238 | _ = @import("behavior/while.zig"); |
| 239 | _ = @import("behavior/widening.zig"); | 239 | _ = @import("behavior/widening.zig"); |
| 240 | _ = @import("behavior/abs.zig"); | ||
| 240 | 241 | ||
| 241 | if (builtin.cpu.arch == .wasm32) { | 242 | if (builtin.cpu.arch == .wasm32) { |
| 242 | _ = @import("behavior/wasm.zig"); | 243 | _ = @import("behavior/wasm.zig"); |
test/behavior/abs.zig created+371| ... | @@ -0,0 +1,371 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std"); | ||
| 3 | const expect = std.testing.expect; | ||
| 4 | |||
| 5 | test "@abs integers" { | ||
| 6 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 7 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 8 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | ||
| 9 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | ||
| 10 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 11 | |||
| 12 | try comptime testAbsIntegers(); | ||
| 13 | try testAbsIntegers(); | ||
| 14 | } | ||
| 15 | |||
| 16 | fn testAbsIntegers() !void { | ||
| 17 | { | ||
| 18 | var x: i32 = -1000; | ||
| 19 | try expect(@abs(x) == 1000); | ||
| 20 | } | ||
| 21 | { | ||
| 22 | var x: i32 = 0; | ||
| 23 | try expect(@abs(x) == 0); | ||
| 24 | } | ||
| 25 | { | ||
| 26 | var x: i32 = 1000; | ||
| 27 | try expect(@abs(x) == 1000); | ||
| 28 | } | ||
| 29 | { | ||
| 30 | var x: i64 = std.math.minInt(i64); | ||
| 31 | try expect(@abs(x) == @as(u64, -std.math.minInt(i64))); | ||
| 32 | } | ||
| 33 | { | ||
| 34 | var x: i5 = -1; | ||
| 35 | try expect(@abs(x) == 1); | ||
| 36 | } | ||
| 37 | { | ||
| 38 | var x: i5 = -5; | ||
| 39 | try expect(@abs(x) == 5); | ||
| 40 | } | ||
| 41 | comptime { | ||
| 42 | try expect(@abs(@as(i2, -2)) == 2); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | test "@abs unsigned integers" { | ||
| 47 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 48 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 49 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | ||
| 50 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | ||
| 51 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 52 | |||
| 53 | try comptime testAbsUnsignedIntegers(); | ||
| 54 | try testAbsUnsignedIntegers(); | ||
| 55 | } | ||
| 56 | |||
| 57 | fn testAbsUnsignedIntegers() !void { | ||
| 58 | { | ||
| 59 | var x: u32 = 1000; | ||
| 60 | try expect(@abs(x) == 1000); | ||
| 61 | } | ||
| 62 | { | ||
| 63 | var x: u32 = 0; | ||
| 64 | try expect(@abs(x) == 0); | ||
| 65 | } | ||
| 66 | { | ||
| 67 | var x: u32 = 1000; | ||
| 68 | try expect(@abs(x) == 1000); | ||
| 69 | } | ||
| 70 | { | ||
| 71 | var x: u5 = 1; | ||
| 72 | try expect(@abs(x) == 1); | ||
| 73 | } | ||
| 74 | { | ||
| 75 | var x: u5 = 5; | ||
| 76 | try expect(@abs(x) == 5); | ||
| 77 | } | ||
| 78 | comptime { | ||
| 79 | try expect(@abs(@as(u2, 2)) == 2); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | test "@abs floats" { | ||
| 84 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 85 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 86 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | ||
| 87 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | ||
| 88 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 89 | |||
| 90 | try comptime testAbsFloats(f16); | ||
| 91 | if (builtin.zig_backend != .stage2_x86_64) try testAbsFloats(f16); | ||
| 92 | try comptime testAbsFloats(f32); | ||
| 93 | try testAbsFloats(f32); | ||
| 94 | try comptime testAbsFloats(f64); | ||
| 95 | try testAbsFloats(f64); | ||
| 96 | try comptime testAbsFloats(f80); | ||
| 97 | if (builtin.zig_backend != .stage2_x86_64 and builtin.zig_backend != .stage2_wasm) try testAbsFloats(f80); | ||
| 98 | try comptime testAbsFloats(f128); | ||
| 99 | if (builtin.zig_backend != .stage2_x86_64 and builtin.zig_backend != .stage2_wasm) try testAbsFloats(f128); | ||
| 100 | } | ||
| 101 | |||
| 102 | fn testAbsFloats(comptime T: type) !void { | ||
| 103 | { | ||
| 104 | var x: T = -2.62; | ||
| 105 | try expect(@abs(x) == 2.62); | ||
| 106 | } | ||
| 107 | { | ||
| 108 | var x: T = 2.62; | ||
| 109 | try expect(@abs(x) == 2.62); | ||
| 110 | } | ||
| 111 | { | ||
| 112 | var x: T = 0.0; | ||
| 113 | try expect(@abs(x) == 0.0); | ||
| 114 | } | ||
| 115 | { | ||
| 116 | var x: T = -std.math.pi; | ||
| 117 | try expect(@abs(x) == std.math.pi); | ||
| 118 | } | ||
| 119 | |||
| 120 | { | ||
| 121 | var x: T = -std.math.inf(T); | ||
| 122 | try expect(@abs(x) == std.math.inf(T)); | ||
| 123 | } | ||
| 124 | { | ||
| 125 | var x: T = std.math.inf(T); | ||
| 126 | try expect(@abs(x) == std.math.inf(T)); | ||
| 127 | } | ||
| 128 | comptime { | ||
| 129 | try expect(@abs(@as(T, -std.math.e)) == std.math.e); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | test "@abs int vectors" { | ||
| 134 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 135 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 136 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 137 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 138 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 139 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | ||
| 140 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | ||
| 141 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 142 | |||
| 143 | try comptime testAbsIntVectors(1); | ||
| 144 | try testAbsIntVectors(1); | ||
| 145 | try comptime testAbsIntVectors(2); | ||
| 146 | try testAbsIntVectors(2); | ||
| 147 | try comptime testAbsIntVectors(3); | ||
| 148 | try testAbsIntVectors(3); | ||
| 149 | try comptime testAbsIntVectors(4); | ||
| 150 | try testAbsIntVectors(4); | ||
| 151 | try comptime testAbsIntVectors(8); | ||
| 152 | try testAbsIntVectors(8); | ||
| 153 | try comptime testAbsIntVectors(16); | ||
| 154 | try testAbsIntVectors(16); | ||
| 155 | try comptime testAbsIntVectors(17); | ||
| 156 | try testAbsIntVectors(17); | ||
| 157 | } | ||
| 158 | |||
| 159 | fn testAbsIntVectors(comptime len: comptime_int) !void { | ||
| 160 | const I32 = @Vector(len, i32); | ||
| 161 | const U32 = @Vector(len, u32); | ||
| 162 | const I64 = @Vector(len, i64); | ||
| 163 | const U64 = @Vector(len, u64); | ||
| 164 | { | ||
| 165 | var x: I32 = @splat(-10); | ||
| 166 | var y: U32 = @splat(10); | ||
| 167 | try expect(std.mem.eql(u32, &@as([len]u32, y), &@as([len]u32, @abs(x)))); | ||
| 168 | } | ||
| 169 | { | ||
| 170 | var x: I32 = @splat(10); | ||
| 171 | var y: U32 = @splat(10); | ||
| 172 | try expect(std.mem.eql(u32, &@as([len]u32, y), &@as([len]u32, @abs(x)))); | ||
| 173 | } | ||
| 174 | { | ||
| 175 | var x: I32 = @splat(0); | ||
| 176 | var y: U32 = @splat(0); | ||
| 177 | try expect(std.mem.eql(u32, &@as([len]u32, y), &@as([len]u32, @abs(x)))); | ||
| 178 | } | ||
| 179 | { | ||
| 180 | var x: I64 = @splat(-10); | ||
| 181 | var y: U64 = @splat(10); | ||
| 182 | try expect(std.mem.eql(u64, &@as([len]u64, y), &@as([len]u64, @abs(x)))); | ||
| 183 | } | ||
| 184 | { | ||
| 185 | var x: I64 = @splat(std.math.minInt(i64)); | ||
| 186 | var y: U64 = @splat(-std.math.minInt(i64)); | ||
| 187 | try expect(std.mem.eql(u64, &@as([len]u64, y), &@as([len]u64, @abs(x)))); | ||
| 188 | } | ||
| 189 | { | ||
| 190 | var x = std.simd.repeat(len, @Vector(4, i32){ -2, 5, std.math.minInt(i32), -7 }); | ||
| 191 | var y = std.simd.repeat(len, @Vector(4, u32){ 2, 5, -std.math.minInt(i32), 7 }); | ||
| 192 | try expect(std.mem.eql(u32, &@as([len]u32, y), &@as([len]u32, @abs(x)))); | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | test "@abs unsigned int vectors" { | ||
| 197 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 198 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 199 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 200 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 201 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 202 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | ||
| 203 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | ||
| 204 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 205 | |||
| 206 | try comptime testAbsUnsignedIntVectors(1); | ||
| 207 | try testAbsUnsignedIntVectors(1); | ||
| 208 | try comptime testAbsUnsignedIntVectors(2); | ||
| 209 | try testAbsUnsignedIntVectors(2); | ||
| 210 | try comptime testAbsUnsignedIntVectors(3); | ||
| 211 | try testAbsUnsignedIntVectors(3); | ||
| 212 | try comptime testAbsUnsignedIntVectors(4); | ||
| 213 | try testAbsUnsignedIntVectors(4); | ||
| 214 | try comptime testAbsUnsignedIntVectors(8); | ||
| 215 | try testAbsUnsignedIntVectors(8); | ||
| 216 | try comptime testAbsUnsignedIntVectors(16); | ||
| 217 | try testAbsUnsignedIntVectors(16); | ||
| 218 | try comptime testAbsUnsignedIntVectors(17); | ||
| 219 | try testAbsUnsignedIntVectors(17); | ||
| 220 | } | ||
| 221 | |||
| 222 | fn testAbsUnsignedIntVectors(comptime len: comptime_int) !void { | ||
| 223 | const U32 = @Vector(len, u32); | ||
| 224 | const U64 = @Vector(len, u64); | ||
| 225 | { | ||
| 226 | var x: U32 = @splat(10); | ||
| 227 | var y: U32 = @splat(10); | ||
| 228 | try expect(std.mem.eql(u32, &@as([len]u32, y), &@as([len]u32, @abs(x)))); | ||
| 229 | } | ||
| 230 | { | ||
| 231 | var x: U32 = @splat(10); | ||
| 232 | var y: U32 = @splat(10); | ||
| 233 | try expect(std.mem.eql(u32, &@as([len]u32, y), &@as([len]u32, @abs(x)))); | ||
| 234 | } | ||
| 235 | { | ||
| 236 | var x: U32 = @splat(0); | ||
| 237 | var y: U32 = @splat(0); | ||
| 238 | try expect(std.mem.eql(u32, &@as([len]u32, y), &@as([len]u32, @abs(x)))); | ||
| 239 | } | ||
| 240 | { | ||
| 241 | var x: U64 = @splat(10); | ||
| 242 | var y: U64 = @splat(10); | ||
| 243 | try expect(std.mem.eql(u64, &@as([len]u64, y), &@as([len]u64, @abs(x)))); | ||
| 244 | } | ||
| 245 | { | ||
| 246 | var x = std.simd.repeat(len, @Vector(3, u32){ 2, 5, 7 }); | ||
| 247 | var y = std.simd.repeat(len, @Vector(3, u32){ 2, 5, 7 }); | ||
| 248 | try expect(std.mem.eql(u32, &@as([len]u32, y), &@as([len]u32, @abs(x)))); | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | test "@abs float vectors" { | ||
| 253 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 254 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 255 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 256 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 257 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 258 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | ||
| 259 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | ||
| 260 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 261 | |||
| 262 | // https://github.com/ziglang/zig/issues/12827 | ||
| 263 | if (builtin.zig_backend == .stage2_llvm and | ||
| 264 | builtin.os.tag == .macos and | ||
| 265 | builtin.target.cpu.arch == .x86_64) return error.SkipZigTest; | ||
| 266 | |||
| 267 | @setEvalBranchQuota(2000); | ||
| 268 | try comptime testAbsFloatVectors(f16, 1); | ||
| 269 | try testAbsFloatVectors(f16, 1); | ||
| 270 | try comptime testAbsFloatVectors(f16, 2); | ||
| 271 | try testAbsFloatVectors(f16, 2); | ||
| 272 | try comptime testAbsFloatVectors(f16, 3); | ||
| 273 | try testAbsFloatVectors(f16, 3); | ||
| 274 | try comptime testAbsFloatVectors(f16, 4); | ||
| 275 | try testAbsFloatVectors(f16, 4); | ||
| 276 | try comptime testAbsFloatVectors(f16, 8); | ||
| 277 | try testAbsFloatVectors(f16, 8); | ||
| 278 | try comptime testAbsFloatVectors(f16, 16); | ||
| 279 | try testAbsFloatVectors(f16, 16); | ||
| 280 | try comptime testAbsFloatVectors(f16, 17); | ||
| 281 | |||
| 282 | try testAbsFloatVectors(f32, 17); | ||
| 283 | try comptime testAbsFloatVectors(f32, 1); | ||
| 284 | try testAbsFloatVectors(f32, 1); | ||
| 285 | try comptime testAbsFloatVectors(f32, 2); | ||
| 286 | try testAbsFloatVectors(f32, 2); | ||
| 287 | try comptime testAbsFloatVectors(f32, 3); | ||
| 288 | try testAbsFloatVectors(f32, 3); | ||
| 289 | try comptime testAbsFloatVectors(f32, 4); | ||
| 290 | try testAbsFloatVectors(f32, 4); | ||
| 291 | try comptime testAbsFloatVectors(f32, 8); | ||
| 292 | try testAbsFloatVectors(f32, 8); | ||
| 293 | try comptime testAbsFloatVectors(f32, 16); | ||
| 294 | try testAbsFloatVectors(f32, 16); | ||
| 295 | try comptime testAbsFloatVectors(f32, 17); | ||
| 296 | try testAbsFloatVectors(f32, 17); | ||
| 297 | |||
| 298 | try comptime testAbsFloatVectors(f64, 1); | ||
| 299 | try testAbsFloatVectors(f64, 1); | ||
| 300 | try comptime testAbsFloatVectors(f64, 2); | ||
| 301 | try testAbsFloatVectors(f64, 2); | ||
| 302 | try comptime testAbsFloatVectors(f64, 3); | ||
| 303 | try testAbsFloatVectors(f64, 3); | ||
| 304 | try comptime testAbsFloatVectors(f64, 4); | ||
| 305 | try testAbsFloatVectors(f64, 4); | ||
| 306 | try comptime testAbsFloatVectors(f64, 8); | ||
| 307 | try testAbsFloatVectors(f64, 8); | ||
| 308 | try comptime testAbsFloatVectors(f64, 16); | ||
| 309 | try testAbsFloatVectors(f64, 16); | ||
| 310 | try comptime testAbsFloatVectors(f64, 17); | ||
| 311 | try testAbsFloatVectors(f64, 17); | ||
| 312 | |||
| 313 | try comptime testAbsFloatVectors(f80, 1); | ||
| 314 | try testAbsFloatVectors(f80, 1); | ||
| 315 | try comptime testAbsFloatVectors(f80, 2); | ||
| 316 | try testAbsFloatVectors(f80, 2); | ||
| 317 | try comptime testAbsFloatVectors(f80, 3); | ||
| 318 | try testAbsFloatVectors(f80, 3); | ||
| 319 | try comptime testAbsFloatVectors(f80, 4); | ||
| 320 | try testAbsFloatVectors(f80, 4); | ||
| 321 | try comptime testAbsFloatVectors(f80, 8); | ||
| 322 | try testAbsFloatVectors(f80, 8); | ||
| 323 | try comptime testAbsFloatVectors(f80, 16); | ||
| 324 | try testAbsFloatVectors(f80, 16); | ||
| 325 | try comptime testAbsFloatVectors(f80, 17); | ||
| 326 | try testAbsFloatVectors(f80, 17); | ||
| 327 | |||
| 328 | try comptime testAbsFloatVectors(f128, 1); | ||
| 329 | try testAbsFloatVectors(f128, 1); | ||
| 330 | try comptime testAbsFloatVectors(f128, 2); | ||
| 331 | try testAbsFloatVectors(f128, 2); | ||
| 332 | try comptime testAbsFloatVectors(f128, 3); | ||
| 333 | try testAbsFloatVectors(f128, 3); | ||
| 334 | try comptime testAbsFloatVectors(f128, 4); | ||
| 335 | try testAbsFloatVectors(f128, 4); | ||
| 336 | try comptime testAbsFloatVectors(f128, 8); | ||
| 337 | try testAbsFloatVectors(f128, 8); | ||
| 338 | try comptime testAbsFloatVectors(f128, 16); | ||
| 339 | try testAbsFloatVectors(f128, 16); | ||
| 340 | try comptime testAbsFloatVectors(f128, 17); | ||
| 341 | try testAbsFloatVectors(f128, 17); | ||
| 342 | } | ||
| 343 | |||
| 344 | fn testAbsFloatVectors(comptime T: type, comptime len: comptime_int) !void { | ||
| 345 | const V = @Vector(len, T); | ||
| 346 | { | ||
| 347 | var x: V = @splat(-7.5); | ||
| 348 | var y: V = @splat(7.5); | ||
| 349 | try expect(std.mem.eql(T, &@as([len]T, y), &@as([len]T, @abs(x)))); | ||
| 350 | } | ||
| 351 | { | ||
| 352 | var x: V = @splat(7.5); | ||
| 353 | var y: V = @splat(7.5); | ||
| 354 | try expect(std.mem.eql(T, &@as([len]T, y), &@as([len]T, @abs(x)))); | ||
| 355 | } | ||
| 356 | { | ||
| 357 | var x: V = @splat(0.0); | ||
| 358 | var y: V = @splat(0.0); | ||
| 359 | try expect(std.mem.eql(T, &@as([len]T, y), &@as([len]T, @abs(x)))); | ||
| 360 | } | ||
| 361 | { | ||
| 362 | var x: V = @splat(-std.math.pi); | ||
| 363 | var y: V = @splat(std.math.pi); | ||
| 364 | try expect(std.mem.eql(T, &@as([len]T, y), &@as([len]T, @abs(x)))); | ||
| 365 | } | ||
| 366 | { | ||
| 367 | var x: V = @splat(std.math.pi); | ||
| 368 | var y: V = @splat(std.math.pi); | ||
| 369 | try expect(std.mem.eql(T, &@as([len]T, y), &@as([len]T, @abs(x)))); | ||
| 370 | } | ||
| 371 | } | ||
test/behavior/floatop.zig+36-33| ... | @@ -523,7 +523,7 @@ fn testLog10WithVectors() !void { | ... | @@ -523,7 +523,7 @@ fn testLog10WithVectors() !void { |
| 523 | try expect(@log10(@as(f32, 0.4)) == result[3]); | 523 | try expect(@log10(@as(f32, 0.4)) == result[3]); |
| 524 | } | 524 | } |
| 525 | 525 | ||
| 526 | test "@fabs" { | 526 | test "@abs" { |
| 527 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 527 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 528 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 528 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 529 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 529 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | @@ -533,24 +533,24 @@ test "@fabs" { | ... | @@ -533,24 +533,24 @@ test "@fabs" { |
| 533 | } | 533 | } |
| 534 | 534 | ||
| 535 | fn testFabs() !void { | 535 | fn testFabs() !void { |
| 536 | try expect(@fabs(@as(f16, -2.5)) == 2.5); | 536 | try expect(@abs(@as(f16, -2.5)) == 2.5); |
| 537 | try expect(@fabs(@as(f16, 2.5)) == 2.5); | 537 | try expect(@abs(@as(f16, 2.5)) == 2.5); |
| 538 | try expect(@fabs(@as(f32, -2.5)) == 2.5); | 538 | try expect(@abs(@as(f32, -2.5)) == 2.5); |
| 539 | try expect(@fabs(@as(f32, 2.5)) == 2.5); | 539 | try expect(@abs(@as(f32, 2.5)) == 2.5); |
| 540 | try expect(@fabs(@as(f64, -2.5)) == 2.5); | 540 | try expect(@abs(@as(f64, -2.5)) == 2.5); |
| 541 | try expect(@fabs(@as(f64, 2.5)) == 2.5); | 541 | try expect(@abs(@as(f64, 2.5)) == 2.5); |
| 542 | 542 | ||
| 543 | // TODO test f128, and c_longdouble | 543 | // TODO test f128, and c_longdouble |
| 544 | // https://github.com/ziglang/zig/issues/4026 | 544 | // https://github.com/ziglang/zig/issues/4026 |
| 545 | // { | 545 | // { |
| 546 | // var a: f80 = -2.5; | 546 | // var a: f80 = -2.5; |
| 547 | // var b: f80 = 2.5; | 547 | // var b: f80 = 2.5; |
| 548 | // try expect(@fabs(a) == 2.5); | 548 | // try expect(@abs(a) == 2.5); |
| 549 | // try expect(@fabs(b) == 2.5); | 549 | // try expect(@abs(b) == 2.5); |
| 550 | // } | 550 | // } |
| 551 | } | 551 | } |
| 552 | 552 | ||
| 553 | test "@fabs with vectors" { | 553 | test "@abs with vectors" { |
| 554 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 554 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 555 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 555 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 556 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 556 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| ... | @@ -562,14 +562,15 @@ test "@fabs with vectors" { | ... | @@ -562,14 +562,15 @@ test "@fabs with vectors" { |
| 562 | 562 | ||
| 563 | fn testFabsWithVectors() !void { | 563 | fn testFabsWithVectors() !void { |
| 564 | var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; | 564 | var v: @Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; |
| 565 | var result = @fabs(v); | 565 | var result = @abs(v); |
| 566 | try expect(math.approxEqAbs(f32, @fabs(@as(f32, 1.1)), result[0], epsilon)); | 566 | try expect(math.approxEqAbs(f32, @abs(@as(f32, 1.1)), result[0], epsilon)); |
| 567 | try expect(math.approxEqAbs(f32, @fabs(@as(f32, -2.2)), result[1], epsilon)); | 567 | try expect(math.approxEqAbs(f32, @abs(@as(f32, -2.2)), result[1], epsilon)); |
| 568 | try expect(math.approxEqAbs(f32, @fabs(@as(f32, 0.3)), result[2], epsilon)); | 568 | try expect(math.approxEqAbs(f32, @abs(@as(f32, 0.3)), result[2], epsilon)); |
| 569 | try expect(math.approxEqAbs(f32, @fabs(@as(f32, -0.4)), result[3], epsilon)); | 569 | try expect(math.approxEqAbs(f32, @abs(@as(f32, -0.4)), result[3], epsilon)); |
| 570 | } | 570 | } |
| 571 | 571 | ||
| 572 | test "another, possibly redundant, @fabs test" { | 572 | test "another, possibly redundant, @abs test" { |
| 573 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 573 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 574 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 574 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 575 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 575 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 576 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| ... | @@ -587,11 +588,12 @@ test "another, possibly redundant, @fabs test" { | ... | @@ -587,11 +588,12 @@ test "another, possibly redundant, @fabs test" { |
| 587 | 588 | ||
| 588 | const x = 14.0; | 589 | const x = 14.0; |
| 589 | const y = -x; | 590 | const y = -x; |
| 590 | const z = @fabs(y); | 591 | const z = @abs(y); |
| 591 | try comptime std.testing.expectEqual(x, z); | 592 | try comptime std.testing.expectEqual(x, z); |
| 592 | } | 593 | } |
| 593 | 594 | ||
| 594 | test "@fabs f80" { | 595 | test "@abs f80" { |
| 596 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 595 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 597 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 596 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 598 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 597 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 599 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| ... | @@ -604,11 +606,12 @@ test "@fabs f80" { | ... | @@ -604,11 +606,12 @@ test "@fabs f80" { |
| 604 | 606 | ||
| 605 | fn testFabsLegacy(comptime T: type, x: T) !void { | 607 | fn testFabsLegacy(comptime T: type, x: T) !void { |
| 606 | const y = -x; | 608 | const y = -x; |
| 607 | const z = @fabs(y); | 609 | const z = @abs(y); |
| 608 | try expect(x == z); | 610 | try expect(x == z); |
| 609 | } | 611 | } |
| 610 | 612 | ||
| 611 | test "a third @fabs test, surely there should not be three fabs tests" { | 613 | test "a third @abs test, surely there should not be three fabs tests" { |
| 614 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 612 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 615 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 613 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 616 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 614 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 617 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| ... | @@ -617,23 +620,23 @@ test "a third @fabs test, surely there should not be three fabs tests" { | ... | @@ -617,23 +620,23 @@ test "a third @fabs test, surely there should not be three fabs tests" { |
| 617 | 620 | ||
| 618 | inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| { | 621 | inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| { |
| 619 | // normals | 622 | // normals |
| 620 | try expect(@fabs(@as(T, 1.0)) == 1.0); | 623 | try expect(@abs(@as(T, 1.0)) == 1.0); |
| 621 | try expect(@fabs(@as(T, -1.0)) == 1.0); | 624 | try expect(@abs(@as(T, -1.0)) == 1.0); |
| 622 | try expect(@fabs(math.floatMin(T)) == math.floatMin(T)); | 625 | try expect(@abs(math.floatMin(T)) == math.floatMin(T)); |
| 623 | try expect(@fabs(-math.floatMin(T)) == math.floatMin(T)); | 626 | try expect(@abs(-math.floatMin(T)) == math.floatMin(T)); |
| 624 | try expect(@fabs(math.floatMax(T)) == math.floatMax(T)); | 627 | try expect(@abs(math.floatMax(T)) == math.floatMax(T)); |
| 625 | try expect(@fabs(-math.floatMax(T)) == math.floatMax(T)); | 628 | try expect(@abs(-math.floatMax(T)) == math.floatMax(T)); |
| 626 | 629 | ||
| 627 | // subnormals | 630 | // subnormals |
| 628 | try expect(@fabs(@as(T, 0.0)) == 0.0); | 631 | try expect(@abs(@as(T, 0.0)) == 0.0); |
| 629 | try expect(@fabs(@as(T, -0.0)) == 0.0); | 632 | try expect(@abs(@as(T, -0.0)) == 0.0); |
| 630 | try expect(@fabs(math.floatTrueMin(T)) == math.floatTrueMin(T)); | 633 | try expect(@abs(math.floatTrueMin(T)) == math.floatTrueMin(T)); |
| 631 | try expect(@fabs(-math.floatTrueMin(T)) == math.floatTrueMin(T)); | 634 | try expect(@abs(-math.floatTrueMin(T)) == math.floatTrueMin(T)); |
| 632 | 635 | ||
| 633 | // non-finite numbers | 636 | // non-finite numbers |
| 634 | try expect(math.isPositiveInf(@fabs(math.inf(T)))); | 637 | try expect(math.isPositiveInf(@abs(math.inf(T)))); |
| 635 | try expect(math.isPositiveInf(@fabs(-math.inf(T)))); | 638 | try expect(math.isPositiveInf(@abs(-math.inf(T)))); |
| 636 | try expect(math.isNan(@fabs(math.nan(T)))); | 639 | try expect(math.isNan(@abs(math.nan(T)))); |
| 637 | } | 640 | } |
| 638 | } | 641 | } |
| 639 | 642 |
test/behavior/math.zig+3-3| ... | @@ -1391,7 +1391,7 @@ fn frem(comptime T: type) !void { | ... | @@ -1391,7 +1391,7 @@ fn frem(comptime T: type) !void { |
| 1391 | } | 1391 | } |
| 1392 | 1392 | ||
| 1393 | fn fremOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void { | 1393 | fn fremOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void { |
| 1394 | try expect(@fabs(@rem(a, b) - c) < epsilon); | 1394 | try expect(@abs(@rem(a, b) - c) < epsilon); |
| 1395 | } | 1395 | } |
| 1396 | 1396 | ||
| 1397 | test "float modulo division using @mod" { | 1397 | test "float modulo division using @mod" { |
| ... | @@ -1434,7 +1434,7 @@ fn fmod(comptime T: type) !void { | ... | @@ -1434,7 +1434,7 @@ fn fmod(comptime T: type) !void { |
| 1434 | } | 1434 | } |
| 1435 | 1435 | ||
| 1436 | fn fmodOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void { | 1436 | fn fmodOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void { |
| 1437 | try expect(@fabs(@mod(@as(T, a), @as(T, b)) - @as(T, c)) < epsilon); | 1437 | try expect(@abs(@mod(@as(T, a), @as(T, b)) - @as(T, c)) < epsilon); |
| 1438 | } | 1438 | } |
| 1439 | 1439 | ||
| 1440 | test "@round" { | 1440 | test "@round" { |
| ... | @@ -1627,7 +1627,7 @@ fn testAbsFloat() !void { | ... | @@ -1627,7 +1627,7 @@ fn testAbsFloat() !void { |
| 1627 | try testAbsFloatOne(10.05, 10.05); | 1627 | try testAbsFloatOne(10.05, 10.05); |
| 1628 | } | 1628 | } |
| 1629 | fn testAbsFloatOne(in: f32, out: f32) !void { | 1629 | fn testAbsFloatOne(in: f32, out: f32) !void { |
| 1630 | try expect(@fabs(@as(f32, in)) == @as(f32, out)); | 1630 | try expect(@abs(@as(f32, in)) == @as(f32, out)); |
| 1631 | } | 1631 | } |
| 1632 | 1632 | ||
| 1633 | test "mod lazy values" { | 1633 | test "mod lazy values" { |