mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-18 23:07:07 -05:00
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:
1 parent
eecf909539
commit
e671332d2e
2 files changed
+13
-1
No files matched your search
@@ -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); }
|
||||
|
||||
@@ -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}) {
|
||||
|
||||
Reference in new issue
Block a user