mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 06:37:43 +00:00
LibM: Implement nextafter() and nexttoward()
Patch from Anonymous.
This commit is contained in:
parent
e87eac9273
commit
0269578d3e
2 changed files with 186 additions and 10 deletions
|
@ -70,11 +70,14 @@ union FloatExtractor;
|
|||
template<>
|
||||
union FloatExtractor<double> {
|
||||
static const int mantissa_bits = 52;
|
||||
static const unsigned long long mantissa_max = (1ull << 52) - 1;
|
||||
static const int exponent_bias = 1023;
|
||||
static const int exponent_bits = 11;
|
||||
static const unsigned exponent_max = 2047;
|
||||
struct {
|
||||
unsigned long long mantissa : 52;
|
||||
unsigned exponent : 11;
|
||||
int sign : 1;
|
||||
unsigned sign : 1;
|
||||
};
|
||||
double d;
|
||||
};
|
||||
|
@ -82,11 +85,14 @@ union FloatExtractor<double> {
|
|||
template<>
|
||||
union FloatExtractor<float> {
|
||||
static const int mantissa_bits = 23;
|
||||
static const unsigned mantissa_max = (1 << 23) - 1;
|
||||
static const int exponent_bias = 127;
|
||||
static const int exponent_bits = 8;
|
||||
static const unsigned exponent_max = 255;
|
||||
struct {
|
||||
unsigned long long mantissa : 23;
|
||||
unsigned exponent : 8;
|
||||
int sign : 1;
|
||||
unsigned sign : 1;
|
||||
};
|
||||
float d;
|
||||
};
|
||||
|
@ -152,6 +158,71 @@ static FloatType internal_to_integer(FloatType x, RoundingMode rounding_mode)
|
|||
return extractor.d;
|
||||
}
|
||||
|
||||
// This is much branchier than it really needs to be
|
||||
template<typename FloatType>
|
||||
static FloatType internal_nextafter(FloatType x, bool up)
|
||||
{
|
||||
if (!isfinite(x))
|
||||
return x;
|
||||
using Extractor = FloatExtractor<decltype(x)>;
|
||||
Extractor extractor;
|
||||
extractor.d = x;
|
||||
if (x == 0) {
|
||||
if (!extractor.sign) {
|
||||
extractor.mantissa = 1;
|
||||
extractor.sign = !up;
|
||||
return extractor.d;
|
||||
}
|
||||
if (up) {
|
||||
extractor.sign = false;
|
||||
extractor.mantissa = 1;
|
||||
return extractor.d;
|
||||
}
|
||||
extractor.mantissa = 1;
|
||||
extractor.sign = up != extractor.sign;
|
||||
return extractor.d;
|
||||
}
|
||||
if (up != extractor.sign) {
|
||||
extractor.mantissa++;
|
||||
if (!extractor.mantissa) {
|
||||
// no need to normalize the mantissa as we just hit a power
|
||||
// of two.
|
||||
extractor.exponent++;
|
||||
if (extractor.exponent == Extractor::exponent_max) {
|
||||
extractor.exponent = Extractor::exponent_max - 1;
|
||||
extractor.mantissa = Extractor::mantissa_max;
|
||||
}
|
||||
}
|
||||
return extractor.d;
|
||||
}
|
||||
|
||||
if (!extractor.mantissa) {
|
||||
if (extractor.exponent) {
|
||||
extractor.exponent--;
|
||||
extractor.mantissa = Extractor::mantissa_max;
|
||||
} else {
|
||||
extractor.d = 0;
|
||||
}
|
||||
return extractor.d;
|
||||
}
|
||||
|
||||
extractor.mantissa--;
|
||||
if (extractor.mantissa != Extractor::mantissa_max)
|
||||
return extractor.d;
|
||||
if (extractor.exponent) {
|
||||
extractor.exponent--;
|
||||
// normalize
|
||||
extractor.mantissa <<= 1;
|
||||
} else {
|
||||
if (extractor.sign) {
|
||||
// Negative infinity
|
||||
extractor.mantissa = 0;
|
||||
extractor.exponent = Extractor::exponent_max;
|
||||
}
|
||||
}
|
||||
return extractor.d;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
double trunc(double x) NOEXCEPT
|
||||
|
@ -634,14 +705,18 @@ double erfc(double x) NOEXCEPT
|
|||
return 1 - erf(x);
|
||||
}
|
||||
|
||||
double nextafter(double, double) NOEXCEPT
|
||||
double nextafter(double x, double target) NOEXCEPT
|
||||
{
|
||||
TODO();
|
||||
if (x == target)
|
||||
return target;
|
||||
return internal_nextafter(x, target >= x);
|
||||
}
|
||||
|
||||
float nextafterf(float, float) NOEXCEPT
|
||||
float nextafterf(float x, float target) NOEXCEPT
|
||||
{
|
||||
TODO();
|
||||
if (x == target)
|
||||
return target;
|
||||
return internal_nextafter(x, target >= x);
|
||||
}
|
||||
|
||||
long double nextafterl(long double, long double) NOEXCEPT
|
||||
|
@ -649,14 +724,18 @@ long double nextafterl(long double, long double) NOEXCEPT
|
|||
TODO();
|
||||
}
|
||||
|
||||
double nexttoward(double, long double) NOEXCEPT
|
||||
double nexttoward(double x, long double target) NOEXCEPT
|
||||
{
|
||||
TODO();
|
||||
if (x == target)
|
||||
return target;
|
||||
return internal_nextafter(x, target >= x);
|
||||
}
|
||||
|
||||
float nexttowardf(float, long double) NOEXCEPT
|
||||
float nexttowardf(float x, long double target) NOEXCEPT
|
||||
{
|
||||
TODO();
|
||||
if (x == target)
|
||||
return target;
|
||||
return internal_nextafter(x, target >= x);
|
||||
}
|
||||
|
||||
long double nexttowardl(long double, long double) NOEXCEPT
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue