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:
JJenkxandClaude Opus 5.5 committed 2026-10-28 00:16:15 -04:00
1 parent 11760ab51b
commit 86b89d7de9
2 files changed
+10 -16

No files matched your search

+5 -16
View File
@@ -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);
+5
View File
@@ -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);