Skip to content

Commit

Permalink
Correct hex-float parsing
Browse files Browse the repository at this point in the history
Unblocks #495.
  • Loading branch information
tiehuis committed Jun 28, 2018
1 parent 2fa588e commit 4a35d7e
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 2 deletions.
11 changes: 9 additions & 2 deletions src/tokenizer.cpp
Expand Up @@ -357,12 +357,19 @@ static void end_float_token(Tokenize *t) {
// Mask the sign bit to 0 since always non-negative lex
const uint64_t exp_mask = 0xffffull << exp_shift;

if (shift >= 64) {
// must be special-cased to avoid undefined behavior on shift == 64
if (shift == 128) {
f_bits.repr[0] = 0;
f_bits.repr[1] = sig_bits[0];
} else if (shift == 0) {
f_bits.repr[0] = sig_bits[0];
f_bits.repr[1] = sig_bits[1];
} else if (shift >= 64) {
f_bits.repr[0] = 0;
f_bits.repr[1] = sig_bits[0] << (shift - 64);
} else {
f_bits.repr[0] = sig_bits[0] << shift;
f_bits.repr[1] = ((sig_bits[1] << shift) | (sig_bits[0] >> (64 - shift)));
f_bits.repr[1] = (sig_bits[1] << shift) | (sig_bits[0] >> (64 - shift));
}

f_bits.repr[1] &= ~exp_mask;
Expand Down
8 changes: 8 additions & 0 deletions test/cases/math.zig
Expand Up @@ -296,6 +296,14 @@ test "quad hex float literal parsing in range" {
const d = 0x1.edcbff8ad76ab5bf46463233214fp-435;
}

test "quad hex float literal parsing accurate" {
const a: f128 = 0x1.1111222233334444555566667777p+0;

// implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing.
const expected: u128 = 0x3fff1111222233334444555566667777;
assert(@bitCast(u128, a) == expected);
}

test "hex float literal within range" {
const a = 0x1.0p16383;
const b = 0x0.1p16387;
Expand Down

0 comments on commit 4a35d7e

Please sign in to comment.