commit b636906fb640a12107cd21637c2af67b8e9d6ebd (tree)
parent c150a66bfe2010be86e38f40573ffc8bdf5c2326
Author: whatisaphone <hi@whatisaph.one>
Date: Sat, 20 Jun 2026 09:45:17 -0400
std.math: Add signExtend
Diffstat:
1 file changed, 36 insertions(+), 0 deletions(-)
diff --git a/lib/std/math.zig b/lib/std/math.zig
@@ -1875,3 +1875,39 @@ test sign {
try testSign();
try comptime testSign();
}
+
+/// Increases the bit width of an integer by copying the most significant bit.
+/// This results in the input and output having the same arithmetic value, when
+/// interpreted as two's complement integers.
+fn signExtend(To: type, n: anytype) To {
+ const From = @TypeOf(n);
+ if (From == u0) return 0;
+ const FromSigned = @Int(.signed, @typeInfo(From).int.bits);
+ const ToSigned = @Int(.signed, @typeInfo(To).int.bits);
+
+ return @bitCast(@as(ToSigned, @as(FromSigned, @bitCast(n))));
+}
+
+test signExtend {
+ const number: u8 = 0x86;
+ try testing.expectEqual(0xff86, signExtend(u16, number));
+
+ try testing.expectEqual(0, signExtend(u1, @as(u0, 0)));
+ try testing.expectEqual(0, signExtend(u16, @as(u0, 0)));
+
+ try testing.expectEqual(0x0000, signExtend(u16, @as(u1, 0b0)));
+ try testing.expectEqual(0xffff, signExtend(u16, @as(u1, 0b1)));
+
+ try testing.expectEqual(0b000, signExtend(u3, @as(u2, 0b00)));
+ try testing.expectEqual(0b001, signExtend(u3, @as(u2, 0b01)));
+ try testing.expectEqual(0b110, signExtend(u3, @as(u2, 0b10)));
+ try testing.expectEqual(0b111, signExtend(u3, @as(u2, 0b11)));
+ try testing.expectEqual(0b0000_0001, signExtend(u8, @as(u2, 0b01)));
+ try testing.expectEqual(0b1111_1110, signExtend(u8, @as(u2, 0b10)));
+
+ try testing.expectEqual(0x0039, signExtend(u16, @as(u8, 0x39)));
+ try testing.expectEqual(0xff93, signExtend(u16, @as(u8, 0x93)));
+
+ try testing.expectEqual(5, signExtend(i32, @as(i8, 5)));
+ try testing.expectEqual(-123, signExtend(i16, @as(i8, -123)));
+}