Merge pull request #4942 from QRMOE/fix-libc-llroundl-upper-bound

fix(libc): accept the full llroundl integer range
This commit is contained in:
Dean 2026-10-14 14:29:14 +13:00 committed by GitHub
commit 34355eeeac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 1 deletions

View File

@ -18,7 +18,7 @@ namespace {
template<typename TFloat>
std::int64_t RoundToInt64(TFloat value) {
const TFloat rounded = std::round(value);
if (!(rounded >= static_cast<TFloat>(INT64_MIN) && rounded < static_cast<TFloat>(INT64_MAX))) {
if (!(rounded >= static_cast<TFloat>(INT64_MIN) && rounded < -static_cast<TFloat>(INT64_MIN))) {
std::feraiseexcept(FE_INVALID);
return INT64_MIN;
}

View File

@ -737,6 +737,17 @@ static void CheckFloatRounding(float value, std::int64_t expected, bool invalid)
}
}
static void CheckLongDoubleRounding(long double value, std::int64_t expected, bool invalid) {
std::feclearexcept(FE_ALL_EXCEPT);
errno = 12345;
const std::int64_t result = llroundl_nid_postfix(value);
if (result != expected || (std::fetestexcept(FE_INVALID) != 0) != invalid || errno != 12345) {
std::fprintf(stderr, "llroundl failed for %La: expected %lld, got %lld\n", value,
static_cast<long long>(expected), static_cast<long long>(result));
std::abort();
}
}
static void CheckNoConversionIsPositiveZero() {
for (const char* text : {"", " ", "-", "+", "-.", "+.", "-x", "-.e1", "-e5", "- 1", " -."}) {
char* end = nullptr;
@ -858,6 +869,21 @@ int main() {
Require(std::abs(lgamma_nid_postfix(-0.5) - 1.2655121234846454) < 1e-15);
Require(llroundl_nid_postfix(2.5L) == 3 && llroundl_nid_postfix(-2.5L) == -3 && llroundl_nid_postfix(0.49999999999999999L) == 0);
Require(llroundl_nid_postfix(9007199254740993.0L) == 9007199254740993LL && llroundl_nid_postfix(-1e30L) == INT64_MIN);
for (const int mode : {FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO}) {
Require(std::fesetround(mode) == 0);
CheckLongDoubleRounding(9223372036854775807.0L, INT64_MAX, false);
CheckLongDoubleRounding(9223372036854775806.5L, INT64_MAX, false);
CheckLongDoubleRounding(9223372036854775806.0L, INT64_MAX - 1, false);
CheckLongDoubleRounding(-0x1p63L, INT64_MIN, false);
CheckLongDoubleRounding(-9223372036854775807.5L, INT64_MIN, false);
CheckLongDoubleRounding(-9223372036854775807.0L, INT64_MIN + 1, false);
for (const long double value : {9223372036854775807.5L, 0x1p63L, -9223372036854775809.0L,
std::numeric_limits<long double>::infinity(), -std::numeric_limits<long double>::infinity(),
std::numeric_limits<long double>::quiet_NaN()}) {
CheckLongDoubleRounding(value, INT64_MIN, true);
}
}
Require(std::fesetround(FE_TONEAREST) == 0);
Require(logbf_nid_postfix(8.f) == 3.f && logbf_nid_postfix(-0.75f) == -1.f);
Require(logbf_nid_postfix(std::numeric_limits<float>::denorm_min()) == -149.f);
Require(logbf_nid_postfix(0.f) == -std::numeric_limits<float>::infinity());