Skip to content

Commit a5900e3

Browse files
jacobly0andrewrk
authored andcommitted
compiler-rt: fix signed min int from float
1 parent 7e0c25e commit a5900e3

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

lib/compiler_rt/int_from_float.zig

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,12 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul
7272
} });
7373

7474
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);
7678
const int: I = @intFromFloat(switch (exponent) {
7779
0 => a,
78-
else => math.ldexp(parts.significand, significand_bits),
80+
else => math.ldexp(parts.significand, significand_bits_adjusted_to_handle_smin),
7981
});
8082
switch (signedness) {
8183
.signed => {

lib/compiler_rt/int_from_float_test.zig

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;
2424
const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi;
2525
const __fixdfti = @import("fixdfti.zig").__fixdfti;
2626
const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti;
27+
const __fixdfei = @import("fixdfei.zig").__fixdfei;
28+
const __fixunsdfei = @import("fixunsdfei.zig").__fixunsdfei;
2729

2830
// Conversion from f128
2931
const __fixtfsi = @import("fixtfsi.zig").__fixtfsi;
@@ -681,6 +683,44 @@ test "fixunsdfti" {
681683
try test__fixunsdfti(-0x1.FFFFFFFFFFFFEp+62, 0);
682684
}
683685

686+
fn 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+
698+
test "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+
714+
test "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+
684724
fn test__fixtfsi(a: f128, expected: i32) !void {
685725
const x = __fixtfsi(a);
686726
try testing.expect(x == expected);

0 commit comments

Comments
 (0)