authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-03-08 01:42:03-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-03-08 14:21:22-05:00
loga5900e310e6424d32c641cacd2007cc504e8caf6
tree8496c40d36490fd62f69b8ae188ea4be2e914362
parent7e0c25eccd8d9bc5b77953dbc9a39a26e383c550

compiler-rt: fix signed min int from float


2 files changed, 44 insertions(+), 2 deletions(-)

lib/compiler_rt/int_from_float.zig+4-2
...@@ -72,10 +72,12 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul...@@ -72,10 +72,12 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul
72 } });72 } });
7373
74 const parts = math.frexp(a);74 const parts = math.frexp(a);
75 const exponent = @max(parts.exponent - significand_bits, 0);75 const significand_bits_adjusted_to_handle_smin = @as(i32, significand_bits) +
76 @intFromBool(signedness == .signed and parts.exponent == 32 * result.len);
77 const exponent = @max(parts.exponent - significand_bits_adjusted_to_handle_smin, 0);
76 const int: I = @intFromFloat(switch (exponent) {78 const int: I = @intFromFloat(switch (exponent) {
77 0 => a,79 0 => a,
78 else => math.ldexp(parts.significand, significand_bits),80 else => math.ldexp(parts.significand, significand_bits_adjusted_to_handle_smin),
79 });81 });
80 switch (signedness) {82 switch (signedness) {
81 .signed => {83 .signed => {
lib/compiler_rt/int_from_float_test.zig+40
...@@ -24,6 +24,8 @@ const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;...@@ -24,6 +24,8 @@ const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;
24const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi;24const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi;
25const __fixdfti = @import("fixdfti.zig").__fixdfti;25const __fixdfti = @import("fixdfti.zig").__fixdfti;
26const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti;26const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti;
27const __fixdfei = @import("fixdfei.zig").__fixdfei;
28const __fixunsdfei = @import("fixunsdfei.zig").__fixunsdfei;
2729
28// Conversion from f12830// Conversion from f128
29const __fixtfsi = @import("fixtfsi.zig").__fixtfsi;31const __fixtfsi = @import("fixtfsi.zig").__fixtfsi;
...@@ -681,6 +683,44 @@ test "fixunsdfti" {...@@ -681,6 +683,44 @@ test "fixunsdfti" {
681 try test__fixunsdfti(-0x1.FFFFFFFFFFFFEp+62, 0);683 try test__fixunsdfti(-0x1.FFFFFFFFFFFFEp+62, 0);
682}684}
683685
686fn test_fixdfei(comptime T: type, expected: T, a: f64) !void {
687 const int = @typeInfo(T).int;
688 var expected_buf: [@divExact(int.bits, 32)]u32 = undefined;
689 std.mem.writeInt(T, std.mem.asBytes(&expected_buf), expected, endian);
690 var actual_buf: [@divExact(int.bits, 32)]u32 = undefined;
691 _ = switch (int.signedness) {
692 .signed => __fixdfei,
693 .unsigned => __fixunsdfei,
694 }(&actual_buf, int.bits, a);
695 try testing.expect(std.mem.eql(u32, &expected_buf, &actual_buf));
696}
697
698test "fixdfei" {
699 try test_fixdfei(i256, -1 << 255, -0x1p255);
700 try test_fixdfei(i256, -1 << 127, -0x1p127);
701 try test_fixdfei(i256, -1 << 100, -0x1p100);
702 try test_fixdfei(i256, -1 << 50, -0x1p50);
703 try test_fixdfei(i256, -1 << 1, -0x1p1);
704 try test_fixdfei(i256, -1 << 0, -0x1p0);
705 try test_fixdfei(i256, 0, 0);
706 try test_fixdfei(i256, 1 << 0, 0x1p0);
707 try test_fixdfei(i256, 1 << 1, 0x1p1);
708 try test_fixdfei(i256, 1 << 50, 0x1p50);
709 try test_fixdfei(i256, 1 << 100, 0x1p100);
710 try test_fixdfei(i256, 1 << 127, 0x1p127);
711 try test_fixdfei(i256, 1 << 254, 0x1p254);
712}
713
714test "fixundfei" {
715 try test_fixdfei(u256, 0, 0);
716 try test_fixdfei(u256, 1 << 0, 0x1p0);
717 try test_fixdfei(u256, 1 << 1, 0x1p1);
718 try test_fixdfei(u256, 1 << 50, 0x1p50);
719 try test_fixdfei(u256, 1 << 100, 0x1p100);
720 try test_fixdfei(u256, 1 << 127, 0x1p127);
721 try test_fixdfei(u256, 1 << 255, 0x1p255);
722}
723
684fn test__fixtfsi(a: f128, expected: i32) !void {724fn test__fixtfsi(a: f128, expected: i32) !void {
685 const x = __fixtfsi(a);725 const x = __fixtfsi(a);
686 try testing.expect(x == expected);726 try testing.expect(x == expected);