diff options
author | sin-ack <sin-ack@users.noreply.github.com> | 2022-01-01 17:21:01 +0000 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2022-01-02 12:44:31 +0330 |
commit | d8ee3839e41a0c22725a5dac1d6271a7275245f5 (patch) | |
tree | e57d29680e589445d43f8287af5ae6411ddc1792 /Userland/Libraries | |
parent | 2de7f2021d1f4881ab1b19b63002e3c978634399 (diff) | |
download | serenity-d8ee3839e41a0c22725a5dac1d6271a7275245f5.zip |
LibM: Count fractions when exponent < -1 with mantissa == 0
Without this change, floor(-0.125) returned 0.
This is because the number has a fraction part even if mantissa is zero
while the unbiased exponent is negative.
The names of some variables were also made clearer.
Co-Authored-By: Daniel Bertalan <dani@danielbertalan.dev>
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibM/math.cpp | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/Userland/Libraries/LibM/math.cpp b/Userland/Libraries/LibM/math.cpp index b0a3459064..7c714fda28 100644 --- a/Userland/Libraries/LibM/math.cpp +++ b/Userland/Libraries/LibM/math.cpp @@ -113,49 +113,56 @@ static FloatType internal_to_integer(FloatType x, RoundingMode rounding_mode) { if (!isfinite(x)) return x; + using Extractor = FloatExtractor<decltype(x)>; Extractor extractor; extractor.d = x; + auto unbiased_exponent = extractor.exponent - Extractor::exponent_bias; - bool round = false; - bool guard = false; + + bool has_half_fraction = false; + bool has_nonhalf_fraction = false; if (unbiased_exponent < 0) { // it was easier to special case [0..1) as it saves us from // handling subnormals, underflows, etc if (unbiased_exponent == -1) { - round = true; + has_half_fraction = true; } - guard = extractor.mantissa != 0; + + has_nonhalf_fraction = unbiased_exponent < -1 || extractor.mantissa != 0; extractor.mantissa = 0; extractor.exponent = 0; } else { if (unbiased_exponent >= Extractor::mantissa_bits) return x; + auto dead_bitcount = Extractor::mantissa_bits - unbiased_exponent; auto dead_mask = (1ull << dead_bitcount) - 1; auto dead_bits = extractor.mantissa & dead_mask; extractor.mantissa &= ~dead_mask; - auto guard_mask = dead_mask >> 1; - guard = (dead_bits & guard_mask) != 0; - round = (dead_bits & ~guard_mask) != 0; + auto nonhalf_fraction_mask = dead_mask >> 1; + has_nonhalf_fraction = (dead_bits & nonhalf_fraction_mask) != 0; + has_half_fraction = (dead_bits & ~nonhalf_fraction_mask) != 0; } + bool should_round = false; switch (rounding_mode) { case RoundingMode::ToEven: - should_round = round; + should_round = has_half_fraction; break; case RoundingMode::Up: if (!extractor.sign) - should_round = guard || round; + should_round = has_nonhalf_fraction || has_half_fraction; break; case RoundingMode::Down: if (extractor.sign) - should_round = guard || round; + should_round = has_nonhalf_fraction || has_half_fraction; break; case RoundingMode::ToZero: break; } + if (should_round) { // We could do this ourselves, but this saves us from manually // handling overflow. |