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