LibM: Implement more rounding functions

This patch implements the entire rint family, while taking into account
the current rounding mode, and implements ceil, round, trunc, and floor
for types which they weren't before.
This commit is contained in:
Mițca Dumitru 2021-03-07 23:47:07 +02:00 committed by Andreas Kling
parent 88d342d007
commit efe4845c56
Notes: sideshowbarker 2024-07-18 21:35:42 +09:00
2 changed files with 83 additions and 6 deletions

View File

@ -28,6 +28,7 @@
#include <AK/Platform.h>
#include <AK/StdLibExtras.h>
#include <LibC/assert.h>
#include <fenv.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
@ -61,10 +62,10 @@ template<size_t value>
constexpr size_t product_odd() { return value * product_odd<value - 2>(); }
enum class RoundingMode {
ToZero,
Up,
Down,
ToEven
ToZero = FE_TOWARDZERO,
Up = FE_UPWARD,
Down = FE_DOWNWARD,
ToEven = FE_TONEAREST
};
template<typename T>
@ -307,6 +308,16 @@ double trunc(double x) NOEXCEPT
return internal_to_integer(x, RoundingMode::ToZero);
}
float truncf(float x) NOEXCEPT
{
return internal_to_integer(x, RoundingMode::ToZero);
}
long double truncl(long double x) NOEXCEPT
{
return internal_to_integer(x, RoundingMode::ToZero);
}
double cos(double angle) NOEXCEPT
{
return sin(angle + M_PI_2);
@ -691,6 +702,11 @@ float roundf(float value) NOEXCEPT
return internal_to_integer(value, RoundingMode::ToEven);
}
long double roundl(long double value) NOEXCEPT
{
return internal_to_integer(value, RoundingMode::ToEven);
}
float floorf(float value) NOEXCEPT
{
return internal_to_integer(value, RoundingMode::Down);
@ -701,10 +717,54 @@ double floor(double value) NOEXCEPT
return internal_to_integer(value, RoundingMode::Down);
}
long double floorl(long double value) NOEXCEPT
{
return internal_to_integer(value, RoundingMode::Down);
}
long double rintl(long double value) NOEXCEPT
{
return internal_to_integer(value, RoundingMode { fegetround() });
}
double rint(double value) NOEXCEPT
{
// This should be the current rounding mode
return internal_to_integer(value, RoundingMode::ToEven);
return internal_to_integer(value, RoundingMode { fegetround() });
}
float rintf(float value) NOEXCEPT
{
return internal_to_integer(value, RoundingMode { fegetround() });
}
long lrintl(long double value) NOEXCEPT
{
return (long)internal_to_integer(value, RoundingMode { fegetround() });
}
long lrint(double value) NOEXCEPT
{
return (long)internal_to_integer(value, RoundingMode { fegetround() });
}
long lrintf(float value) NOEXCEPT
{
return (long)internal_to_integer(value, RoundingMode { fegetround() });
}
long long llrintl(long double value) NOEXCEPT
{
return (long long)internal_to_integer(value, RoundingMode { fegetround() });
}
long long llrint(double value) NOEXCEPT
{
return (long long)internal_to_integer(value, RoundingMode { fegetround() });
}
long long llrintf(float value) NOEXCEPT
{
return (long long)internal_to_integer(value, RoundingMode { fegetround() });
}
float ceilf(float value) NOEXCEPT
@ -717,6 +777,11 @@ double ceil(double value) NOEXCEPT
return internal_to_integer(value, RoundingMode::Up);
}
long double ceill(long double value) NOEXCEPT
{
return internal_to_integer(value, RoundingMode::Up);
}
double modf(double x, double* intpart) NOEXCEPT
{
double integer_part = internal_to_integer(x, RoundingMode::ToZero);

View File

@ -99,12 +99,24 @@ double tanh(double) NOEXCEPT;
float tanhf(float) NOEXCEPT;
double ceil(double) NOEXCEPT;
float ceilf(float) NOEXCEPT;
long double ceill(long double) NOEXCEPT;
double floor(double) NOEXCEPT;
float floorf(float) NOEXCEPT;
long double floorl(long double) NOEXCEPT;
double trunc(double) NOEXCEPT;
float truncf(float) NOEXCEPT;
long double truncl(long double) NOEXCEPT;
double round(double) NOEXCEPT;
float roundf(float) NOEXCEPT;
long double roundl(long double) NOEXCEPT;
double rint(double) NOEXCEPT;
float rintf(float) NOEXCEPT;
long lrintl(long double) NOEXCEPT;
long lrint(double) NOEXCEPT;
long lrintf(float) NOEXCEPT;
long long llrintl(long double) NOEXCEPT;
long long llrint(double) NOEXCEPT;
long long llrintf(float) NOEXCEPT;
double fabs(double) NOEXCEPT;
float fabsf(float) NOEXCEPT;
double fmod(double, double) NOEXCEPT;