authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-31 22:59:49-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-02 22:07:56-07:00
logcee0f082df0bb0f90c7ee38c98ba8071c3be8d0c
tree899099c7f51b7c055ee3c8c5fdd906ee0b915eb4
parent23d148e5c7ab036ef686606f11a2343940890f5a

Merge pull request #10743 from m-radomski/master

std: correct rounding in parse_hex_float.zig

1 files changed, 11 insertions(+), 9 deletions(-)

lib/std/fmt/parse_hex_float.zig+11-9
...@@ -202,18 +202,19 @@ pub fn parseHexFloat(comptime T: type, s: []const u8) !T {...@@ -202,18 +202,19 @@ pub fn parseHexFloat(comptime T: type, s: []const u8) !T {
202 exponent += 1;202 exponent += 1;
203 }203 }
204204
205 // There are two cases to handle:205 // Whenever the guard bit is one (G=1) and:
206 // - We've truncated more than 0.5ULP (R=S=1), increase the mantissa.206 // - we've truncated more than 0.5ULP (R=S=1)
207 // - We've truncated exactly 0.5ULP (R=1 S=0), increase the mantissa if the207 // - we've truncated exactly 0.5ULP (R=1 S=0)
208 // result is odd (G=1).208 // Were are going to increase the mantissa (round up)
209 // The two checks can be neatly folded as follows.209 const guard_bit_and_half_or_more = (mantissa & 0b110) == 0b110;
210 mantissa |= @boolToInt(mantissa & 0b100 != 0);
211 mantissa += 1;
212
213 mantissa >>= 2;210 mantissa >>= 2;
214 exponent += 2;211 exponent += 2;
215212
216 if (mantissa & (1 << (mantissa_bits + 1)) != 0) {213 if (guard_bit_and_half_or_more) {
214 mantissa += 1;
215 }
216
217 if (mantissa == (1 << (mantissa_bits + 1))) {
217 // Renormalize, if the exponent overflows we'll catch that below.218 // Renormalize, if the exponent overflows we'll catch that below.
218 mantissa >>= 1;219 mantissa >>= 1;
219 exponent += 1;220 exponent += 1;
...@@ -338,6 +339,7 @@ test "f128" {...@@ -338,6 +339,7 @@ test "f128" {
338 // // Min denormalized value.339 // // Min denormalized value.
339 .{ .s = "0x1p-16494", .v = math.f128_true_min },340 .{ .s = "0x1p-16494", .v = math.f128_true_min },
340 .{ .s = "-0x1p-16494", .v = -math.f128_true_min },341 .{ .s = "-0x1p-16494", .v = -math.f128_true_min },
342 .{ .s = "0x1.edcb34a235253948765432134674fp-1", .v = 0x1.edcb34a235253948765432134674fp-1 },
341 };343 };
342344
343 for (cases) |case| {345 for (cases) |case| {