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