1 | #ifndef _MATH_H |
2 | |
3 | #ifdef _ISOMAC |
4 | # undef NO_LONG_DOUBLE |
5 | #endif |
6 | |
7 | #include <math/math.h> |
8 | |
9 | #ifndef _ISOMAC |
10 | /* Now define the internal interfaces. */ |
11 | extern int __signgam; |
12 | |
13 | # if IS_IN (libc) || IS_IN (libm) |
14 | hidden_proto (__finite) |
15 | hidden_proto (__isinf) |
16 | hidden_proto (__isnan) |
17 | hidden_proto (__finitef) |
18 | hidden_proto (__isinff) |
19 | hidden_proto (__isnanf) |
20 | |
21 | # if !defined __NO_LONG_DOUBLE_MATH \ |
22 | && __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 0 |
23 | hidden_proto (__finitel) |
24 | hidden_proto (__isinfl) |
25 | hidden_proto (__isnanl) |
26 | # endif |
27 | |
28 | # if __HAVE_DISTINCT_FLOAT128 |
29 | hidden_proto (__finitef128) |
30 | hidden_proto (__isinff128) |
31 | hidden_proto (__isnanf128) |
32 | # endif |
33 | # endif |
34 | |
35 | libm_hidden_proto (__fpclassify) |
36 | libm_hidden_proto (__fpclassifyf) |
37 | libm_hidden_proto (__issignaling) |
38 | libm_hidden_proto (__issignalingf) |
39 | libm_hidden_proto (__exp) |
40 | libm_hidden_proto (__expf) |
41 | libm_hidden_proto (__roundeven) |
42 | |
43 | # if !defined __NO_LONG_DOUBLE_MATH \ |
44 | && __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 0 |
45 | libm_hidden_proto (__fpclassifyl) |
46 | libm_hidden_proto (__issignalingl) |
47 | libm_hidden_proto (__expl) |
48 | libm_hidden_proto (__expm1l) |
49 | # endif |
50 | |
51 | # if __HAVE_DISTINCT_FLOAT128 |
52 | libm_hidden_proto (__fpclassifyf128) |
53 | libm_hidden_proto (__issignalingf128) |
54 | libm_hidden_proto (__expf128) |
55 | libm_hidden_proto (__expm1f128) |
56 | # endif |
57 | |
58 | #include <stdint.h> |
59 | #include <nan-high-order-bit.h> |
60 | |
61 | /* A union which permits us to convert between a float and a 32 bit |
62 | int. */ |
63 | |
64 | typedef union |
65 | { |
66 | float value; |
67 | uint32_t word; |
68 | } ieee_float_shape_type; |
69 | |
70 | /* Get a 32 bit int from a float. */ |
71 | #ifndef GET_FLOAT_WORD |
72 | # define GET_FLOAT_WORD(i,d) \ |
73 | do { \ |
74 | ieee_float_shape_type gf_u; \ |
75 | gf_u.value = (d); \ |
76 | (i) = gf_u.word; \ |
77 | } while (0) |
78 | #endif |
79 | |
80 | /* Set a float from a 32 bit int. */ |
81 | #ifndef SET_FLOAT_WORD |
82 | # define SET_FLOAT_WORD(d,i) \ |
83 | do { \ |
84 | ieee_float_shape_type sf_u; \ |
85 | sf_u.word = (i); \ |
86 | (d) = sf_u.value; \ |
87 | } while (0) |
88 | #endif |
89 | |
90 | extern inline int |
91 | __issignalingf (float x) |
92 | { |
93 | uint32_t xi; |
94 | GET_FLOAT_WORD (xi, x); |
95 | #if HIGH_ORDER_BIT_IS_SET_FOR_SNAN |
96 | /* We only have to care about the high-order bit of x's significand, because |
97 | having it set (sNaN) already makes the significand different from that |
98 | used to designate infinity. */ |
99 | return (xi & 0x7fc00000) == 0x7fc00000; |
100 | #else |
101 | /* To keep the following comparison simple, toggle the quiet/signaling bit, |
102 | so that it is set for sNaNs. This is inverse to IEEE 754-2008 (as well as |
103 | common practice for IEEE 754-1985). */ |
104 | xi ^= 0x00400000; |
105 | /* We have to compare for greater (instead of greater or equal), because x's |
106 | significand being all-zero designates infinity not NaN. */ |
107 | return (xi & 0x7fffffff) > 0x7fc00000; |
108 | #endif |
109 | } |
110 | |
111 | # if __HAVE_DISTINCT_FLOAT128 |
112 | |
113 | /* __builtin_isinf_sign is broken in GCC < 7 for float128. */ |
114 | # if ! __GNUC_PREREQ (7, 0) |
115 | # include <ieee754_float128.h> |
116 | extern inline int |
117 | __isinff128 (_Float128 x) |
118 | { |
119 | int64_t hx, lx; |
120 | GET_FLOAT128_WORDS64 (hx, lx, x); |
121 | lx |= (hx & 0x7fffffffffffffffLL) ^ 0x7fff000000000000LL; |
122 | lx |= -lx; |
123 | return ~(lx >> 63) & (hx >> 62); |
124 | } |
125 | # endif |
126 | |
127 | extern inline _Float128 |
128 | fabsf128 (_Float128 x) |
129 | { |
130 | return __builtin_fabsf128 (x); |
131 | } |
132 | # endif |
133 | |
134 | # if !(defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0) |
135 | # ifndef NO_MATH_REDIRECT |
136 | /* Declare some functions for use within GLIBC. Compilers typically |
137 | inline those functions as a single instruction. Use an asm to |
138 | avoid use of PLTs if it doesn't. */ |
139 | # define MATH_REDIRECT(FUNC, PREFIX, ARGS) \ |
140 | float (FUNC ## f) (ARGS (float)) asm (PREFIX #FUNC "f"); \ |
141 | double (FUNC) (ARGS (double)) asm (PREFIX #FUNC ); \ |
142 | MATH_REDIRECT_LDBL (FUNC, PREFIX, ARGS) \ |
143 | MATH_REDIRECT_F128 (FUNC, PREFIX, ARGS) |
144 | # if defined __NO_LONG_DOUBLE_MATH \ |
145 | || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1 |
146 | # define MATH_REDIRECT_LDBL(FUNC, PREFIX, ARGS) |
147 | # else |
148 | # define MATH_REDIRECT_LDBL(FUNC, PREFIX, ARGS) \ |
149 | long double (FUNC ## l) (ARGS (long double)) asm (PREFIX #FUNC "l"); |
150 | # endif |
151 | # if __HAVE_DISTINCT_FLOAT128 |
152 | # define MATH_REDIRECT_F128(FUNC, PREFIX, ARGS) \ |
153 | _Float128 (FUNC ## f128) (ARGS (_Float128)) asm (PREFIX #FUNC "f128"); |
154 | # else |
155 | # define MATH_REDIRECT_F128(FUNC, PREFIX, ARGS) |
156 | # endif |
157 | # define MATH_REDIRECT_UNARY_ARGS(TYPE) TYPE |
158 | # define MATH_REDIRECT_BINARY_ARGS(TYPE) TYPE, TYPE |
159 | MATH_REDIRECT (sqrt, "__ieee754_" , MATH_REDIRECT_UNARY_ARGS) |
160 | MATH_REDIRECT (ceil, "__" , MATH_REDIRECT_UNARY_ARGS) |
161 | MATH_REDIRECT (floor, "__" , MATH_REDIRECT_UNARY_ARGS) |
162 | MATH_REDIRECT (rint, "__" , MATH_REDIRECT_UNARY_ARGS) |
163 | MATH_REDIRECT (trunc, "__" , MATH_REDIRECT_UNARY_ARGS) |
164 | MATH_REDIRECT (round, "__" , MATH_REDIRECT_UNARY_ARGS) |
165 | MATH_REDIRECT (copysign, "__" , MATH_REDIRECT_BINARY_ARGS) |
166 | # endif |
167 | # endif |
168 | |
169 | #endif |
170 | #endif |
171 | |