| ... | @@ -202,18 +202,21 @@ pub fn parseHexFloat(comptime T: type, s: []const u8) !T { | ... | @@ -202,18 +202,21 @@ pub fn parseHexFloat(comptime T: type, s: []const u8) !T { |
| 202 | exponent += 1; | 202 | exponent += 1; |
| 203 | } | 203 | } |
| 204 | | 204 | |
| 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 the | 207 | // - 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 | var exactly_half = (mantissa & 0b11) == 0b10; |
| 210 | mantissa |= @boolToInt(mantissa & 0b100 != 0); | 210 | var more_than_half = (mantissa & 0b11) == 0b11; |
| 211 | mantissa += 1; | | |
| 212 | | | |
| 213 | mantissa >>= 2; | 211 | mantissa >>= 2; |
| | 212 | var guardBit = mantissa & 1 == 1; |
| 214 | exponent += 2; | 213 | exponent += 2; |
| 215 | | 214 | |
| 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))) { |
| 217 | // Renormalize, if the exponent overflows we'll catch that below. | 220 | // Renormalize, if the exponent overflows we'll catch that below. |
| 218 | mantissa >>= 1; | 221 | mantissa >>= 1; |
| 219 | exponent += 1; | 222 | exponent += 1; |
| ... | @@ -338,6 +341,7 @@ test "f128" { | ... | @@ -338,6 +341,7 @@ test "f128" { |
| 338 | // // Min denormalized value. | 341 | // // Min denormalized value. |
| 339 | .{ .s = "0x1p-16494", .v = math.f128_true_min }, | 342 | .{ .s = "0x1p-16494", .v = math.f128_true_min }, |
| 340 | .{ .s = "-0x1p-16494", .v = -math.f128_true_min }, | 343 | .{ .s = "-0x1p-16494", .v = -math.f128_true_min }, |
| | 344 | .{ .s = "0x1.edcb34a235253948765432134674fp-1", .v = 0x1.edcb34a235253948765432134674fp-1 }, |
| 341 | }; | 345 | }; |
| 342 | | 346 | |
| 343 | for (cases) |case| { | 347 | for (cases) |case| { |