/* { dg-do run } */ /* { dg-skip-if "PR68356 no math-errno on darwin" { "*-*-darwin*" } } */ /* { dg-add-options ieee } */ /* { dg-require-effective-target fenv_exceptions } */ /* { dg-skip-if "fenv" { powerpc-ibm-aix* } } */ #include #include #include extern void abort (void) __attribute__ ((noreturn)); #define LARGE_NEG_MAYBE_ERANGE 0x01 #define LARGE_NEG_ERANGE 0x02 #define LARGE_POS_ERANGE 0x04 #define LARGE_NEG_EDOM 0x08 #define LARGE_POS_EDOM 0x10 #define LARGE_ERANGE (LARGE_NEG_ERANGE | LARGE_POS_ERANGE) #define LARGE_EDOM (LARGE_NEG_EDOM | LARGE_POS_EDOM) #define POWER_ERANGE (LARGE_NEG_MAYBE_ERANGE | LARGE_POS_ERANGE) #define TEST(CALL, FLAGS) (CALL, tester (FLAGS)) volatile double d; volatile int i; static void (*tester) (int); void check_quiet_nan (int flags __attribute__ ((unused))) { if (fetestexcept (FE_ALL_EXCEPT)) abort (); if (errno) abort (); } void check_large_neg (int flags) { if (flags & LARGE_NEG_MAYBE_ERANGE) return; int expected_errno = (flags & LARGE_NEG_ERANGE ? ERANGE : flags & LARGE_NEG_EDOM ? EDOM : 0); if (expected_errno != errno) abort (); errno = 0; } void check_large_pos (int flags) { int expected_errno = (flags & LARGE_POS_ERANGE ? ERANGE : flags & LARGE_POS_EDOM ? EDOM : 0); if (expected_errno != errno) abort (); errno = 0; } void test (void) { TEST (acos (d), LARGE_EDOM); TEST (asin (d), LARGE_EDOM); TEST (acosh (d), LARGE_NEG_EDOM); TEST (atanh (d), LARGE_EDOM); TEST (cosh (d), LARGE_ERANGE); TEST (sinh (d), LARGE_ERANGE); TEST (log (d), LARGE_NEG_EDOM); #if defined (__sun__) && defined (__unix__) /* Disabled due to a bug in Solaris libm. */ if (0) #endif TEST (log2 (d), LARGE_NEG_EDOM); TEST (log10 (d), LARGE_NEG_EDOM); #if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 22)) /* Disabled due to glibc PR 6792, fixed in glibc 2.22. */ if (0) #endif TEST (log1p (d), LARGE_NEG_EDOM); TEST (exp (d), POWER_ERANGE); #if (defined (__sun__) || defined(__hppa__)) && defined (__unix__) /* Disabled due to a bug in Solaris libm. HP PA-RISC libm doesn't support ERANGE for exp2. */ if (0) #endif { TEST (exp2 (d), POWER_ERANGE); #if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 11)) /* Disabled due to glibc PR 6788, fixed in glibc 2.11. */ if (0) #endif TEST (expm1 (d), POWER_ERANGE); } TEST (sqrt (d), LARGE_NEG_EDOM); TEST (pow (100.0, d), POWER_ERANGE); TEST (pow (i, d), POWER_ERANGE); } int main (void) { errno = 0; i = 100; d = __builtin_nan (""); tester = check_quiet_nan; feclearexcept (FE_ALL_EXCEPT); test (); d = -1.0e80; tester = check_large_neg; errno = 0; test (); d = 1.0e80; tester = check_large_pos; errno = 0; test (); return 0; }