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