Skip to content

Commit 7f024d6

Browse files
mateuszradomskiandrewrk
authored andcommitted
std: correct rounding in parse_hex_float.zig
1 parent 627cf6c commit 7f024d6

File tree

2 files changed

+13
-14
lines changed

2 files changed

+13
-14
lines changed

lib/std/fmt/parse_hex_float.zig

+13-9
Original file line numberDiff line numberDiff line change
@@ -202,18 +202,21 @@ pub fn parseHexFloat(comptime T: type, s: []const u8) !T {
202202
exponent += 1;
203203
}
204204

205-
// There are two cases to handle:
206-
// - We've truncated more than 0.5ULP (R=S=1), increase the mantissa.
207-
// - We've truncated exactly 0.5ULP (R=1 S=0), increase the mantissa if the
208-
// result is odd (G=1).
209-
// The two checks can be neatly folded as follows.
210-
mantissa |= @boolToInt(mantissa & 0b100 != 0);
211-
mantissa += 1;
212-
205+
// Whenever the guard bit is one (G=1) and:
206+
// - we've truncated more than 0.5ULP (R=S=1)
207+
// - we've truncated exactly 0.5ULP (R=1 S=0)
208+
// Were are going to increase the mantissa (round up)
209+
var exactly_half = (mantissa & 0b11) == 0b10;
210+
var more_than_half = (mantissa & 0b11) == 0b11;
213211
mantissa >>= 2;
212+
var guardBit = mantissa & 1 == 1;
214213
exponent += 2;
215214

216-
if (mantissa & (1 << (mantissa_bits + 1)) != 0) {
215+
if (guardBit and (exactly_half or more_than_half)) {
216+
mantissa += 1;
217+
}
218+
219+
if (mantissa == (1 << (mantissa_bits + 1))) {
217220
// Renormalize, if the exponent overflows we'll catch that below.
218221
mantissa >>= 1;
219222
exponent += 1;
@@ -338,6 +341,7 @@ test "f128" {
338341
// // Min denormalized value.
339342
.{ .s = "0x1p-16494", .v = math.f128_true_min },
340343
.{ .s = "-0x1p-16494", .v = -math.f128_true_min },
344+
.{ .s = "0x1.edcb34a235253948765432134674fp-1", .v = 0x1.edcb34a235253948765432134674fp-1 },
341345
};
342346

343347
for (cases) |case| {

test/behavior/math.zig

-5
Original file line numberDiff line numberDiff line change
@@ -632,11 +632,6 @@ test "allow signed integer division/remainder when values are comptime known and
632632
}
633633

634634
test "quad hex float literal parsing accurate" {
635-
if (builtin.zig_backend != .stage1) {
636-
// TODO https://github.com/ziglang/zig/issues/10737
637-
return error.SkipZigTest;
638-
}
639-
640635
const a: f128 = 0x1.1111222233334444555566667777p+0;
641636

642637
// implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing.

0 commit comments

Comments
 (0)