cpp-d1064d
[cross.git] / i686-linux-gnu-4.7 / usr / include / x86_64-linux-gnu / bits / mathinline.h
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.
4
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.
9
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.
14
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/>.  */
18
19 #ifndef _MATH_H
20 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
21 #endif
22
23 #ifndef __extern_always_inline
24 # define __MATH_INLINE __inline
25 #else
26 # define __MATH_INLINE __extern_always_inline
27 #endif
28
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__
31    for x86_64.  */
32 #if !defined __SSE2_MATH__ && !defined __x86_64__
33 # if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
34      && defined __OPTIMIZE__)
35
36 /* The inline functions do not set errno or raise necessarily the
37    correct exceptions.  */
38 #  undef math_errhandling
39
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.  */
46
47 #  ifdef __USE_ISOC99
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)
56 #  else
57 #   define __inline_mathop(func, op) \
58   __inline_mathop_ (double, func, op)
59 #   define __inline_mathopNP(func, op) \
60   __inline_mathopNP_ (double, func, op)
61 #  endif
62
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))
67
68
69 #  ifdef __USE_ISOC99
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)
78 #  else
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)
83 #  endif
84
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)
88
89 #  define __inline_mathop_declNP_(float_type, func, op, params...) \
90   __MATH_INLINE float_type __NTH (func (float_type __x))                      \
91   {                                                                           \
92     register float_type __result;                                             \
93     __asm __volatile__ (op : "=t" (__result) : params);                       \
94     return __result;                                                          \
95   }
96
97
98 #  ifdef __USE_ISOC99
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)
123 #  else
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)
136 #  endif
137
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)
141
142 #  define __inline_mathcodeNP_(float_type, func, arg, code) \
143   __MATH_INLINE float_type __NTH (func (float_type arg))                      \
144   {                                                                           \
145     code;                                                                     \
146   }
147
148
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)
152
153 #  define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \
154   __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2))    \
155   {                                                                           \
156     code;                                                                     \
157   }
158
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)
162
163 #  define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \
164   __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2,     \
165                                         float_type arg3))                     \
166   {                                                                           \
167     code;                                                                     \
168   }
169 # endif
170
171
172 # if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
173 /* Miscellaneous functions  */
174
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.  */
179
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
185 #   else
186 #    define __expm1_code \
187   register long double __value;                                               \
188   register long double __exponent;                                            \
189   register long double __temp;                                                \
190   __asm __volatile__                                                          \
191     ("fldl2e                    # e^x - 1 = 2^(x * log2(e)) - 1\n\t"          \
192      "fmul      %%st(1)         # x * log2(e)\n\t"                            \
193      "fst       %%st(1)\n\t"                                                  \
194      "frndint                   # int(x * log2(e))\n\t"                       \
195      "fxch\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));                        \
200   __asm __volatile__                                                          \
201     ("fscale                    # 2^int(x * log2(e))\n\t"                     \
202      : "=t" (__temp) : "0" (1.0), "u" (__exponent));                          \
203   __temp -= 1.0;                                                              \
204   __temp += __value;                                                          \
205   return __temp ? __temp : __x
206 #   endif
207 __inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
208
209 #   if __GNUC_PREREQ (3, 4)
210 __inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x))
211 #   else
212 #    define __exp_code \
213   register long double __value;                                               \
214   register long double __exponent;                                            \
215   __asm __volatile__                                                          \
216     ("fldl2e                    # e^x = 2^(x * log2(e))\n\t"                  \
217      "fmul      %%st(1)         # x * log2(e)\n\t"                            \
218      "fst       %%st(1)\n\t"                                                  \
219      "frndint                   # int(x * log2(e))\n\t"                       \
220      "fxch\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));                        \
224   __value += 1.0;                                                             \
225   __asm __volatile__                                                          \
226     ("fscale"                                                                 \
227      : "=t" (__value) : "0" (__value), "u" (__exponent));                     \
228   return __value
229 __inline_mathcodeNP (exp, __x, __exp_code)
230 __inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
231 #   endif
232 #  endif /* __FAST_MATH__ */
233
234
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)
240 #   else
241 #    define __libc_sqrtl(n) __builtin_sqrtl (n)
242 #   endif
243 #  endif
244
245 #  if __GNUC_PREREQ (2, 8)
246 __inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
247 #   ifdef __USE_ISOC99
248 __inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
249 __inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
250 #   endif
251 __inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
252 #  else
253 __inline_mathop (fabs, "fabs")
254 __inline_mathop_ (long double, __fabsl, "fabs")
255 # endif
256
257 __inline_mathcode_ (long double, __sgn1l, __x, \
258   __extension__ union { long double __xld; unsigned int __xi[3]; } __n =      \
259     { __xld: __x };                                                           \
260   __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff;                              \
261   __n.__xi[1] = 0x80000000;                                                   \
262   __n.__xi[0] = 0;                                                            \
263   return __n.__xld)
264
265
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))
271
272 __inline_mathcodeNP (cosh, __x, \
273   register long double __ex = __expl (__x);                                   \
274   return 0.5 * (__ex + 1.0 / __ex))
275
276 __inline_mathcodeNP (tanh, __x, \
277   register long double __exm1 = __expm1l (-__fabsl (__x + __x));              \
278   return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
279 #  endif
280
281
282 /* Optimized versions for some non-standardized functions.  */
283 #  ifdef __USE_ISOC99
284
285 #   ifdef __FAST_MATH__
286 __inline_mathcodeNP (expm1, __x, __expm1_code)
287
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)   \
292           * __sgn1l (__x)))
293
294 __inline_mathcodeNP (acosh, __x, \
295   return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0)))
296
297 __inline_mathcodeNP (atanh, __x, \
298   register long double __y = __fabsl (__x);                                   \
299   return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
300
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))
304
305 #   endif
306 #  endif
307
308
309 /* Undefine some of the large macros which are not used anymore.  */
310 #  ifdef __FAST_MATH__
311 #   undef __expm1_code
312 #   undef __exp_code
313 #  endif /* __FAST_MATH__ */
314
315 # endif /* __NO_MATH_INLINES  */
316
317
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"
323                                          : "=t" (__value)
324                                          : "0" (__x), "u" (__y) : "st(1)");
325                      return __value;)
326 # endif
327
328 #endif /* !__SSE2_MATH__ && !__x86_64__ */