static T nextafter_impl(T from, T to) { if (mwg::stdm::isnan(from) || mwg::stdm::isnan(to)) return NAN; if (from == to) return to; if (mwg::stdm::isinf(from)) return from > T(0.0)? mwg::stdm::numeric_limits<T>::max(): mwg::stdm::numeric_limits<T>::lowest(); if (from == 0.0) return mwg::stdm::copysign(mwg::stdm::numeric_limits<T>::min(), to); int const exp = mwg::stdm::logb(from); T man = mwg::stdm::scalbn(from, -exp); if (from < to) man += std::numeric_limits<T>::epsilon(); else man -= std::numeric_limits<T>::epsilon(); T const next = mwg::stdm::scalbn(man, exp); if (mwg::stdm::isinf(next)) feraiseexcept(FE_INEXACT | FE_OVERFLOW); else if (next == 0.0 || !mwg::stdm::isnormal(next)) feraiseexcept(FE_INEXACT | FE_UNDERFLOW); return next; }
double fdlibm_setexception(double x, enum FDLIBM_EXCEPTION type) { double ret; switch (type) { case FDLIBM_DIVIDE_BY_ZERO: /* Division by zero. Use the sign of x to get the correct * signed infinity */ feraiseexcept(FE_DIVBYZERO); ret = copysign(INFINITY, x); break; case FDLIBM_UNDERFLOW: /* Underflow. Use the sign of x to get a signed zero. */ feraiseexcept(FE_UNDERFLOW); ret = copysign(0.0, x); break; case FDLIBM_OVERFLOW: /* overflow */ feraiseexcept(FE_OVERFLOW); ret = copysign(INFINITY, x); break; case FDLIBM_INVALID: { /* invalid */ if (!isQNaN(x)) { /* * If it's not a quiet NaN, we want to signal an invalid * operation. Otherwise, we silently return a NaN. */ feraiseexcept(FE_INVALID); } /* * FIXME: Of the many NaN values that we have, what NaN * should we return? */ union { int i[2]; double d; } ux; ux.i[HIWORD] = 0x7ff80000; ux.i[LOWORD] = 0xdeadbeef; ret = ux.d; break; } case FDLIBM_INEXACT: feraiseexcept(FE_INEXACT); ret = x; break; default: /* Shouldn't happen! */ ret = 0.0; break; } return ret; }
/* wrapper yn */ double yn (int n, double x) { if (__builtin_expect (islessequal (x, 0.0) || isgreater (x, X_TLOSS), 0) && _LIB_VERSION != _IEEE_) { if (x < 0.0) { /* d = zero/(x-x) */ feraiseexcept (FE_INVALID); return __kernel_standard (n, x, 13); } else if (x == 0.0) { /* d = -one/(x-x) */ feraiseexcept (FE_DIVBYZERO); return __kernel_standard (n, x, 12); } else if (_LIB_VERSION != _POSIX_) /* yn(n,x>X_TLOSS) */ return __kernel_standard (n, x, 39); } return __ieee754_yn (n, x); }
static void set_single_exc (const char *test_name, int fe_exc, fexcept_t exception) { char str[200]; /* The standard allows the inexact exception to be set together with the underflow and overflow exceptions. So ignore the inexact flag if the others are raised. */ int ignore_inexact = (fe_exc & (UNDERFLOW_EXC | OVERFLOW_EXC)) != 0; strcpy (str, test_name); strcat (str, ": set flag, with rest not set"); feclearexcept (FE_ALL_EXCEPT); feraiseexcept (exception); test_exceptions (str, fe_exc, ignore_inexact); strcpy (str, test_name); strcat (str, ": clear flag, rest also unset"); feclearexcept (exception); test_exceptions (str, NO_EXC, ignore_inexact); strcpy (str, test_name); strcat (str, ": set flag, with rest set"); feraiseexcept (FE_ALL_EXCEPT ^ exception); feraiseexcept (exception); test_exceptions (str, ALL_EXC, 0); strcpy (str, test_name); strcat (str, ": clear flag, leave rest set"); feclearexcept (exception); test_exceptions (str, ALL_EXC ^ fe_exc, 0); }
static int do_test (void) { /* clear all exceptions and test if all are cleared */ feclearexcept (FE_ALL_EXCEPT); test_exceptions ("feclearexcept (FE_ALL_EXCEPT) clears all exceptions", NO_EXC); /* raise all exceptions and test if all are raised */ feraiseexcept (FE_ALL_EXCEPT); if (EXCEPTION_TESTS (float)) test_exceptions ("feraiseexcept (FE_ALL_EXCEPT) raises all exceptions", ALL_EXC); /* Same test, but using double as argument */ feclearexcept ((double)FE_ALL_EXCEPT); test_exceptions ("feclearexcept ((double)FE_ALL_EXCEPT) clears all exceptions", NO_EXC); feraiseexcept ((double)FE_ALL_EXCEPT); if (EXCEPTION_TESTS (float)) test_exceptions ("feraiseexcept ((double)FE_ALL_EXCEPT) raises all exceptions", ALL_EXC); if (EXCEPTION_TESTS (float)) test_exceptionflag (); test_fesetround (); test_feenabledisable (); return count_errors; }
/* * Test feraiseexcept(). * * Prerequisites: fetestexcept(), feclearexcept() */ static void test_feraiseexcept(void) { int excepts, i; for (i = 0; i < 1 << NEXCEPTS; i++) { excepts = std_except_sets[i]; assert(fetestexcept(FE_ALL_EXCEPT) == 0); assert(feraiseexcept(excepts) == 0); if ((excepts & (FE_UNDERFLOW | FE_OVERFLOW)) != 0) { excepts |= FE_INEXACT; assert((fetestexcept(ALL_STD_EXCEPT) | FE_INEXACT) == excepts); } else { assert(fetestexcept(ALL_STD_EXCEPT) == excepts); } assert(feclearexcept(FE_ALL_EXCEPT) == 0); } assert(feraiseexcept(FE_INVALID | FE_DIVBYZERO) == 0); assert(fetestexcept(ALL_STD_EXCEPT) == (FE_INVALID | FE_DIVBYZERO)); assert(feraiseexcept(FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) == 0); assert(fetestexcept(ALL_STD_EXCEPT) == ALL_STD_EXCEPT); assert(feclearexcept(FE_ALL_EXCEPT) == 0); }
/* wrapper y1f */ float y1f (float x) { if (__builtin_expect (islessequal (x, 0.0f) || isgreater (x, (float) X_TLOSS), 0) && _LIB_VERSION != _IEEE_) { if (x < 0.0f) { /* d = zero/(x-x) */ feraiseexcept (FE_INVALID); return __kernel_standard_f (x, x, 111); } else if (x == 0.0f) { /* d = -one/(x-x) */ feraiseexcept (FE_DIVBYZERO); return __kernel_standard_f (x, x, 110); } else if (_LIB_VERSION != _POSIX_) /* y1(x>X_TLOSS) */ return __kernel_standard_f (x, x, 137); } return __ieee754_y1f (x); }
/* wrapper y0l */ long double y0l (long double x) { # if defined(__UCLIBC_HAS_FENV__) if (__builtin_expect (islessequal (x, 0.0L) || isgreater (x, X_TLOSS), 0) && _LIB_VERSION != _IEEE_) { if (x < 0.0L) { /* d = zero/(x-x) */ feraiseexcept (FE_INVALID); return __kernel_standard_l (x, x, 209); } else if (x == 0.0L) { /* d = -one/(x-x) */ feraiseexcept (FE_DIVBYZERO); return __kernel_standard_l (x, x, 208); } else if (_LIB_VERSION != _POSIX_) /* y0(x>X_TLOSS) */ return __kernel_standard_l (x, x, 235); } # endif /* __UCLIBC_HAS_FENV__ */ return (long double)__ieee754_y0 ((double) x); }
__complex__ double __ccos (__complex__ double x) { __complex__ double res; if (!isfinite (__real__ x) || __isnan (__imag__ x)) { if (__real__ x == 0.0 || __imag__ x == 0.0) { __real__ res = __nan (""); __imag__ res = 0.0; #ifdef FE_INVALID if (__isinf (__real__ x)) feraiseexcept (FE_INVALID); #endif } else if (__isinf (__imag__ x)) { __real__ res = HUGE_VAL; __imag__ res = __nan (""); #ifdef FE_INVALID if (__isinf (__real__ x)) feraiseexcept (FE_INVALID); #endif } else { __real__ res = __nan (""); __imag__ res = __nan (""); #ifdef FE_INVALID if (isfinite (__imag__ x)) feraiseexcept (FE_INVALID); #endif } } else { __complex__ double y; __real__ y = -__imag__ x; __imag__ y = __real__ x; res = __ccosh (y); } return res; }
__complex__ float __ccosf (__complex__ float x) { __complex__ float res; if (!isfinite (__real__ x) || __isnanf (__imag__ x)) { if (__real__ x == 0.0 || __imag__ x == 0.0) { __real__ res = __nanf (""); __imag__ res = 0.0; #ifdef FE_INVALID if (__isinff (__real__ x)) feraiseexcept (FE_INVALID); #endif } else if (__isinff (__imag__ x)) { __real__ res = HUGE_VALF; __imag__ res = __nanf (""); #ifdef FE_INVALID if (__isinff (__real__ x)) feraiseexcept (FE_INVALID); #endif } else { __real__ res = __nanf (""); __imag__ res = __nanf (""); #ifdef FE_INVALID if (isfinite (__imag__ x)) feraiseexcept (FE_INVALID); #endif } } else { __complex__ float y; __real__ y = -__imag__ x; __imag__ y = __real__ x; res = __ccoshf (y); } return res; }
double _IEEE_REMAINDER_H_R(float argx, double argy) { union _ieee_double { double dword; long lword; }; double __remainder_r(double x, double y); double x_val; int xfpclas = _fpclassifyf(argx); int yfpclas = _fpclassify(argy); if ((xfpclas == FP_INFINITE) || yfpclas == FP_ZERO) { union _ieee_double x_val; int j; x_val.dword = _SGL_NaN; /* need to emit invalid exception */ j = FE_INVALID; feraiseexcept(j); return(x_val.dword); } x_val = (double) argx; return(__remainder_r(x_val, argy)); }
int ilogbq (__float128 x) { int64_t hx,lx; int ix; GET_FLT128_WORDS64(hx,lx,x); hx &= 0x7fffffffffffffffLL; if(hx <= 0x0001000000000000LL) { if((hx|lx)==0) { errno = EDOM; #ifdef USE_FENV_H feraiseexcept (FE_INVALID); #endif return FP_ILOGB0; /* ilogbl(0) = FP_ILOGB0 */ } else /* subnormal x */ if(hx==0) { for (ix = -16431; lx>0; lx<<=1) ix -=1; } else { for (ix = -16382, hx<<=15; hx>0; hx<<=1) ix -=1; } return ix; } else if (hx<0x7fff000000000000LL) return (hx>>48)-0x3fff; else if (FP_ILOGBNAN != INT_MAX) {
long double _IEEE_REMAINDER_D_H(long double argx, float argy) { union _ieee_ldouble { long double ldword; long lword[2]; }; long double __remainder_d(long double x, long double y); long double y_val; int xfpclas = _fpclassifyl(argx); int yfpclas = _fpclassifyf(argy); if ((xfpclas == FP_INFINITE) || yfpclas == FP_ZERO) { union _ieee_ldouble xval; int j; xval.ldword = _DBL_NaN; /* need to emit invalid exception */ j = FE_INVALID; feraiseexcept(j); return(xval.ldword); } y_val = (long double) argy; return(__remainder_d(argx, y_val)); }
DEC_TYPE PREFIXED_FUNCTION_NAME (DEC_TYPE x, DEC_TYPE y) { DEC_TYPE result; decNumber dn_x, dn_y, dn_result; decContext context; decContextDefault(&context, DEFAULT_CONTEXT); FUNC_CONVERT_TO_DN(&x, &dn_x); FUNC_CONVERT_TO_DN(&y, &dn_y); decNumberSubtract(&dn_result, &dn_x, &dn_y, &context); if (context.status != 0) { int ieee_flags = 0; if (context.status & DEC_IEEE_854_Division_by_zero) ieee_flags |= FE_DIVBYZERO; if (context.status & DEC_IEEE_854_Inexact) ieee_flags |= FE_INEXACT; if (context.status & DEC_IEEE_854_Invalid_operation) ieee_flags |= FE_INVALID; if (context.status & DEC_IEEE_854_Overflow) ieee_flags |= FE_OVERFLOW; if (context.status & DEC_IEEE_854_Underflow) ieee_flags |= FE_UNDERFLOW; if (ieee_flags != 0) feraiseexcept (ieee_flags); } FUNC_CONVERT_FROM_DN (&dn_result, &result, &context); return result; }
TEST(fenv, feraiseexcept) { feclearexcept(FE_ALL_EXCEPT); ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT)); ASSERT_EQ(0, feraiseexcept(FE_DIVBYZERO | FE_OVERFLOW)); ASSERT_EQ(FE_DIVBYZERO | FE_OVERFLOW, fetestexcept(FE_ALL_EXCEPT)); }
TEST(fenv, feenableexcept_fegetexcept) { #if defined(__aarch64__) || defined(__arm__) // ARM doesn't support this. They used to if you go back far enough, but it was removed in // the Cortex-A8 between r3p1 and r3p2. ASSERT_EQ(-1, feenableexcept(FE_INVALID)); ASSERT_EQ(0, fegetexcept()); ASSERT_EQ(-1, feenableexcept(FE_DIVBYZERO)); ASSERT_EQ(0, fegetexcept()); ASSERT_EQ(-1, feenableexcept(FE_OVERFLOW)); ASSERT_EQ(0, fegetexcept()); ASSERT_EQ(-1, feenableexcept(FE_UNDERFLOW)); ASSERT_EQ(0, fegetexcept()); ASSERT_EQ(-1, feenableexcept(FE_INEXACT)); ASSERT_EQ(0, fegetexcept()); ASSERT_EQ(-1, feenableexcept(FE_DENORMAL)); ASSERT_EQ(0, fegetexcept()); #else // We can't recover from SIGFPE, so sacrifice a child... pid_t pid = fork(); ASSERT_NE(-1, pid) << strerror(errno); if (pid == 0) { feclearexcept(FE_ALL_EXCEPT); ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT)); ASSERT_EQ(0, feenableexcept(FE_INVALID)); ASSERT_EQ(FE_INVALID, fegetexcept()); ASSERT_EQ(0, feraiseexcept(FE_INVALID)); _exit(123); } AssertChildExited(pid, -SIGFPE); #endif }
TEST(fenv, fegetexceptflag_fesetexceptflag) { // Set three flags. feclearexcept(FE_ALL_EXCEPT); ASSERT_EQ(0, feraiseexcept(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW)); ASSERT_EQ(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW, fetestexcept(FE_ALL_EXCEPT)); fexcept_t all; // FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW fexcept_t two; // FE_OVERFLOW | FE_UNDERFLOW ASSERT_EQ(0, fegetexceptflag(&all, FE_ALL_EXCEPT)); ASSERT_EQ(0, fegetexceptflag(&two, FE_OVERFLOW | FE_UNDERFLOW)); // Check we can restore all. feclearexcept(FE_ALL_EXCEPT); ASSERT_EQ(0, fesetexceptflag(&all, FE_ALL_EXCEPT)); ASSERT_EQ(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW, fetestexcept(FE_ALL_EXCEPT)); // Check that `two` only stored a subset. feclearexcept(FE_ALL_EXCEPT); ASSERT_EQ(0, fesetexceptflag(&two, FE_ALL_EXCEPT)); ASSERT_EQ(FE_OVERFLOW | FE_UNDERFLOW, fetestexcept(FE_ALL_EXCEPT)); // Check that we can restore a single flag. feclearexcept(FE_ALL_EXCEPT); ASSERT_EQ(0, fesetexceptflag(&all, FE_DIVBYZERO)); ASSERT_EQ(FE_DIVBYZERO, fetestexcept(FE_ALL_EXCEPT)); // Check that we can restore a subset of flags. feclearexcept(FE_ALL_EXCEPT); ASSERT_EQ(0, fesetexceptflag(&all, FE_OVERFLOW | FE_UNDERFLOW)); ASSERT_EQ(FE_OVERFLOW | FE_UNDERFLOW, fetestexcept(FE_ALL_EXCEPT)); }
int feupdateenv(const fenv_t *envp) { int ex = fetestexcept(FE_ALL_EXCEPT); fesetenv(envp); feraiseexcept(ex); return 0; }
int CLuaHandle::RunCallInTraceback(int inArgs, int outArgs, int errfuncIndex, std::string& traceback) { #if defined(__SUPPORT_SNAN__) // do not signal floating point exceptions in user Lua code feclearexcept(streflop::FPU_Exceptions(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW)); #endif CLuaHandle* orig = activeHandle; SetActiveHandle(); const int error = lua_pcall(L, inArgs, outArgs, errfuncIndex); SetActiveHandle(orig); if (error == 0) { // pop the error handler if (errfuncIndex != 0) { lua_remove(L, errfuncIndex); } } else { traceback = lua_tostring(L, -1); lua_pop(L, 1); if (errfuncIndex != 0) lua_remove(L, errfuncIndex); // log only errors that lead to a crash callinErrors += (error == 2); } #if defined(__SUPPORT_SNAN__) feraiseexcept(streflop::FPU_Exceptions(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW)); #endif return error; }
long double _IEEE_REMAINDER_R_D(double argx, long double argy) { union _ieee_ldouble { long double dword; long lword[2]; }; long double __remainder_d(long double x, long double y); long double x_val; int xfpclas = _fpclassify(argx); int yfpclas = _fpclassifyl(argy); if ((xfpclas == FP_NAN) || yfpclas == FP_ZERO) { union _ieee_ldouble x_val; int j; x_val.dword = _DBL_NaN; /* need to emit invalid exception */ j = FE_INVALID; feraiseexcept(j); return(x_val.dword); } x_val = (long double) argx; return(__remainder_d(x_val, argy)); }
static void fe_tests (void) { /* clear all exceptions and test if all are cleared */ feclearexcept (FE_ALL_EXCEPT); test_exceptions ("feclearexcept (FE_ALL_EXCEPT) clears all exceptions", NO_EXC, 0); /* raise all exceptions and test if all are raised */ feraiseexcept (FE_ALL_EXCEPT); test_exceptions ("feraiseexcept (FE_ALL_EXCEPT) raises all exceptions", ALL_EXC, 0); feclearexcept (FE_ALL_EXCEPT); #ifdef FE_DIVBYZERO set_single_exc ("Set/Clear FE_DIVBYZERO", DIVBYZERO_EXC, FE_DIVBYZERO); #endif #ifdef FE_INVALID set_single_exc ("Set/Clear FE_INVALID", INVALID_EXC, FE_INVALID); #endif #ifdef FE_INEXACT set_single_exc ("Set/Clear FE_INEXACT", INEXACT_EXC, FE_INEXACT); #endif #ifdef FE_UNDERFLOW set_single_exc ("Set/Clear FE_UNDERFLOW", UNDERFLOW_EXC, FE_UNDERFLOW); #endif #ifdef FE_OVERFLOW set_single_exc ("Set/Clear FE_OVERFLOW", OVERFLOW_EXC, FE_OVERFLOW); #endif }
int feupdateenv(const fenv_t *envp) { #pragma STDC FENV_ACCESS ON int ex = fetestexcept(FE_ALL_EXCEPT); fesetenv(envp); feraiseexcept(ex); return 0; }
/* Test that program aborts with no masked interrupts */ static void feenv_nomask_test (const char *flag_name, int fe_exc) { #if defined FE_NOMASK_ENV int status; pid_t pid; if (!EXCEPTION_ENABLE_SUPPORTED (FE_ALL_EXCEPT) && fesetenv (FE_NOMASK_ENV) != 0) { printf ("Test: not testing FE_NOMASK_ENV, it isn't implemented.\n"); return; } printf ("Test: after fesetenv (FE_NOMASK_ENV) processes will abort\n"); printf (" when feraiseexcept (%s) is called.\n", flag_name); pid = fork (); if (pid == 0) { #ifdef RLIMIT_CORE /* Try to avoid dumping core. */ struct rlimit core_limit; core_limit.rlim_cur = 0; core_limit.rlim_max = 0; setrlimit (RLIMIT_CORE, &core_limit); #endif fesetenv (FE_NOMASK_ENV); feraiseexcept (fe_exc); exit (2); } else if (pid < 0) { if (errno != ENOSYS) { printf (" Fail: Could not fork.\n"); ++count_errors; } else printf (" `fork' not implemented, test ignored.\n"); } else { if (waitpid (pid, &status, 0) != pid) { printf (" Fail: waitpid call failed.\n"); ++count_errors; } else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGFPE) printf (" Pass: Process received SIGFPE.\n"); else { printf (" Fail: Process didn't receive signal and exited with status %d.\n", status); ++count_errors; } } #endif }
static void raise_exception (void) { if (feraiseexcept (FE_INVALID) == 0) expected_exceptions = FE_INVALID; else puts ("feraiseexcept (FE_INVALID) failed, continuing test"); longjmp (env, 1); }
int main() { feraiseexcept(FE_ALL_EXCEPT); fn(0.0); if (fetestexcept(FE_INVALID)) printf("FE_INVALID raised\n"); return 0; }
static R lint_impl(T value) { if (mwg::stdm::isnan(value)) { feraiseexcept(FE_INVALID); return (R) 0; } if (value < mwg::stdm::numeric_limits<R>::lowest()) { feraiseexcept(FE_INVALID); return mwg::stdm::numeric_limits<R>::lowest(); } if (mwg::stdm::numeric_limits<R>::max() < value) { feraiseexcept(FE_INVALID); return mwg::stdm::numeric_limits<R>::max(); } return (R) value; }
int feupdateenv(const fenv_t *p) { unsigned long fsr; __fenv_getfsr(&fsr); (void) fesetenv(p); (void) feraiseexcept((int)__fenv_get_ex(fsr)); return 0; }
/* wrapper logf(x) */ float __logf (float x) { if (__builtin_expect (x <= 0.0f, 0) && _LIB_VERSION != _IEEE_) { if (x == 0.0f) { feraiseexcept (FE_DIVBYZERO); return __kernel_standard_f (x, x, 116); /* log(0) */ } else { feraiseexcept (FE_INVALID); return __kernel_standard_f (x, x, 117); /* log(x<0) */ } } return __ieee754_logf (x); }
_STD_BEGIN int (feupdateenv)(const fenv_t *penv) { /* merge in stored floating-point environment */ int except = fetestexcept(FE_ALL_EXCEPT); fesetenv(penv); feraiseexcept(except); return (0); }
/* wrapper log10l(x) */ long double __log10l (long double x) { if (__builtin_expect (islessequal (x, 0.0L), 0) && _LIB_VERSION != _IEEE_) { if (x == 0.0L) { feraiseexcept (FE_DIVBYZERO); return __kernel_standard_l (x, x, 218); /* log10(0) */ } else { feraiseexcept (FE_INVALID); return __kernel_standard_l (x, x, 219); /* log10(x<0) */ } } return __ieee754_log10l (x); }