1 /* { dg-do run } */
2 /* { dg-skip-if "PR68356 no math-errno on darwin" { "*-*-darwin*" } } */
3 /* { dg-add-options ieee } */
4 /* { dg-require-effective-target fenv_exceptions } */
5 /* { dg-skip-if "fenv" { powerpc-ibm-aix* } } */
6 
7 #include <fenv.h>
8 #include <math.h>
9 #include <errno.h>
10 
11 extern void abort (void) __attribute__ ((noreturn));
12 
13 #define LARGE_NEG_MAYBE_ERANGE 0x01
14 #define LARGE_NEG_ERANGE       0x02
15 #define LARGE_POS_ERANGE       0x04
16 #define LARGE_NEG_EDOM         0x08
17 #define LARGE_POS_EDOM         0x10
18 
19 #define LARGE_ERANGE (LARGE_NEG_ERANGE | LARGE_POS_ERANGE)
20 #define LARGE_EDOM (LARGE_NEG_EDOM | LARGE_POS_EDOM)
21 #define POWER_ERANGE (LARGE_NEG_MAYBE_ERANGE | LARGE_POS_ERANGE)
22 
23 #define TEST(CALL, FLAGS) (CALL, tester (FLAGS))
24 
25 volatile double d;
26 volatile int i;
27 
28 static void (*tester) (int);
29 
30 void
check_quiet_nan(int flags)31 check_quiet_nan (int flags __attribute__ ((unused)))
32 {
33   if (fetestexcept (FE_ALL_EXCEPT))
34     abort ();
35   if (errno)
36     abort ();
37 }
38 
39 void
check_large_neg(int flags)40 check_large_neg (int flags)
41 {
42   if (flags & LARGE_NEG_MAYBE_ERANGE)
43     return;
44   int expected_errno = (flags & LARGE_NEG_ERANGE ? ERANGE
45 			: flags & LARGE_NEG_EDOM ? EDOM
46 			: 0);
47   if (expected_errno != errno)
48     abort ();
49   errno = 0;
50 }
51 
52 void
check_large_pos(int flags)53 check_large_pos (int flags)
54 {
55   int expected_errno = (flags & LARGE_POS_ERANGE ? ERANGE
56 			: flags & LARGE_POS_EDOM ? EDOM
57 			: 0);
58   if (expected_errno != errno)
59     abort ();
60   errno = 0;
61 }
62 
63 void
test(void)64 test (void)
65 {
66   TEST (acos (d), LARGE_EDOM);
67   TEST (asin (d), LARGE_EDOM);
68   TEST (acosh (d), LARGE_NEG_EDOM);
69   TEST (atanh (d), LARGE_EDOM);
70   TEST (cosh (d), LARGE_ERANGE);
71   TEST (sinh (d), LARGE_ERANGE);
72   TEST (log (d), LARGE_NEG_EDOM);
73 #if defined (__sun__) && defined (__unix__)
74   /* Disabled due to a bug in Solaris libm.  */
75   if (0)
76 #endif
77     TEST (log2 (d), LARGE_NEG_EDOM);
78   TEST (log10 (d), LARGE_NEG_EDOM);
79 #if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 22))
80   /* Disabled due to glibc PR 6792, fixed in glibc 2.22.  */
81   if (0)
82 #endif
83     TEST (log1p (d), LARGE_NEG_EDOM);
84   TEST (exp (d), POWER_ERANGE);
85 #if (defined (__sun__) || defined(__hppa__)) && defined (__unix__)
86   /* Disabled due to a bug in Solaris libm.  HP PA-RISC libm doesn't support
87      ERANGE for exp2.  */
88   if (0)
89 #endif
90     {
91       TEST (exp2 (d), POWER_ERANGE);
92 #if defined(__GLIBC__) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 11))
93       /* Disabled due to glibc PR 6788, fixed in glibc 2.11.  */
94       if (0)
95 #endif
96 	TEST (expm1 (d), POWER_ERANGE);
97     }
98   TEST (sqrt (d), LARGE_NEG_EDOM);
99   TEST (pow (100.0, d), POWER_ERANGE);
100   TEST (pow (i, d), POWER_ERANGE);
101 }
102 
103 int
main(void)104 main (void)
105 {
106   errno = 0;
107   i = 100;
108   d = __builtin_nan ("");
109   tester = check_quiet_nan;
110   feclearexcept (FE_ALL_EXCEPT);
111   test ();
112 
113   d = -1.0e80;
114   tester = check_large_neg;
115   errno = 0;
116   test ();
117 
118   d = 1.0e80;
119   tester = check_large_pos;
120   errno = 0;
121   test ();
122 
123   return 0;
124 }
125