1 /* Inline math functions for i387 and SSE.
2 Copyright (C) 1995-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/>. */
20 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
23 #ifndef __extern_always_inline
24 # define __MATH_INLINE __inline
26 # define __MATH_INLINE __extern_always_inline
29 /* Disable x87 inlines when -fpmath=sse is passed and also when we're building
30 on x86_64. Older gcc (gcc-3.2 for example) does not define __SSE2_MATH__
32 #if !defined __SSE2_MATH__ && !defined __x86_64__
33 # if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
34 && defined __OPTIMIZE__)
36 /* The inline functions do not set errno or raise necessarily the
37 correct exceptions. */
38 # undef math_errhandling
40 /* A macro to define float, double, and long double versions of various
41 math functions for the ix87 FPU. FUNC is the function name (which will
42 be suffixed with f and l for the float and long double version,
43 respectively). OP is the name of the FPU operation.
44 We define two sets of macros. The set with the additional NP
45 doesn't add a prototype declaration. */
48 # define __inline_mathop(func, op) \
49 __inline_mathop_ (double, func, op) \
50 __inline_mathop_ (float, __CONCAT(func,f), op) \
51 __inline_mathop_ (long double, __CONCAT(func,l), op)
52 # define __inline_mathopNP(func, op) \
53 __inline_mathopNP_ (double, func, op) \
54 __inline_mathopNP_ (float, __CONCAT(func,f), op) \
55 __inline_mathopNP_ (long double, __CONCAT(func,l), op)
57 # define __inline_mathop(func, op) \
58 __inline_mathop_ (double, func, op)
59 # define __inline_mathopNP(func, op) \
60 __inline_mathopNP_ (double, func, op)
63 # define __inline_mathop_(float_type, func, op) \
64 __inline_mathop_decl_ (float_type, func, op, "0" (__x))
65 # define __inline_mathopNP_(float_type, func, op) \
66 __inline_mathop_declNP_ (float_type, func, op, "0" (__x))
70 # define __inline_mathop_decl(func, op, params...) \
71 __inline_mathop_decl_ (double, func, op, params) \
72 __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \
73 __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
74 # define __inline_mathop_declNP(func, op, params...) \
75 __inline_mathop_declNP_ (double, func, op, params) \
76 __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \
77 __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params)
79 # define __inline_mathop_decl(func, op, params...) \
80 __inline_mathop_decl_ (double, func, op, params)
81 # define __inline_mathop_declNP(func, op, params...) \
82 __inline_mathop_declNP_ (double, func, op, params)
85 # define __inline_mathop_decl_(float_type, func, op, params...) \
86 __MATH_INLINE float_type func (float_type) __THROW; \
87 __inline_mathop_declNP_ (float_type, func, op, params)
89 # define __inline_mathop_declNP_(float_type, func, op, params...) \
90 __MATH_INLINE float_type __NTH (func (float_type __x)) \
92 register float_type __result; \
93 __asm __volatile__ (op : "=t" (__result) : params); \
99 # define __inline_mathcode(func, arg, code) \
100 __inline_mathcode_ (double, func, arg, code) \
101 __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \
102 __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
103 # define __inline_mathcodeNP(func, arg, code) \
104 __inline_mathcodeNP_ (double, func, arg, code) \
105 __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \
106 __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code)
107 # define __inline_mathcode2(func, arg1, arg2, code) \
108 __inline_mathcode2_ (double, func, arg1, arg2, code) \
109 __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \
110 __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
111 # define __inline_mathcodeNP2(func, arg1, arg2, code) \
112 __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \
113 __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \
114 __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code)
115 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
116 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \
117 __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
118 __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
119 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
120 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \
121 __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
122 __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
124 # define __inline_mathcode(func, arg, code) \
125 __inline_mathcode_ (double, func, (arg), code)
126 # define __inline_mathcodeNP(func, arg, code) \
127 __inline_mathcodeNP_ (double, func, (arg), code)
128 # define __inline_mathcode2(func, arg1, arg2, code) \
129 __inline_mathcode2_ (double, func, arg1, arg2, code)
130 # define __inline_mathcodeNP2(func, arg1, arg2, code) \
131 __inline_mathcodeNP2_ (double, func, arg1, arg2, code)
132 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
133 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
134 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
135 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)
138 # define __inline_mathcode_(float_type, func, arg, code) \
139 __MATH_INLINE float_type func (float_type) __THROW; \
140 __inline_mathcodeNP_(float_type, func, arg, code)
142 # define __inline_mathcodeNP_(float_type, func, arg, code) \
143 __MATH_INLINE float_type __NTH (func (float_type arg)) \
149 # define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
150 __MATH_INLINE float_type func (float_type, float_type) __THROW; \
151 __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code)
153 # define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \
154 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2)) \
159 # define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
160 __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \
161 __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code)
163 # define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \
164 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2, \
172 # if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
173 /* Miscellaneous functions */
175 /* __FAST_MATH__ is defined by gcc -ffast-math. */
176 # ifdef __FAST_MATH__
177 /* Optimized inline implementation, sometimes with reduced precision
178 and/or argument range. */
180 # if __GNUC_PREREQ (3, 5)
181 # define __expm1_code \
182 register long double __temp; \
183 __temp = __builtin_expm1l (__x); \
184 return __temp ? __temp : __x
186 # define __expm1_code \
187 register long double __value; \
188 register long double __exponent; \
189 register long double __temp; \
191 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \
192 "fmul %%st(1) # x * log2(e)\n\t" \
194 "frndint # int(x * log2(e))\n\t" \
196 "fsub %%st(1) # fract(x * log2(e))\n\t" \
197 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
198 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
199 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
201 ("fscale # 2^int(x * log2(e))\n\t" \
202 : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \
205 return __temp ? __temp : __x
207 __inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
209 # if __GNUC_PREREQ (3, 4)
210 __inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x))
212 # define __exp_code \
213 register long double __value; \
214 register long double __exponent; \
216 ("fldl2e # e^x = 2^(x * log2(e))\n\t" \
217 "fmul %%st(1) # x * log2(e)\n\t" \
219 "frndint # int(x * log2(e))\n\t" \
221 "fsub %%st(1) # fract(x * log2(e))\n\t" \
222 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
223 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
227 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
229 __inline_mathcodeNP (exp, __x, __exp_code)
230 __inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
232 # endif /* __FAST_MATH__ */
235 # ifdef __FAST_MATH__
236 # if !__GNUC_PREREQ (3,3)
237 __inline_mathopNP (sqrt, "fsqrt")
238 __inline_mathopNP_ (long double, __sqrtl, "fsqrt")
239 # define __libc_sqrtl(n) __sqrtl (n)
241 # define __libc_sqrtl(n) __builtin_sqrtl (n)
245 # if __GNUC_PREREQ (2, 8)
246 __inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
248 __inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
249 __inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
251 __inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
253 __inline_mathop (fabs, "fabs")
254 __inline_mathop_ (long double, __fabsl, "fabs")
257 __inline_mathcode_ (long double, __sgn1l, __x, \
258 __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \
260 __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \
261 __n.__xi[1] = 0x80000000; \
266 # ifdef __FAST_MATH__
267 /* The argument range of the inline version of sinhl is slightly reduced. */
268 __inline_mathcodeNP (sinh, __x, \
269 register long double __exm1 = __expm1l (__fabsl (__x)); \
270 return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
272 __inline_mathcodeNP (cosh, __x, \
273 register long double __ex = __expl (__x); \
274 return 0.5 * (__ex + 1.0 / __ex))
276 __inline_mathcodeNP (tanh, __x, \
277 register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \
278 return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
282 /* Optimized versions for some non-standardized functions. */
285 # ifdef __FAST_MATH__
286 __inline_mathcodeNP (expm1, __x, __expm1_code)
288 /* The argument range of the inline version of asinhl is slightly reduced. */
289 __inline_mathcodeNP (asinh, __x, \
290 register long double __y = __fabsl (__x); \
291 return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \
294 __inline_mathcodeNP (acosh, __x, \
295 return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0)))
297 __inline_mathcodeNP (atanh, __x, \
298 register long double __y = __fabsl (__x); \
299 return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
301 /* The argument range of the inline version of hypotl is slightly reduced. */
302 __inline_mathcodeNP2 (hypot, __x, __y,
303 return __libc_sqrtl (__x * __x + __y * __y))
309 /* Undefine some of the large macros which are not used anymore. */
310 # ifdef __FAST_MATH__
313 # endif /* __FAST_MATH__ */
315 # endif /* __NO_MATH_INLINES */
318 /* This code is used internally in the GNU libc. */
319 # ifdef __LIBC_INTERNAL_MATH_INLINES
320 __inline_mathcode2_ (long double, __ieee754_atan2l, __y, __x,
321 register long double __value;
322 __asm __volatile__ ("fpatan\n\t"
324 : "0" (__x), "u" (__y) : "st(1)");
328 #endif /* !__SSE2_MATH__ && !__x86_64__ */