From 86b89d7de96df115690a9a161b4ee9381d61ba3b Mon Sep 17 00:00:00 2001 From: JJenkx Date: Wed, 28 Oct 2026 00:16:03 -0400 Subject: [PATCH] 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 --- core/libs/prx/libc/src/MathExact.cpp | 21 +++++---------------- core/libs/tests/GuestMathExact.cpp | 5 +++++ 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/core/libs/prx/libc/src/MathExact.cpp b/core/libs/prx/libc/src/MathExact.cpp index bbfe5114ef..e6f7d3849f 100644 --- a/core/libs/prx/libc/src/MathExact.cpp +++ b/core/libs/prx/libc/src/MathExact.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #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); diff --git a/core/libs/tests/GuestMathExact.cpp b/core/libs/tests/GuestMathExact.cpp index 5db64f610d..53b41df063 100644 --- a/core/libs/tests/GuestMathExact.cpp +++ b/core/libs/tests/GuestMathExact.cpp @@ -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(INFINITY), -static_cast(INFINITY), static_cast(NAN)}) { + Require(lrint_nid_postfix(outside) == INT64_MIN && llrint_nid_postfix(outside) == LLONG_MIN); + Require(lrintf_nid_postfix(static_cast(outside)) == INT64_MIN && llrintf_nid_postfix(static_cast(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);