fix(libc): keep lgamma finite for subnormal arguments on Windows

The MinGW-w64 lgamma overflows to infinity for nonzero |x| at or below 2^-1024. FreeBSD msun e_lgamma_r.c returns -log(|x|) for every nonzero |x| below 2^-56, so take that branch before the host function.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Muhammad Wasif Ali WasifandClaude Opus 5.5 committed 2026-10-14 15:03:50 +05:00
1 parent eecf909539
commit e671332d2e
2 files changed
+13 -1

No files matched your search

+5 -1
View File
@@ -300,7 +300,11 @@ float APS5_VABI log1pf_nid_postfix(float x) { return std::log1p(x); }
double APS5_VABI expm1_nid_postfix(double x) { return std::expm1(x); }
float APS5_VABI expm1f_nid_postfix(float x) { return std::expm1(x); }
float APS5_VABI erff_nid_postfix(float x) { return std::erf(x); }
double APS5_VABI lgamma_nid_postfix(double x) { return std::lgamma(x); }
double APS5_VABI lgamma_nid_postfix(double x) {
const std::uint64_t magnitude = std::bit_cast<std::uint64_t>(x) & 0x7fffffffffffffffull;
if (magnitude != 0 && magnitude < 0x3c70000000000000ull) return -std::log(std::fabs(x));
return std::lgamma(x);
}
float APS5_VABI sinf_nid_postfix(float x) { return std::sin(x); }
float APS5_VABI cosf_nid_postfix(float x) { return std::cos(x); }
+8
View File
@@ -867,6 +867,14 @@ int main() {
Require(lgamma_nid_postfix(1.) == 0. && lgamma_nid_postfix(2.) == 0. && std::isinf(lgamma_nid_postfix(0.)));
Require(std::abs(lgamma_nid_postfix(0.5) - 0.5723649429247001) < 1e-15 && std::abs(lgamma_nid_postfix(10.) - 12.801827480081469) < 1e-13);
Require(std::abs(lgamma_nid_postfix(-0.5) - 1.2655121234846454) < 1e-15);
for (const double sign : {1.0, -1.0}) {
std::feclearexcept(FE_ALL_EXCEPT);
Require(std::abs(lgamma_nid_postfix(sign * std::numeric_limits<double>::denorm_min()) - 744.44007192138122) < 1e-12);
Require(std::abs(lgamma_nid_postfix(sign * 0x1p-1025) - 710.47586007394398) < 1e-12);
Require(std::abs(lgamma_nid_postfix(sign * 0x1p-1022) - 708.39641853226408) < 1e-12);
Require(std::abs(lgamma_nid_postfix(sign * 0x1p-57) - 39.509389291916882) < 1e-13);
Require(std::fetestexcept(FE_OVERFLOW | FE_DIVBYZERO | FE_INVALID) == 0);
}
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}) {