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

View File

@ -99,12 +99,24 @@ double tanh(double) NOEXCEPT;
float tanhf(float) NOEXCEPT; float tanhf(float) NOEXCEPT;
double ceil(double) NOEXCEPT; double ceil(double) NOEXCEPT;
float ceilf(float) NOEXCEPT; float ceilf(float) NOEXCEPT;
long double ceill(long double) NOEXCEPT;
double floor(double) NOEXCEPT; double floor(double) NOEXCEPT;
float floorf(float) NOEXCEPT; float floorf(float) NOEXCEPT;
long double floorl(long double) NOEXCEPT;
double trunc(double) NOEXCEPT; double trunc(double) NOEXCEPT;
float truncf(float) NOEXCEPT; float truncf(float) NOEXCEPT;
long double truncl(long double) NOEXCEPT;
double round(double) NOEXCEPT; double round(double) NOEXCEPT;
float roundf(float) 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; double fabs(double) NOEXCEPT;
float fabsf(float) NOEXCEPT; float fabsf(float) NOEXCEPT;
double fmod(double, double) NOEXCEPT; double fmod(double, double) NOEXCEPT;