fix(libc): asin(|x| > 1) returns the x86 default NaN and leaves errno unchanged
On main asin(2.0) returns 0x7ff8000000000000 and sets errno to 33; FreeBSD msun (lib/msun/src/e_asin.c) returns 0xfff8000000000000 and never sets errno. asin now handles |x| > 1 itself with quiet comparisons, so a NaN input still raises no exception. For |x| <= 1 and for NaN the host function is still called. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
a11c8f7f70
commit
fba96d6422
|
|
@ -70,7 +70,13 @@ int APS5_VABI __isnormalf_nid_postfix(float x) { return std::isnormal(x) ? 1 : 0
|
|||
int APS5_VABI __isinff_nid_postfix(float x) { return std::isinf(x) ? 1 : 0; }
|
||||
|
||||
double APS5_VABI cbrt_nid_postfix(double x) { return std::cbrt(x); }
|
||||
double APS5_VABI asin_nid_postfix(double x) { return std::asin(x); }
|
||||
double APS5_VABI asin_nid_postfix(double x) {
|
||||
if (std::isgreater(x, 1.0) || std::isless(x, -1.0)) {
|
||||
std::feraiseexcept(FE_INVALID);
|
||||
return -std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
return std::asin(x);
|
||||
}
|
||||
double APS5_VABI acos_nid_postfix(double x) { return std::acos(x); }
|
||||
double APS5_VABI sqrt_nid_postfix(double x) { return std::sqrt(x); }
|
||||
float APS5_VABI sqrtf_nid_postfix(float x) { return std::sqrt(x); }
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ int APS5_VABI __fpclassifyf_nid_postfix(float);
|
|||
float APS5_VABI fmodf_nid_postfix(float, float);
|
||||
float APS5_VABI asinf_nid_postfix(float);
|
||||
float APS5_VABI acosf_nid_postfix(float);
|
||||
double APS5_VABI asin_nid_postfix(double);
|
||||
float APS5_VABI atan2f_nid_postfix(float, float);
|
||||
float APS5_VABI hypotf_nid_postfix(float, float);
|
||||
double APS5_VABI hypot_nid_postfix(double, double);
|
||||
|
|
@ -281,6 +282,36 @@ static void CheckIntegerConversions() {
|
|||
|
||||
static bool Near(double value, double expected, double tolerance) { return std::abs(value - expected) <= tolerance * std::abs(expected); }
|
||||
|
||||
static void CheckAsin() {
|
||||
const double pi = 3.14159265358979323846;
|
||||
const double pi_2 = pi / 2;
|
||||
const double nan = std::numeric_limits<double>::quiet_NaN();
|
||||
const double infinity = std::numeric_limits<double>::infinity();
|
||||
|
||||
Require(asin_nid_postfix(0.) == 0.);
|
||||
Require(std::signbit(asin_nid_postfix(-0.)));
|
||||
Require(Near(asin_nid_postfix(1.), pi_2, 1e-15));
|
||||
Require(Near(asin_nid_postfix(-1.), -pi_2, 1e-15));
|
||||
Require(std::isnan(asin_nid_postfix(2.0)) && std::signbit(asin_nid_postfix(2.0)));
|
||||
Require(std::isnan(asin_nid_postfix(-2.0)) && std::signbit(asin_nid_postfix(-2.0)));
|
||||
Require(std::isnan(asin_nid_postfix(infinity)) && std::signbit(asin_nid_postfix(infinity)));
|
||||
Require(std::isnan(asin_nid_postfix(-infinity)) && std::signbit(asin_nid_postfix(-infinity)));
|
||||
Require(std::isnan(asin_nid_postfix(nan)));
|
||||
Require(Near(asin_nid_postfix(0.5), pi/6, 1e-15));
|
||||
Require(Near(asin_nid_postfix(-0.5), -pi/6, 1e-15));
|
||||
Require(Near(asin_nid_postfix(1./std::sqrt(2)), pi/4, 1e-15));
|
||||
Require(asin_nid_postfix(1e-300) == 1e-300);
|
||||
Require(asin_nid_postfix(-1e-300) == -1e-300);
|
||||
std::feclearexcept(FE_ALL_EXCEPT);
|
||||
errno = 0;
|
||||
asin_nid_postfix(2.0);
|
||||
Require(std::fetestexcept(FE_INVALID));
|
||||
Require(errno == 0);
|
||||
std::feclearexcept(FE_ALL_EXCEPT);
|
||||
asin_nid_postfix(nan);
|
||||
Require(!std::fetestexcept(FE_INVALID));
|
||||
}
|
||||
|
||||
static void CheckHyperbolic() {
|
||||
const double infinity = std::numeric_limits<double>::infinity();
|
||||
Require(sinh_nid_postfix(0.) == 0. && std::signbit(sinh_nid_postfix(-0.)));
|
||||
|
|
@ -478,6 +509,7 @@ int main() {
|
|||
Require(__isnormalf_nid_postfix(std::numeric_limits<float>::denorm_min()) == 0);
|
||||
Require(__isnormal_nid_postfix(1.) == 1 && __isnormal_nid_postfix(0.) == 0);
|
||||
Require(__isnormal_nid_postfix(std::numeric_limits<double>::denorm_min()) == 0);
|
||||
CheckAsin();
|
||||
const auto quotient = div_nid_postfix(7, 2);
|
||||
Require(quotient.quot == 3 && quotient.rem == 1);
|
||||
const auto negativeNumerator = div_nid_postfix(-7, 2);
|
||||
|
|
|
|||
Loading…
Reference in New Issue