| ... | @@ -784,15 +784,31 @@ fn testOverflow() !void { | ... | @@ -784,15 +784,31 @@ fn testOverflow() !void { |
| 784 | /// See also: `absCast` | 784 | /// See also: `absCast` |
| 785 | pub fn absInt(x: anytype) !@TypeOf(x) { | 785 | pub fn absInt(x: anytype) !@TypeOf(x) { |
| 786 | const T = @TypeOf(x); | 786 | const T = @TypeOf(x); |
| 787 | comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt | 787 | return switch (@typeInfo(T)) { |
| 788 | comptime assert(@typeInfo(T).Int.signedness == .signed); // must pass a signed integer to absInt | 788 | .Int => |info| { |
| 789 | | 789 | comptime assert(info.signedness == .signed); // must pass a signed integer to absInt |
| 790 | if (x == minInt(T)) { | 790 | if (x == minInt(T)) { |
| 791 | return error.Overflow; | 791 | return error.Overflow; |
| 792 | } else { | 792 | } else { |
| 793 | @setRuntimeSafety(false); | 793 | @setRuntimeSafety(false); |
| 794 | return if (x < 0) -x else x; | 794 | return if (x < 0) -x else x; |
| 795 | } | 795 | } |
| | 796 | }, |
| | 797 | .Vector => |vinfo| blk: { |
| | 798 | switch (@typeInfo(vinfo.child)) { |
| | 799 | .Int => |info| { |
| | 800 | comptime assert(info.signedness == .signed); // must pass a signed integer to absInt |
| | 801 | if (@reduce(.Or, x == @splat(vinfo.len, @as(vinfo.child, minInt(vinfo.child))))) { |
| | 802 | return error.Overflow; |
| | 803 | } |
| | 804 | const zero = @splat(vinfo.len, @as(vinfo.child, 0)); |
| | 805 | break :blk @select(vinfo.child, x > zero, x, -x); |
| | 806 | }, |
| | 807 | else => @compileError("Expected vector of ints, found " ++ @typeName(T)), |
| | 808 | } |
| | 809 | }, |
| | 810 | else => @compileError("Expected an int or vector, found " ++ @typeName(T)), |
| | 811 | }; |
| 796 | } | 812 | } |
| 797 | | 813 | |
| 798 | test "absInt" { | 814 | test "absInt" { |
| ... | @@ -802,6 +818,10 @@ test "absInt" { | ... | @@ -802,6 +818,10 @@ test "absInt" { |
| 802 | fn testAbsInt() !void { | 818 | fn testAbsInt() !void { |
| 803 | try testing.expect((absInt(@as(i32, -10)) catch unreachable) == 10); | 819 | try testing.expect((absInt(@as(i32, -10)) catch unreachable) == 10); |
| 804 | try testing.expect((absInt(@as(i32, 10)) catch unreachable) == 10); | 820 | try testing.expect((absInt(@as(i32, 10)) catch unreachable) == 10); |
| | 821 | try testing.expectEqual(@Vector(3, i32){ 10, 10, 0 }, (absInt(@Vector(3, i32){ -10, 10, 0 }) catch unreachable)); |
| | 822 | |
| | 823 | try testing.expectError(error.Overflow, absInt(@as(i32, minInt(i32)))); |
| | 824 | try testing.expectError(error.Overflow, absInt(@Vector(3, i32){ 10, -10, minInt(i32) })); |
| 805 | } | 825 | } |
| 806 | | 826 | |
| 807 | /// Divide numerator by denominator, rounding toward zero. Returns an | 827 | /// Divide numerator by denominator, rounding toward zero. Returns an |