Skip to content

Commit 09f03f6

Browse files
committed
std.math.sign: Narrow integer return types to possible values
This may be a breaking change for callers that depend on the return type being identical to the input type. For example, `sign(i32) * i8 + i8` could now overflow. Callers can add an explicit type annotation to avoid that situation. If Zig ever allows small integer types to coerce to floats (see #18614), then it might make sense to always return an integer. In the meantime, I figured it would be too annoying for users dealing with floats.
1 parent 3be6809 commit 09f03f6

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

lib/std/math.zig

+14-2
Original file line numberDiff line numberDiff line change
@@ -1735,12 +1735,24 @@ pub const F80 = struct {
17351735
}
17361736
};
17371737

1738+
fn Sign(T: type) type {
1739+
return switch (@typeInfo(T)) {
1740+
.int => |int| IntFittingRange(if (int.signedness == .signed) -1 else 0, 1),
1741+
.vector => |vec| switch (@typeInfo(vec.child)) {
1742+
.int => |int| @Vector(vec.len, IntFittingRange(if (int.signedness == .signed) -1 else 0, 1)),
1743+
else => T,
1744+
},
1745+
else => T,
1746+
};
1747+
}
1748+
17381749
/// Returns -1, 0, or 1.
17391750
/// Supports integer and float types and vectors of integer and float types.
17401751
/// Unsigned integer types will always return 0 or 1.
1752+
/// Returned integer types are narrowed to fit the possible values.
17411753
/// Branchless.
1742-
pub inline fn sign(i: anytype) @TypeOf(i) {
1743-
const T = @TypeOf(i);
1754+
pub inline fn sign(i: anytype) Sign(@TypeOf(i)) {
1755+
const T = Sign(@TypeOf(i));
17441756
return switch (@typeInfo(T)) {
17451757
.int, .comptime_int => @as(T, @intFromBool(i > 0)) - @as(T, @intFromBool(i < 0)),
17461758
.float, .comptime_float => @as(T, @floatFromInt(@intFromBool(i > 0))) - @as(T, @floatFromInt(@intFromBool(i < 0))),

0 commit comments

Comments
 (0)