mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
AK: Add trunc and rint to AK/Math.h
These are useful in some algorithms, which require specific rounding.
This commit is contained in:
parent
6573ace8f1
commit
594369121a
Notes:
sideshowbarker
2024-07-17 04:03:27 +09:00
Author: https://github.com/Hendiadyoin1 Commit: https://github.com/SerenityOS/serenity/commit/594369121a Pull-request: https://github.com/SerenityOS/serenity/pull/18998 Reviewed-by: https://github.com/kleinesfilmroellchen ✅ Reviewed-by: https://github.com/linusg ✅
1 changed files with 64 additions and 0 deletions
64
AK/Math.h
64
AK/Math.h
|
@ -85,6 +85,7 @@ namespace Rounding {
|
||||||
template<FloatingPoint T>
|
template<FloatingPoint T>
|
||||||
constexpr T ceil(T num)
|
constexpr T ceil(T num)
|
||||||
{
|
{
|
||||||
|
// FIXME: SSE4.1 rounds[sd] num, res, 0b110
|
||||||
if (is_constant_evaluated()) {
|
if (is_constant_evaluated()) {
|
||||||
if (num < NumericLimits<i64>::min() || num > NumericLimits<i64>::max())
|
if (num < NumericLimits<i64>::min() || num > NumericLimits<i64>::max())
|
||||||
return num;
|
return num;
|
||||||
|
@ -102,6 +103,7 @@ constexpr T ceil(T num)
|
||||||
template<FloatingPoint T>
|
template<FloatingPoint T>
|
||||||
constexpr T floor(T num)
|
constexpr T floor(T num)
|
||||||
{
|
{
|
||||||
|
// FIXME: SSE4.1 rounds[sd] num, res, 0b101
|
||||||
if (is_constant_evaluated()) {
|
if (is_constant_evaluated()) {
|
||||||
if (num < NumericLimits<i64>::min() || num > NumericLimits<i64>::max())
|
if (num < NumericLimits<i64>::min() || num > NumericLimits<i64>::max())
|
||||||
return num;
|
return num;
|
||||||
|
@ -116,6 +118,66 @@ constexpr T floor(T num)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<FloatingPoint T>
|
||||||
|
constexpr T trunc(T num)
|
||||||
|
{
|
||||||
|
#if ARCH(AARCH64)
|
||||||
|
if (is_constant_evaluated()) {
|
||||||
|
if (num < NumericLimits<i64>::min() || num > NumericLimits<i64>::max())
|
||||||
|
return num;
|
||||||
|
return static_cast<T>(static_cast<i64>(num));
|
||||||
|
}
|
||||||
|
AARCH64_INSTRUCTION(frintz, num);
|
||||||
|
#endif
|
||||||
|
// FIXME: Use dedicated instruction in the non constexpr case
|
||||||
|
// SSE4.1: rounds[sd] %num, %res, 0b111
|
||||||
|
if (num < NumericLimits<i64>::min() || num > NumericLimits<i64>::max())
|
||||||
|
return num;
|
||||||
|
return static_cast<T>(static_cast<i64>(num));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<FloatingPoint T>
|
||||||
|
constexpr T rint(T x)
|
||||||
|
{
|
||||||
|
CONSTEXPR_STATE(rint, x);
|
||||||
|
// Note: This does break tie to even
|
||||||
|
// But the behavior of frndint/rounds[ds]/frintx can be configured
|
||||||
|
// through the floating point control registers.
|
||||||
|
// FIXME: We should decide if we rename this to allow us to get away from
|
||||||
|
// the configurability "burden" rint has
|
||||||
|
// this would make us use `rounds[sd] %num, %res, 0b100`
|
||||||
|
// and `frintn` respectively,
|
||||||
|
// no such guaranteed round exists for x87 `frndint`
|
||||||
|
#if ARCH(X86_64)
|
||||||
|
# ifdef __SSE4_1__
|
||||||
|
if constexpr (IsSame<T, double>) {
|
||||||
|
T r;
|
||||||
|
asm(
|
||||||
|
"roundsd %1, %0"
|
||||||
|
: "=x"(r)
|
||||||
|
: "x"(x));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if constexpr (IsSame<T, float>) {
|
||||||
|
T r;
|
||||||
|
asm(
|
||||||
|
"roundss %1, %0"
|
||||||
|
: "=x"(r)
|
||||||
|
: "x"(x));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
asm(
|
||||||
|
"frndint"
|
||||||
|
: "+t"(x));
|
||||||
|
return x;
|
||||||
|
# endif
|
||||||
|
#elif ARCH(AARCH64)
|
||||||
|
AARCH64_INSTRUCTION(frintx, x);
|
||||||
|
#endif
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
template<FloatingPoint T>
|
template<FloatingPoint T>
|
||||||
constexpr T round(T x)
|
constexpr T round(T x)
|
||||||
{
|
{
|
||||||
|
@ -286,8 +348,10 @@ ALWAYS_INLINE I round_to(P value)
|
||||||
|
|
||||||
using Rounding::ceil;
|
using Rounding::ceil;
|
||||||
using Rounding::floor;
|
using Rounding::floor;
|
||||||
|
using Rounding::rint;
|
||||||
using Rounding::round;
|
using Rounding::round;
|
||||||
using Rounding::round_to;
|
using Rounding::round_to;
|
||||||
|
using Rounding::trunc;
|
||||||
|
|
||||||
namespace Division {
|
namespace Division {
|
||||||
template<FloatingPoint T>
|
template<FloatingPoint T>
|
||||||
|
|
Loading…
Reference in a new issue