summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorsin-ack <sin-ack@users.noreply.github.com>2022-01-01 17:21:01 +0000
committerAli Mohammad Pur <Ali.mpfard@gmail.com>2022-01-02 12:44:31 +0330
commitd8ee3839e41a0c22725a5dac1d6271a7275245f5 (patch)
treee57d29680e589445d43f8287af5ae6411ddc1792 /Userland/Libraries
parent2de7f2021d1f4881ab1b19b63002e3c978634399 (diff)
downloadserenity-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.cpp27
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.