mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-29 12:15:39 +00:00
fix(libc): return the integer indefinite from lrint and llrint out of range
Titles' libc.prx converts lrint, lrintf, llrint and llrintf with cvtsd2si and cvtss2si, so NaN, infinities and values outside the int64 range return INT64_MIN. On Windows they went through UCRT's llrint, which returns 0 there. Use the same SSE conversions. They round in the current mode, raise the same exception flags and leave errno alone. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
11760ab51b
commit
86b89d7de9
2 files changed
+10
-16
No files matched your search
@@ -5,6 +5,7 @@
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <emmintrin.h>
|
||||
#include <limits>
|
||||
|
||||
#include "prx/libc/include/General.hpp"
|
||||
@@ -179,25 +180,13 @@ long double APS5_VABI fmal_nid_postfix(long double x, long double y, long double
|
||||
double APS5_VABI rint_nid_postfix(double x) { return std::isnan(x) ? x + x : std::rint(x); }
|
||||
float APS5_VABI rintf_nid_postfix(float x) { return std::isnan(x) ? x + x : std::rint(x); }
|
||||
|
||||
std::int64_t APS5_VABI lrint_nid_postfix(double x) {
|
||||
ErrnoGuard guard;
|
||||
return std::llrint(x);
|
||||
}
|
||||
std::int64_t APS5_VABI lrint_nid_postfix(double x) { return _mm_cvtsd_si64(_mm_set_sd(x)); }
|
||||
|
||||
std::int64_t APS5_VABI lrintf_nid_postfix(float x) {
|
||||
ErrnoGuard guard;
|
||||
return std::llrint(x);
|
||||
}
|
||||
std::int64_t APS5_VABI lrintf_nid_postfix(float x) { return _mm_cvtss_si64(_mm_set_ss(x)); }
|
||||
|
||||
long long APS5_VABI llrint_nid_postfix(double x) {
|
||||
ErrnoGuard guard;
|
||||
return std::llrint(x);
|
||||
}
|
||||
long long APS5_VABI llrint_nid_postfix(double x) { return _mm_cvtsd_si64(_mm_set_sd(x)); }
|
||||
|
||||
long long APS5_VABI llrintf_nid_postfix(float x) {
|
||||
ErrnoGuard guard;
|
||||
return std::llrint(x);
|
||||
}
|
||||
long long APS5_VABI llrintf_nid_postfix(float x) { return _mm_cvtss_si64(_mm_set_ss(x)); }
|
||||
|
||||
double APS5_VABI drem_nid_postfix(double x, double y) {
|
||||
return Remainder(x, y);
|
||||
|
||||
@@ -103,6 +103,11 @@ static void CheckConsoleQuirks() {
|
||||
Require(scalblnl_nid_postfix(1.0L, INT64_C(0x100000001)) == 2.0L && scalblnl_nid_postfix(1.0L, INT64_MAX) == 0.5L);
|
||||
Require(scalbln_nid_postfix(1.0, INT64_C(0x100000001)) == INFINITY && scalbln_nid_postfix(1.0, INT64_MIN) == 0.0);
|
||||
Require(lrint_nid_postfix(0x1p40) == INT64_C(0x10000000000));
|
||||
for (const double outside : {0x1p63, -0x1p64, 1e300, static_cast<double>(INFINITY), -static_cast<double>(INFINITY), static_cast<double>(NAN)}) {
|
||||
Require(lrint_nid_postfix(outside) == INT64_MIN && llrint_nid_postfix(outside) == LLONG_MIN);
|
||||
Require(lrintf_nid_postfix(static_cast<float>(outside)) == INT64_MIN && llrintf_nid_postfix(static_cast<float>(outside)) == LLONG_MIN);
|
||||
}
|
||||
Require(lrint_nid_postfix(-0x1p63) == INT64_MIN && lrintf_nid_postfix(0x1.fffffep62f) == INT64_C(0x7fffff8000000000));
|
||||
const long double product = Extended(0x4000, 0xe000000000000000ull) * Extended(0x4001, 0xda76b022816f6a94ull);
|
||||
Require(SameBits(fmal_nid_postfix(Extended(0x4000, 0xe000000000000000ull), Extended(0x4001, 0xda76b022816f6a94ull), Extended(0x9b45, 0xd3b49eac84283c95ull)), product));
|
||||
Require(finite_nid_postfix(1.0) == 1 && finite_nid_postfix(INFINITY) == 0);
|
||||
|
||||
Reference in new issue
Block a user