mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:27:43 +00:00
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>
This commit is contained in:
parent
2de7f2021d
commit
d8ee3839e4
1 changed files with 17 additions and 10 deletions
|
@ -113,49 +113,56 @@ static FloatType internal_to_integer(FloatType x, RoundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
if (!isfinite(x))
|
if (!isfinite(x))
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
using Extractor = FloatExtractor<decltype(x)>;
|
using Extractor = FloatExtractor<decltype(x)>;
|
||||||
Extractor extractor;
|
Extractor extractor;
|
||||||
extractor.d = x;
|
extractor.d = x;
|
||||||
|
|
||||||
auto unbiased_exponent = extractor.exponent - Extractor::exponent_bias;
|
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) {
|
if (unbiased_exponent < 0) {
|
||||||
// it was easier to special case [0..1) as it saves us from
|
// it was easier to special case [0..1) as it saves us from
|
||||||
// handling subnormals, underflows, etc
|
// handling subnormals, underflows, etc
|
||||||
if (unbiased_exponent == -1) {
|
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.mantissa = 0;
|
||||||
extractor.exponent = 0;
|
extractor.exponent = 0;
|
||||||
} else {
|
} else {
|
||||||
if (unbiased_exponent >= Extractor::mantissa_bits)
|
if (unbiased_exponent >= Extractor::mantissa_bits)
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
auto dead_bitcount = Extractor::mantissa_bits - unbiased_exponent;
|
auto dead_bitcount = Extractor::mantissa_bits - unbiased_exponent;
|
||||||
auto dead_mask = (1ull << dead_bitcount) - 1;
|
auto dead_mask = (1ull << dead_bitcount) - 1;
|
||||||
auto dead_bits = extractor.mantissa & dead_mask;
|
auto dead_bits = extractor.mantissa & dead_mask;
|
||||||
extractor.mantissa &= ~dead_mask;
|
extractor.mantissa &= ~dead_mask;
|
||||||
|
|
||||||
auto guard_mask = dead_mask >> 1;
|
auto nonhalf_fraction_mask = dead_mask >> 1;
|
||||||
guard = (dead_bits & guard_mask) != 0;
|
has_nonhalf_fraction = (dead_bits & nonhalf_fraction_mask) != 0;
|
||||||
round = (dead_bits & ~guard_mask) != 0;
|
has_half_fraction = (dead_bits & ~nonhalf_fraction_mask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool should_round = false;
|
bool should_round = false;
|
||||||
switch (rounding_mode) {
|
switch (rounding_mode) {
|
||||||
case RoundingMode::ToEven:
|
case RoundingMode::ToEven:
|
||||||
should_round = round;
|
should_round = has_half_fraction;
|
||||||
break;
|
break;
|
||||||
case RoundingMode::Up:
|
case RoundingMode::Up:
|
||||||
if (!extractor.sign)
|
if (!extractor.sign)
|
||||||
should_round = guard || round;
|
should_round = has_nonhalf_fraction || has_half_fraction;
|
||||||
break;
|
break;
|
||||||
case RoundingMode::Down:
|
case RoundingMode::Down:
|
||||||
if (extractor.sign)
|
if (extractor.sign)
|
||||||
should_round = guard || round;
|
should_round = has_nonhalf_fraction || has_half_fraction;
|
||||||
break;
|
break;
|
||||||
case RoundingMode::ToZero:
|
case RoundingMode::ToZero:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (should_round) {
|
if (should_round) {
|
||||||
// We could do this ourselves, but this saves us from manually
|
// We could do this ourselves, but this saves us from manually
|
||||||
// handling overflow.
|
// handling overflow.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue