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