| ... | @@ -1772,26 +1772,33 @@ pub const F80 = struct { | ... | @@ -1772,26 +1772,33 @@ pub const F80 = struct { |
| 1772 | } | 1772 | } |
| 1773 | }; | 1773 | }; |
| 1774 | | 1774 | |
| | 1775 | fn SignOf(T: type) type { |
| | 1776 | return switch (@typeInfo(T)) { |
| | 1777 | .comptime_int, .comptime_float => comptime_int, |
| | 1778 | .int => |int| switch (int.signedness) { |
| | 1779 | .signed => IntFittingRange(-1, 1), |
| | 1780 | .unsigned => IntFittingRange(0, 1), |
| | 1781 | }, |
| | 1782 | .float => IntFittingRange(-1, 1), |
| | 1783 | .vector => |vec| @Vector(vec.len, SignOf(vec.child)), |
| | 1784 | else => @compileError("Expected an int, float, or a vector of one, found " ++ @typeName(T)), |
| | 1785 | }; |
| | 1786 | } |
| | 1787 | |
| 1775 | /// Returns -1, 0, or 1. | 1788 | /// Returns -1, 0, or 1. |
| 1776 | /// Supports integer and float types and vectors of integer and float types. | 1789 | /// Supports integer and float types and vectors of integer and float types. |
| 1777 | /// Unsigned integer types will always return 0 or 1. | 1790 | /// Unsigned integer types will always return 0 or 1. |
| | 1791 | /// The returned integer type is the smallest that fits the possible values. |
| 1778 | /// Branchless. | 1792 | /// Branchless. |
| 1779 | pub inline fn sign(i: anytype) @TypeOf(i) { | 1793 | pub inline fn sign(n: anytype) SignOf(@TypeOf(n)) { |
| 1780 | const T = @TypeOf(i); | 1794 | const T = SignOf(@TypeOf(n)); |
| 1781 | return switch (@typeInfo(T)) { | 1795 | return switch (@typeInfo(T)) { |
| 1782 | .int, .comptime_int => @as(T, @intFromBool(i > 0)) - @as(T, @intFromBool(i < 0)), | 1796 | .vector => |vec| blk: { |
| 1783 | .float, .comptime_float => @as(T, @floatFromInt(@intFromBool(i > 0))) - @as(T, @floatFromInt(@intFromBool(i < 0))), | 1797 | const zero: T = @splat(0); |
| 1784 | .vector => |vinfo| blk: { | 1798 | const one: T = @splat(1); |
| 1785 | switch (@typeInfo(vinfo.child)) { | 1799 | break :blk @select(vec.child, n > zero, one, zero) - @select(vec.child, n < zero, one, zero); |
| 1786 | .int, .float => { | | |
| 1787 | const zero: T = @splat(0); | | |
| 1788 | const one: T = @splat(1); | | |
| 1789 | break :blk @select(vinfo.child, i > zero, one, zero) - @select(vinfo.child, i < zero, one, zero); | | |
| 1790 | }, | | |
| 1791 | else => @compileError("Expected vector of ints or floats, found " ++ @typeName(T)), | | |
| 1792 | } | | |
| 1793 | }, | 1800 | }, |
| 1794 | else => @compileError("Expected an int, float or vector of one, found " ++ @typeName(T)), | 1801 | else => @as(T, @intFromBool(n > 0)) - @as(T, @intFromBool(n < 0)), |
| 1795 | }; | 1802 | }; |
| 1796 | } | 1803 | } |
| 1797 | | 1804 | |