Remove powerpc, sparc fdim inlines (bug 22987).
[glibc.git] / math / math-narrow.h
bloba062b8db058bc079cc189f473e5d9bf0fad1ce47
1 /* Helper macros for functions returning a narrower type.
2 Copyright (C) 2018 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 #ifndef _MATH_NARROW_H
20 #define _MATH_NARROW_H 1
22 #include <bits/floatn.h>
23 #include <bits/long-double.h>
24 #include <errno.h>
25 #include <fenv.h>
26 #include <ieee754.h>
27 #include <math_private.h>
29 /* Carry out a computation using round-to-odd. The computation is
30 EXPR; the union type in which to store the result is UNION and the
31 subfield of the "ieee" field of that union with the low part of the
32 mantissa is MANTISSA; SUFFIX is the suffix for the libc_fe* macros
33 to ensure that the correct rounding mode is used, for platforms
34 with multiple rounding modes where those macros set only the
35 relevant mode. This macro does not work correctly if the sign of
36 an exact zero result depends on the rounding mode, so that case
37 must be checked for separately. */
38 #define ROUND_TO_ODD(EXPR, UNION, SUFFIX, MANTISSA) \
39 ({ \
40 fenv_t env; \
41 UNION u; \
43 libc_feholdexcept_setround ## SUFFIX (&env, FE_TOWARDZERO); \
44 u.d = (EXPR); \
45 math_force_eval (u.d); \
46 u.ieee.MANTISSA \
47 |= libc_feupdateenv_test ## SUFFIX (&env, FE_INEXACT) != 0; \
49 u.d; \
52 /* Check for error conditions from a narrowing add function returning
53 RET with arguments X and Y and set errno as needed. Overflow and
54 underflow can occur for finite arguments and a domain error for
55 infinite ones. */
56 #define CHECK_NARROW_ADD(RET, X, Y) \
57 do \
58 { \
59 if (!isfinite (RET)) \
60 { \
61 if (isnan (RET)) \
62 { \
63 if (!isnan (X) && !isnan (Y)) \
64 __set_errno (EDOM); \
65 } \
66 else if (isfinite (X) && isfinite (Y)) \
67 __set_errno (ERANGE); \
68 } \
69 else if ((RET) == 0 && (X) != -(Y)) \
70 __set_errno (ERANGE); \
71 } \
72 while (0)
74 /* Implement narrowing add using round-to-odd. The arguments are X
75 and Y, the return type is TYPE and UNION, MANTISSA and SUFFIX are
76 as for ROUND_TO_ODD. */
77 #define NARROW_ADD_ROUND_TO_ODD(X, Y, TYPE, UNION, SUFFIX, MANTISSA) \
78 do \
79 { \
80 TYPE ret; \
82 /* Ensure a zero result is computed in the original rounding \
83 mode. */ \
84 if ((X) == -(Y)) \
85 ret = (TYPE) ((X) + (Y)); \
86 else \
87 ret = (TYPE) ROUND_TO_ODD (math_opt_barrier (X) + (Y), \
88 UNION, SUFFIX, MANTISSA); \
90 CHECK_NARROW_ADD (ret, (X), (Y)); \
91 return ret; \
92 } \
93 while (0)
95 /* Implement a narrowing add function that is not actually narrowing
96 or where no attempt is made to be correctly rounding (the latter
97 only applies to IBM long double). The arguments are X and Y and
98 the return type is TYPE. */
99 #define NARROW_ADD_TRIVIAL(X, Y, TYPE) \
100 do \
102 TYPE ret; \
104 ret = (TYPE) ((X) + (Y)); \
105 CHECK_NARROW_ADD (ret, (X), (Y)); \
106 return ret; \
108 while (0)
110 /* Check for error conditions from a narrowing subtract function
111 returning RET with arguments X and Y and set errno as needed.
112 Overflow and underflow can occur for finite arguments and a domain
113 error for infinite ones. */
114 #define CHECK_NARROW_SUB(RET, X, Y) \
115 do \
117 if (!isfinite (RET)) \
119 if (isnan (RET)) \
121 if (!isnan (X) && !isnan (Y)) \
122 __set_errno (EDOM); \
124 else if (isfinite (X) && isfinite (Y)) \
125 __set_errno (ERANGE); \
127 else if ((RET) == 0 && (X) != (Y)) \
128 __set_errno (ERANGE); \
130 while (0)
132 /* Implement narrowing subtract using round-to-odd. The arguments are
133 X and Y, the return type is TYPE and UNION, MANTISSA and SUFFIX are
134 as for ROUND_TO_ODD. */
135 #define NARROW_SUB_ROUND_TO_ODD(X, Y, TYPE, UNION, SUFFIX, MANTISSA) \
136 do \
138 TYPE ret; \
140 /* Ensure a zero result is computed in the original rounding \
141 mode. */ \
142 if ((X) == (Y)) \
143 ret = (TYPE) ((X) - (Y)); \
144 else \
145 ret = (TYPE) ROUND_TO_ODD (math_opt_barrier (X) - (Y), \
146 UNION, SUFFIX, MANTISSA); \
148 CHECK_NARROW_SUB (ret, (X), (Y)); \
149 return ret; \
151 while (0)
153 /* Implement a narrowing subtract function that is not actually
154 narrowing or where no attempt is made to be correctly rounding (the
155 latter only applies to IBM long double). The arguments are X and Y
156 and the return type is TYPE. */
157 #define NARROW_SUB_TRIVIAL(X, Y, TYPE) \
158 do \
160 TYPE ret; \
162 ret = (TYPE) ((X) - (Y)); \
163 CHECK_NARROW_SUB (ret, (X), (Y)); \
164 return ret; \
166 while (0)
168 /* The following macros declare aliases for a narrowing function. The
169 sole argument is the base name of a family of functions, such as
170 "add". If any platform changes long double format after the
171 introduction of narrowing functions, in a way requiring symbol
172 versioning compatibility, additional variants of these macros will
173 be needed. */
175 #define libm_alias_float_double_main(func) \
176 weak_alias (__f ## func, f ## func) \
177 weak_alias (__f ## func, f32 ## func ## f64) \
178 weak_alias (__f ## func, f32 ## func ## f32x)
180 #ifdef NO_LONG_DOUBLE
181 # define libm_alias_float_double(func) \
182 libm_alias_float_double_main (func) \
183 weak_alias (__f ## func, f ## func ## l)
184 #else
185 # define libm_alias_float_double(func) \
186 libm_alias_float_double_main (func)
187 #endif
189 #define libm_alias_float32x_float64_main(func) \
190 weak_alias (__f32x ## func ## f64, f32x ## func ## f64)
192 #ifdef NO_LONG_DOUBLE
193 # define libm_alias_float32x_float64(func) \
194 libm_alias_float32x_float64_main (func) \
195 weak_alias (__f32x ## func ## f64, d ## func ## l)
196 #elif defined __LONG_DOUBLE_MATH_OPTIONAL
197 # define libm_alias_float32x_float64(func) \
198 libm_alias_float32x_float64_main (func) \
199 weak_alias (__f32x ## func ## f64, __nldbl_d ## func ## l)
200 #else
201 # define libm_alias_float32x_float64(func) \
202 libm_alias_float32x_float64_main (func)
203 #endif
205 #if __HAVE_FLOAT128 && !__HAVE_DISTINCT_FLOAT128
206 # define libm_alias_float_ldouble_f128(func) \
207 weak_alias (__f ## func ## l, f32 ## func ## f128)
208 # define libm_alias_double_ldouble_f128(func) \
209 weak_alias (__d ## func ## l, f32x ## func ## f128) \
210 weak_alias (__d ## func ## l, f64 ## func ## f128)
211 #else
212 # define libm_alias_float_ldouble_f128(func)
213 # define libm_alias_double_ldouble_f128(func)
214 #endif
216 #if __HAVE_FLOAT64X_LONG_DOUBLE
217 # define libm_alias_float_ldouble_f64x(func) \
218 weak_alias (__f ## func ## l, f32 ## func ## f64x)
219 # define libm_alias_double_ldouble_f64x(func) \
220 weak_alias (__d ## func ## l, f32x ## func ## f64x) \
221 weak_alias (__d ## func ## l, f64 ## func ## f64x)
222 #else
223 # define libm_alias_float_ldouble_f64x(func)
224 # define libm_alias_double_ldouble_f64x(func)
225 #endif
227 #define libm_alias_float_ldouble(func) \
228 weak_alias (__f ## func ## l, f ## func ## l) \
229 libm_alias_float_ldouble_f128 (func) \
230 libm_alias_float_ldouble_f64x (func)
232 #define libm_alias_double_ldouble(func) \
233 weak_alias (__d ## func ## l, d ## func ## l) \
234 libm_alias_double_ldouble_f128 (func) \
235 libm_alias_double_ldouble_f64x (func)
237 #define libm_alias_float64x_float128(func) \
238 weak_alias (__f64x ## func ## f128, f64x ## func ## f128)
240 #define libm_alias_float32_float128_main(func) \
241 weak_alias (__f32 ## func ## f128, f32 ## func ## f128)
243 #define libm_alias_float64_float128_main(func) \
244 weak_alias (__f64 ## func ## f128, f64 ## func ## f128) \
245 weak_alias (__f64 ## func ## f128, f32x ## func ## f128)
247 #if __HAVE_FLOAT64X_LONG_DOUBLE
248 # define libm_alias_float32_float128(func) \
249 libm_alias_float32_float128_main (func)
250 # define libm_alias_float64_float128(func) \
251 libm_alias_float64_float128_main (func)
252 #else
253 # define libm_alias_float32_float128(func) \
254 libm_alias_float32_float128_main (func) \
255 weak_alias (__f32 ## func ## f128, f32 ## func ## f64x)
256 # define libm_alias_float64_float128(func) \
257 libm_alias_float64_float128_main (func) \
258 weak_alias (__f64 ## func ## f128, f64 ## func ## f64x) \
259 weak_alias (__f64 ## func ## f128, f32x ## func ## f64x)
260 #endif
262 #endif /* math-narrow.h. */