vfs: check userland buffers before reading them.
[haiku.git] / src / system / libroot / posix / glibc / include / arch / x86 / bits / mathinline.h
blob1288804503c38ec4a674f9448bc8e0539a9c1c3a
1 /* Inline math functions for i387.
2 Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by John C. Bowman <bowman@math.ualberta.ca>, 1995.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
21 #ifndef _MATH_H
22 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
23 #endif
25 #ifndef __extern_always_inline
26 # define __MATH_INLINE __inline
27 #else
28 # define __MATH_INLINE __extern_always_inline
29 #endif
32 #if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2
33 # if __GNUC_PREREQ (2,97)
34 /* GCC 2.97 and up have builtins that actually can be used. */
35 # define isgreater(x, y) __builtin_isgreater (x, y)
36 # define isgreaterequal(x, y) __builtin_isgreaterequal (x, y)
37 # define isless(x, y) __builtin_isless (x, y)
38 # define islessequal(x, y) __builtin_islessequal (x, y)
39 # define islessgreater(x, y) __builtin_islessgreater (x, y)
40 # define isunordered(x, y) __builtin_isunordered (x, y)
41 # else
42 /* ISO C99 defines some macros to perform unordered comparisons. The
43 ix87 FPU supports this with special opcodes and we should use them.
44 These must not be inline functions since we have to be able to handle
45 all floating-point types. */
46 # ifdef __i686__
47 /* For the PentiumPro and more recent processors we can provide
48 better code. */
49 # define isgreater(x, y) \
50 ({ register char __result; \
51 __asm__ ("fucomip %%st(1), %%st; seta %%al" \
52 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
53 __result; })
54 # define isgreaterequal(x, y) \
55 ({ register char __result; \
56 __asm__ ("fucomip %%st(1), %%st; setae %%al" \
57 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
58 __result; })
60 # define isless(x, y) \
61 ({ register char __result; \
62 __asm__ ("fucomip %%st(1), %%st; seta %%al" \
63 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \
64 __result; })
66 # define islessequal(x, y) \
67 ({ register char __result; \
68 __asm__ ("fucomip %%st(1), %%st; setae %%al" \
69 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \
70 __result; })
72 # define islessgreater(x, y) \
73 ({ register char __result; \
74 __asm__ ("fucomip %%st(1), %%st; setne %%al" \
75 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
76 __result; })
78 # define isunordered(x, y) \
79 ({ register char __result; \
80 __asm__ ("fucomip %%st(1), %%st; setp %%al" \
81 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
82 __result; })
83 # else
84 /* This is the dumb, portable code for i386 and above. */
85 # define isgreater(x, y) \
86 ({ register char __result; \
87 __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \
88 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
89 __result; })
91 # define isgreaterequal(x, y) \
92 ({ register char __result; \
93 __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \
94 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
95 __result; })
97 # define isless(x, y) \
98 ({ register char __result; \
99 __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \
100 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
101 __result; })
103 # define islessequal(x, y) \
104 ({ register char __result; \
105 __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \
106 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
107 __result; })
109 # define islessgreater(x, y) \
110 ({ register char __result; \
111 __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al" \
112 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
113 __result; })
115 # define isunordered(x, y) \
116 ({ register char __result; \
117 __asm__ ("fucompp; fnstsw; sahf; setp %%al" \
118 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
119 __result; })
120 # endif /* __i686__ */
121 # endif /* GCC 2.97 */
123 /* The gcc, version 2.7 or below, has problems with all this inlining
124 code. So disable it for this version of the compiler. */
125 # if __GNUC_PREREQ (2, 8)
126 /* Test for negative number. Used in the signbit() macro. */
127 __MATH_INLINE int
128 __signbitf (float __x) __THROW
130 __extension__ union { float __f; int __i; } __u = { __f: __x };
131 return __u.__i < 0;
133 __MATH_INLINE int
134 __signbit (double __x) __THROW
136 __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
137 return __u.__i[1] < 0;
139 __MATH_INLINE int
140 __signbitl (long double __x) __THROW
142 __extension__ union { long double __l; int __i[3]; } __u = { __l: __x };
143 return (__u.__i[2] & 0x8000) != 0;
145 # endif
146 #endif
149 /* The gcc, version 2.7 or below, has problems with all this inlining
150 code. So disable it for this version of the compiler. */
151 #if __GNUC_PREREQ (2, 8)
153 #if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
154 && defined __OPTIMIZE__)
156 /* A macro to define float, double, and long double versions of various
157 math functions for the ix87 FPU. FUNC is the function name (which will
158 be suffixed with f and l for the float and long double version,
159 respectively). OP is the name of the FPU operation.
160 We define two sets of macros. The set with the additional NP
161 doesn't add a prototype declaration. */
163 #if defined __USE_MISC || defined __USE_ISOC99
164 # define __inline_mathop(func, op) \
165 __inline_mathop_ (double, func, op) \
166 __inline_mathop_ (float, __CONCAT(func,f), op) \
167 __inline_mathop_ (long double, __CONCAT(func,l), op)
168 # define __inline_mathopNP(func, op) \
169 __inline_mathopNP_ (double, func, op) \
170 __inline_mathopNP_ (float, __CONCAT(func,f), op) \
171 __inline_mathopNP_ (long double, __CONCAT(func,l), op)
172 #else
173 # define __inline_mathop(func, op) \
174 __inline_mathop_ (double, func, op)
175 # define __inline_mathopNP(func, op) \
176 __inline_mathopNP_ (double, func, op)
177 #endif
179 #define __inline_mathop_(float_type, func, op) \
180 __inline_mathop_decl_ (float_type, func, op, "0" (__x))
181 #define __inline_mathopNP_(float_type, func, op) \
182 __inline_mathop_declNP_ (float_type, func, op, "0" (__x))
185 #if defined __USE_MISC || defined __USE_ISOC99
186 # define __inline_mathop_decl(func, op, params...) \
187 __inline_mathop_decl_ (double, func, op, params) \
188 __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \
189 __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
190 # define __inline_mathop_declNP(func, op, params...) \
191 __inline_mathop_declNP_ (double, func, op, params) \
192 __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \
193 __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params)
194 #else
195 # define __inline_mathop_decl(func, op, params...) \
196 __inline_mathop_decl_ (double, func, op, params)
197 # define __inline_mathop_declNP(func, op, params...) \
198 __inline_mathop_declNP_ (double, func, op, params)
199 #endif
201 #define __inline_mathop_decl_(float_type, func, op, params...) \
202 __MATH_INLINE float_type func (float_type) __THROW; \
203 __inline_mathop_declNP_ (float_type, func, op, params)
205 #define __inline_mathop_declNP_(float_type, func, op, params...) \
206 __MATH_INLINE float_type func (float_type __x) __THROW \
208 register float_type __result; \
209 __asm __volatile__ (op : "=t" (__result) : params); \
210 return __result; \
214 #if defined __USE_MISC || defined __USE_ISOC99
215 # define __inline_mathcode(func, arg, code) \
216 __inline_mathcode_ (double, func, arg, code) \
217 __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \
218 __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
219 # define __inline_mathcodeNP(func, arg, code) \
220 __inline_mathcodeNP_ (double, func, arg, code) \
221 __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \
222 __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code)
223 # define __inline_mathcode2(func, arg1, arg2, code) \
224 __inline_mathcode2_ (double, func, arg1, arg2, code) \
225 __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \
226 __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
227 # define __inline_mathcodeNP2(func, arg1, arg2, code) \
228 __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \
229 __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \
230 __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code)
231 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
232 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \
233 __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
234 __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
235 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
236 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \
237 __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
238 __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
239 #else
240 # define __inline_mathcode(func, arg, code) \
241 __inline_mathcode_ (double, func, (arg), code)
242 # define __inline_mathcodeNP(func, arg, code) \
243 __inline_mathcodeNP_ (double, func, (arg), code)
244 # define __inline_mathcode2(func, arg1, arg2, code) \
245 __inline_mathcode2_ (double, func, arg1, arg2, code)
246 # define __inline_mathcodeNP2(func, arg1, arg2, code) \
247 __inline_mathcodeNP2_ (double, func, arg1, arg2, code)
248 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
249 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
250 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
251 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)
252 #endif
254 #define __inline_mathcode_(float_type, func, arg, code) \
255 __MATH_INLINE float_type func (float_type) __THROW; \
256 __inline_mathcodeNP_(float_type, func, arg, code)
258 #define __inline_mathcodeNP_(float_type, func, arg, code) \
259 __MATH_INLINE float_type func (float_type arg) __THROW \
261 code; \
265 #define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
266 __MATH_INLINE float_type func (float_type, float_type) __THROW; \
267 __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code)
269 #define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \
270 __MATH_INLINE float_type func (float_type arg1, float_type arg2) __THROW \
272 code; \
275 #define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
276 __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \
277 __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code)
279 #define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \
280 __MATH_INLINE float_type func (float_type arg1, float_type arg2, \
281 float_type arg3) __THROW \
283 code; \
285 #endif
288 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
289 /* Miscellaneous functions */
291 __inline_mathcode (__sgn, __x, \
292 return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0))
294 /* __FAST_MATH__ is defined by gcc -ffast-math. */
295 #ifdef __FAST_MATH__
296 __inline_mathcode (__pow2, __x, \
297 register long double __value; \
298 register long double __exponent; \
299 __extension__ long long int __p = (long long int) __x; \
300 if (__x == (long double) __p) \
302 __asm __volatile__ \
303 ("fscale" \
304 : "=t" (__value) : "0" (1.0), "u" (__x)); \
305 return __value; \
307 __asm __volatile__ \
308 ("fld %%st(0)\n\t" \
309 "frndint # int(x)\n\t" \
310 "fxch\n\t" \
311 "fsub %%st(1) # fract(x)\n\t" \
312 "f2xm1 # 2^(fract(x)) - 1\n\t" \
313 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
314 __value += 1.0; \
315 __asm __volatile__ \
316 ("fscale" \
317 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
318 return __value)
320 # ifdef __USE_GNU
321 # define __sincos_code \
322 register long double __cosr; \
323 register long double __sinr; \
324 __asm __volatile__ \
325 ("fsincos\n\t" \
326 "fnstsw %%ax\n\t" \
327 "testl $0x400, %%eax\n\t" \
328 "jz 1f\n\t" \
329 "fldpi\n\t" \
330 "fadd %%st(0)\n\t" \
331 "fxch %%st(1)\n\t" \
332 "2: fprem1\n\t" \
333 "fnstsw %%ax\n\t" \
334 "testl $0x400, %%eax\n\t" \
335 "jnz 2b\n\t" \
336 "fstp %%st(1)\n\t" \
337 "fsincos\n\t" \
338 "1:" \
339 : "=t" (__cosr), "=u" (__sinr) : "0" (__x)); \
340 *__sinx = __sinr; \
341 *__cosx = __cosr
343 __MATH_INLINE void
344 __sincos (double __x, double *__sinx, double *__cosx) __THROW
346 __sincos_code;
349 __MATH_INLINE void
350 __sincosf (float __x, float *__sinx, float *__cosx) __THROW
352 __sincos_code;
355 __MATH_INLINE void
356 __sincosl (long double __x, long double *__sinx, long double *__cosx) __THROW
358 __sincos_code;
360 # endif
363 /* Optimized inline implementation, sometimes with reduced precision
364 and/or argument range. */
366 # define __expm1_code \
367 register long double __value; \
368 register long double __exponent; \
369 register long double __temp; \
370 __asm __volatile__ \
371 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \
372 "fmul %%st(1) # x * log2(e)\n\t" \
373 "fst %%st(1)\n\t" \
374 "frndint # int(x * log2(e))\n\t" \
375 "fxch\n\t" \
376 "fsub %%st(1) # fract(x * log2(e))\n\t" \
377 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
378 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
379 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
380 __asm __volatile__ \
381 ("fscale # 2^int(x * log2(e))\n\t" \
382 : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \
383 __temp -= 1.0; \
384 return __temp + __value ?: __x
385 __inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
388 # define __exp_code \
389 register long double __value; \
390 register long double __exponent; \
391 __asm __volatile__ \
392 ("fldl2e # e^x = 2^(x * log2(e))\n\t" \
393 "fmul %%st(1) # x * log2(e)\n\t" \
394 "fst %%st(1)\n\t" \
395 "frndint # int(x * log2(e))\n\t" \
396 "fxch\n\t" \
397 "fsub %%st(1) # fract(x * log2(e))\n\t" \
398 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
399 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
400 __value += 1.0; \
401 __asm __volatile__ \
402 ("fscale" \
403 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
404 return __value
405 __inline_mathcodeNP (exp, __x, __exp_code)
406 __inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
409 __inline_mathcodeNP (tan, __x, \
410 register long double __value; \
411 register long double __value2 __attribute__ ((__unused__)); \
412 __asm __volatile__ \
413 ("fptan" \
414 : "=t" (__value2), "=u" (__value) : "0" (__x)); \
415 return __value)
416 #endif /* __FAST_MATH__ */
419 # if __GNUC_PREREQ (3, 4)
420 __inline_mathcodeNP2_ (long double, __atan2l, __y, __x,
421 return __builtin_atan2l (__y, __x))
422 # else
423 #define __atan2_code \
424 register long double __value; \
425 __asm __volatile__ \
426 ("fpatan" \
427 : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \
428 return __value
429 # ifdef __FAST_MATH__
430 __inline_mathcodeNP2 (atan2, __y, __x, __atan2_code)
431 # endif
432 __inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code)
433 # endif
436 __inline_mathcodeNP2 (fmod, __x, __y, \
437 register long double __value; \
438 __asm __volatile__ \
439 ("1: fprem\n\t" \
440 "fnstsw %%ax\n\t" \
441 "sahf\n\t" \
442 "jp 1b" \
443 : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
444 return __value)
447 __inline_mathopNP (sqrt, "fsqrt")
448 __inline_mathopNP_ (long double, __sqrtl, "fsqrt")
450 #if __GNUC_PREREQ (2, 8)
451 __inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
452 __inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
453 __inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
454 __inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
455 #else
456 __inline_mathop (fabs, "fabs")
457 __inline_mathop_ (long double, __fabsl, "fabs")
458 #endif
460 #ifdef __FAST_MATH__
461 /* The argument range of this inline version is reduced. */
462 __inline_mathopNP (sin, "fsin")
463 /* The argument range of this inline version is reduced. */
464 __inline_mathopNP (cos, "fcos")
466 __inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)")
467 __inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)")
469 __inline_mathcodeNP (asin, __x, return __atan2l (__x, __sqrtl (1.0 - __x * __x)))
470 __inline_mathcodeNP (acos, __x, return __atan2l (__sqrtl (1.0 - __x * __x), __x))
471 #endif /* __FAST_MATH__ */
473 __inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)")
475 __inline_mathcode_ (long double, __sgn1l, __x, \
476 __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \
477 { __xld: __x }; \
478 __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \
479 __n.__xi[1] = 0x80000000; \
480 __n.__xi[0] = 0; \
481 return __n.__xld)
484 #ifdef __FAST_MATH__
485 /* The argument range of the inline version of sinhl is slightly reduced. */
486 __inline_mathcodeNP (sinh, __x, \
487 register long double __exm1 = __expm1l (__fabsl (__x)); \
488 return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
490 __inline_mathcodeNP (cosh, __x, \
491 register long double __ex = __expl (__x); \
492 return 0.5 * (__ex + 1.0 / __ex))
494 __inline_mathcodeNP (tanh, __x, \
495 register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \
496 return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
497 #endif
499 __inline_mathcodeNP (floor, __x, \
500 register long double __value; \
501 __volatile unsigned short int __cw; \
502 __volatile unsigned short int __cwtmp; \
503 __asm __volatile ("fnstcw %0" : "=m" (__cw)); \
504 __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ \
505 __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
506 __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
507 __asm __volatile ("fldcw %0" : : "m" (__cw)); \
508 return __value)
510 __inline_mathcodeNP (ceil, __x, \
511 register long double __value; \
512 __volatile unsigned short int __cw; \
513 __volatile unsigned short int __cwtmp; \
514 __asm __volatile ("fnstcw %0" : "=m" (__cw)); \
515 __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ \
516 __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
517 __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
518 __asm __volatile ("fldcw %0" : : "m" (__cw)); \
519 return __value)
521 #ifdef __FAST_MATH__
522 #define __ldexp_code \
523 register long double __value; \
524 __asm __volatile__ \
525 ("fscale" \
526 : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \
527 return __value
529 __MATH_INLINE double
530 ldexp (double __x, int __y) __THROW
532 __ldexp_code;
534 #endif
537 /* Optimized versions for some non-standardized functions. */
538 #if defined __USE_ISOC99 || defined __USE_MISC
540 # ifdef __FAST_MATH__
541 __inline_mathcodeNP (expm1, __x, __expm1_code)
543 /* We cannot rely on M_SQRT being defined. So we do it for ourself
544 here. */
545 # define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */
547 __inline_mathcodeNP (log1p, __x, \
548 register long double __value; \
549 if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \
550 __value = logl (1.0 + __x); \
551 else \
552 __asm __volatile__ \
553 ("fldln2\n\t" \
554 "fxch\n\t" \
555 "fyl2xp1" \
556 : "=t" (__value) : "0" (__x) : "st(1)"); \
557 return __value)
560 /* The argument range of the inline version of asinhl is slightly reduced. */
561 __inline_mathcodeNP (asinh, __x, \
562 register long double __y = __fabsl (__x); \
563 return (log1pl (__y * __y / (__sqrtl (__y * __y + 1.0) + 1.0) + __y) \
564 * __sgn1l (__x)))
566 __inline_mathcodeNP (acosh, __x, \
567 return logl (__x + __sqrtl (__x - 1.0) * __sqrtl (__x + 1.0)))
569 __inline_mathcodeNP (atanh, __x, \
570 register long double __y = __fabsl (__x); \
571 return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
573 /* The argument range of the inline version of hypotl is slightly reduced. */
574 __inline_mathcodeNP2 (hypot, __x, __y, return __sqrtl (__x * __x + __y * __y))
576 __inline_mathcodeNP(logb, __x, \
577 register long double __value; \
578 register long double __junk; \
579 __asm __volatile__ \
580 ("fxtract\n\t" \
581 : "=t" (__junk), "=u" (__value) : "0" (__x)); \
582 return __value)
584 # endif
585 #endif
587 #ifdef __USE_ISOC99
588 #ifdef __FAST_MATH__
589 __inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)")
591 __MATH_INLINE float
592 ldexpf (float __x, int __y) __THROW
594 __ldexp_code;
597 __MATH_INLINE long double
598 ldexpl (long double __x, int __y) __THROW
600 __ldexp_code;
603 __inline_mathcodeNP3 (fma, __x, __y, __z, return (__x * __y) + __z)
605 __inline_mathopNP (rint, "frndint")
606 #endif /* __FAST_MATH__ */
608 #define __lrint_code \
609 long int __lrintres; \
610 __asm__ __volatile__ \
611 ("fistpl %0" \
612 : "=m" (__lrintres) : "t" (__x) : "st"); \
613 return __lrintres
614 __MATH_INLINE long int
615 lrintf (float __x) __THROW
617 __lrint_code;
619 __MATH_INLINE long int
620 lrint (double __x) __THROW
622 __lrint_code;
624 __MATH_INLINE long int
625 lrintl (long double __x) __THROW
627 __lrint_code;
629 #undef __lrint_code
631 #define __llrint_code \
632 long long int __llrintres; \
633 __asm__ __volatile__ \
634 ("fistpll %0" \
635 : "=m" (__llrintres) : "t" (__x) : "st"); \
636 return __llrintres
637 __MATH_INLINE long long int
638 llrintf (float __x) __THROW
640 __llrint_code;
642 __MATH_INLINE long long int
643 llrint (double __x) __THROW
645 __llrint_code;
647 __MATH_INLINE long long int
648 llrintl (long double __x) __THROW
650 __llrint_code;
652 #undef __llrint_code
654 #endif
657 #ifdef __USE_MISC
659 __inline_mathcodeNP2 (drem, __x, __y, \
660 register double __value; \
661 register int __clobbered; \
662 __asm __volatile__ \
663 ("1: fprem1\n\t" \
664 "fstsw %%ax\n\t" \
665 "sahf\n\t" \
666 "jp 1b" \
667 : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \
668 return __value)
671 /* This function is used in the `isfinite' macro. */
672 __MATH_INLINE int
673 __finite (double __x) __THROW
675 return (__extension__
676 (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
677 | 0x800fffffu) + 1) >> 31));
680 /* Miscellaneous functions */
681 #ifdef __FAST_MATH__
682 __inline_mathcode (__coshm1, __x, \
683 register long double __exm1 = __expm1l (__fabsl (__x)); \
684 return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
686 __inline_mathcode (__acosh1p, __x, \
687 return log1pl (__x + __sqrtl (__x) * __sqrtl (__x + 2.0)))
689 #endif /* __FAST_MATH__ */
690 #endif /* __USE_MISC */
692 /* Undefine some of the large macros which are not used anymore. */
693 #undef __atan2_code
694 #ifdef __FAST_MATH__
695 # undef __expm1_code
696 # undef __exp_code
697 # undef __sincos_code
698 #endif /* __FAST_MATH__ */
700 #endif /* __NO_MATH_INLINES */
703 /* This code is used internally in the GNU libc. */
704 #ifdef __LIBC_INTERNAL_MATH_INLINES
705 __inline_mathop (__ieee754_sqrt, "fsqrt")
706 __inline_mathcode2 (__ieee754_atan2, __y, __x,
707 register long double __value;
708 __asm __volatile__ ("fpatan\n\t"
709 : "=t" (__value)
710 : "0" (__x), "u" (__y) : "st(1)");
711 return __value;)
712 #endif
714 #endif /* __GNUC__ */