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/* The gcc, version 2.7 or below, has problems with all this inlining
30 code. So disable it for this version of the compiler. */
31#if __GNUC_PREREQ (2, 8)
32# if !__GNUC_PREREQ (3, 4) && !defined __NO_MATH_INLINES \
33 && defined __OPTIMIZE__
34/* GCC 3.4 introduced builtins for all functions below, so
35 there's no need to define any of these inline functions. */
36
37# ifdef __USE_ISOC99
38
39/* Round to nearest integer. */
40# ifdef __SSE_MATH__
41__MATH_INLINE long int
42__NTH (lrintf (float __x))
43{
44 long int __res;
45 /* Mark as volatile since the result is dependent on the state of
46 the SSE control register (the rounding mode). Otherwise GCC might
47 remove these assembler instructions since it does not know about
48 the rounding mode change and cannot currently be told. */
49 __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
50 return __res;
51}
52# endif
53# ifdef __SSE2_MATH__
54__MATH_INLINE long int
55__NTH (lrint (double __x))
56{
57 long int __res;
58 /* Mark as volatile since the result is dependent on the state of
59 the SSE control register (the rounding mode). Otherwise GCC might
60 remove these assembler instructions since it does not know about
61 the rounding mode change and cannot currently be told. */
62 __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
63 return __res;
64}
65# endif
66# ifdef __x86_64__
67__extension__
68__MATH_INLINE long long int
69__NTH (llrintf (float __x))
70{
71 long long int __res;
72 /* Mark as volatile since the result is dependent on the state of
73 the SSE control register (the rounding mode). Otherwise GCC might
74 remove these assembler instructions since it does not know about
75 the rounding mode change and cannot currently be told. */
76 __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x));
77 return __res;
78}
79__extension__
80__MATH_INLINE long long int
81__NTH (llrint (double __x))
82{
83 long long int __res;
84 /* Mark as volatile since the result is dependent on the state of
85 the SSE control register (the rounding mode). Otherwise GCC might
86 remove these assembler instructions since it does not know about
87 the rounding mode change and cannot currently be told. */
88 __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x));
89 return __res;
90}
91# endif
92
93# if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0 \
94 && defined __SSE2_MATH__
95/* Determine maximum of two values. */
96__MATH_INLINE float
97__NTH (fmaxf (float __x, float __y))
98{
99# ifdef __AVX__
100 float __res;
101 __asm ("vmaxss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
102 return __res;
103# else
104 __asm ("maxss %1, %0" : "+x" (__x) : "xm" (__y));
105 return __x;
106# endif
107}
108__MATH_INLINE double
109__NTH (fmax (double __x, double __y))
110{
111# ifdef __AVX__
112 float __res;
113 __asm ("vmaxsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
114 return __res;
115# else
116 __asm ("maxsd %1, %0" : "+x" (__x) : "xm" (__y));
117 return __x;
118# endif
119}
120
121/* Determine minimum of two values. */
122__MATH_INLINE float
123__NTH (fminf (float __x, float __y))
124{
125# ifdef __AVX__
126 float __res;
127 __asm ("vminss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
128 return __res;
129# else
130 __asm ("minss %1, %0" : "+x" (__x) : "xm" (__y));
131 return __x;
132# endif
133}
134__MATH_INLINE double
135__NTH (fmin (double __x, double __y))
136{
137# ifdef __AVX__
138 float __res;
139 __asm ("vminsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y));
140 return __res;
141# else
142 __asm ("minsd %1, %0" : "+x" (__x) : "xm" (__y));
143 return __x;
144# endif
145}
146# endif
147
148# endif
149
150# if defined __SSE4_1__ && defined __SSE2_MATH__
151# if defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
152
153/* Round to nearest integer. */
154__MATH_INLINE double
155__NTH (rint (double __x))
156{
157 double __res;
158 /* Mark as volatile since the result is dependent on the state of
159 the SSE control register (the rounding mode). Otherwise GCC might
160 remove these assembler instructions since it does not know about
161 the rounding mode change and cannot currently be told. */
162 __asm __volatile__ ("roundsd $4, %1, %0" : "=x" (__res) : "xm" (__x));
163 return __res;
164}
165__MATH_INLINE float
166__NTH (rintf (float __x))
167{
168 float __res;
169 /* Mark as volatile since the result is dependent on the state of
170 the SSE control register (the rounding mode). Otherwise GCC might
171 remove these assembler instructions since it does not know about
172 the rounding mode change and cannot currently be told. */
173 __asm __volatile__ ("roundss $4, %1, %0" : "=x" (__res) : "xm" (__x));
174 return __res;
175}
176
177# ifdef __USE_ISOC99
178/* Round to nearest integer without raising inexact exception. */
179__MATH_INLINE double
180__NTH (nearbyint (double __x))
181{
182 double __res;
183 /* Mark as volatile since the result is dependent on the state of
184 the SSE control register (the rounding mode). Otherwise GCC might
185 remove these assembler instructions since it does not know about
186 the rounding mode change and cannot currently be told. */
187 __asm __volatile__ ("roundsd $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
188 return __res;
189}
190__MATH_INLINE float
191__NTH (nearbyintf (float __x))
192{
193 float __res;
194 /* Mark as volatile since the result is dependent on the state of
195 the SSE control register (the rounding mode). Otherwise GCC might
196 remove these assembler instructions since it does not know about
197 the rounding mode change and cannot currently be told. */
198 __asm __volatile__ ("roundss $0xc, %1, %0" : "=x" (__res) : "xm" (__x));
199 return __res;
200}
201# endif
202
203# endif
204
205/* Smallest integral value not less than X. */
206__MATH_INLINE double
207__NTH (ceil (double __x))
208{
209 double __res;
210 __asm ("roundsd $2, %1, %0" : "=x" (__res) : "xm" (__x));
211 return __res;
212}
213
214__MATH_INLINE float
215__NTH (ceilf (float __x))
216{
217 float __res;
218 __asm ("roundss $2, %1, %0" : "=x" (__res) : "xm" (__x));
219 return __res;
220}
221
222/* Largest integer not greater than X. */
223__MATH_INLINE double
224__NTH (floor (double __x))
225{
226 double __res;
227 __asm ("roundsd $1, %1, %0" : "=x" (__res) : "xm" (__x));
228 return __res;
229}
230
231__MATH_INLINE float
232__NTH (floorf (float __x))
233{
234 float __res;
235 __asm ("roundss $1, %1, %0" : "=x" (__res) : "xm" (__x));
236 return __res;
237}
238# endif
239# endif
240#endif
241
242/* Disable x87 inlines when -fpmath=sse is passed and also when we're building
243 on x86_64. Older gcc (gcc-3.2 for example) does not define __SSE2_MATH__
244 for x86_64. */
245#if !defined __SSE2_MATH__ && !defined __x86_64__
246# if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
247 && defined __OPTIMIZE__)
248
249/* The inline functions do not set errno or raise necessarily the
250 correct exceptions. */
251# undef math_errhandling
252
253/* A macro to define float, double, and long double versions of various
254 math functions for the ix87 FPU. FUNC is the function name (which will
255 be suffixed with f and l for the float and long double version,
256 respectively). OP is the name of the FPU operation.
257 We define two sets of macros. The set with the additional NP
258 doesn't add a prototype declaration. */
259
260# ifdef __USE_ISOC99
261# define __inline_mathop(func, op) \
262 __inline_mathop_ (double, func, op) \
263 __inline_mathop_ (float, __CONCAT(func,f), op) \
264 __inline_mathop_ (long double, __CONCAT(func,l), op)
265# define __inline_mathopNP(func, op) \
266 __inline_mathopNP_ (double, func, op) \
267 __inline_mathopNP_ (float, __CONCAT(func,f), op) \
268 __inline_mathopNP_ (long double, __CONCAT(func,l), op)
269# else
270# define __inline_mathop(func, op) \
271 __inline_mathop_ (double, func, op)
272# define __inline_mathopNP(func, op) \
273 __inline_mathopNP_ (double, func, op)
274# endif
275
276# define __inline_mathop_(float_type, func, op) \
277 __inline_mathop_decl_ (float_type, func, op, "0" (__x))
278# define __inline_mathopNP_(float_type, func, op) \
279 __inline_mathop_declNP_ (float_type, func, op, "0" (__x))
280
281
282# ifdef __USE_ISOC99
283# define __inline_mathop_decl(func, op, params...) \
284 __inline_mathop_decl_ (double, func, op, params) \
285 __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \
286 __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
287# define __inline_mathop_declNP(func, op, params...) \
288 __inline_mathop_declNP_ (double, func, op, params) \
289 __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \
290 __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params)
291# else
292# define __inline_mathop_decl(func, op, params...) \
293 __inline_mathop_decl_ (double, func, op, params)
294# define __inline_mathop_declNP(func, op, params...) \
295 __inline_mathop_declNP_ (double, func, op, params)
296# endif
297
298# define __inline_mathop_decl_(float_type, func, op, params...) \
299 __MATH_INLINE float_type func (float_type) __THROW; \
300 __inline_mathop_declNP_ (float_type, func, op, params)
301
302# define __inline_mathop_declNP_(float_type, func, op, params...) \
303 __MATH_INLINE float_type __NTH (func (float_type __x)) \
304 { \
305 register float_type __result; \
306 __asm __volatile__ (op : "=t" (__result) : params); \
307 return __result; \
308 }
309
310
311# ifdef __USE_ISOC99
312# define __inline_mathcode(func, arg, code) \
313 __inline_mathcode_ (double, func, arg, code) \
314 __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \
315 __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
316# define __inline_mathcodeNP(func, arg, code) \
317 __inline_mathcodeNP_ (double, func, arg, code) \
318 __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \
319 __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code)
320# define __inline_mathcode2(func, arg1, arg2, code) \
321 __inline_mathcode2_ (double, func, arg1, arg2, code) \
322 __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \
323 __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
324# define __inline_mathcodeNP2(func, arg1, arg2, code) \
325 __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \
326 __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \
327 __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code)
328# define __inline_mathcode3(func, arg1, arg2, arg3, code) \
329 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \
330 __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
331 __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
332# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
333 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \
334 __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
335 __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
336# else
337# define __inline_mathcode(func, arg, code) \
338 __inline_mathcode_ (double, func, (arg), code)
339# define __inline_mathcodeNP(func, arg, code) \
340 __inline_mathcodeNP_ (double, func, (arg), code)
341# define __inline_mathcode2(func, arg1, arg2, code) \
342 __inline_mathcode2_ (double, func, arg1, arg2, code)
343# define __inline_mathcodeNP2(func, arg1, arg2, code) \
344 __inline_mathcodeNP2_ (double, func, arg1, arg2, code)
345# define __inline_mathcode3(func, arg1, arg2, arg3, code) \
346 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
347# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
348 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)
349# endif
350
351# define __inline_mathcode_(float_type, func, arg, code) \
352 __MATH_INLINE float_type func (float_type) __THROW; \
353 __inline_mathcodeNP_(float_type, func, arg, code)
354
355# define __inline_mathcodeNP_(float_type, func, arg, code) \
356 __MATH_INLINE float_type __NTH (func (float_type arg)) \
357 { \
358 code; \
359 }
360
361
362# define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
363 __MATH_INLINE float_type func (float_type, float_type) __THROW; \
364 __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code)
365
366# define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \
367 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2)) \
368 { \
369 code; \
370 }
371
372# define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
373 __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \
374 __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code)
375
376# define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \
377 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2, \
378 float_type arg3)) \
379 { \
380 code; \
381 }
382# endif
383
384
385# if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
386/* Miscellaneous functions */
387
388/* __FAST_MATH__ is defined by gcc -ffast-math. */
389# ifdef __FAST_MATH__
390# ifdef __USE_GNU
391# define __sincos_code \
392 register long double __cosr; \
393 register long double __sinr; \
394 register unsigned int __swtmp; \
395 __asm __volatile__ \
396 ("fsincos\n\t" \
397 "fnstsw %w2\n\t" \
398 "testl $0x400, %2\n\t" \
399 "jz 1f\n\t" \
400 "fldpi\n\t" \
401 "fadd %%st(0)\n\t" \
402 "fxch %%st(1)\n\t" \
403 "2: fprem1\n\t" \
404 "fnstsw %w2\n\t" \
405 "testl $0x400, %2\n\t" \
406 "jnz 2b\n\t" \
407 "fstp %%st(1)\n\t" \
408 "fsincos\n\t" \
409 "1:" \
410 : "=t" (__cosr), "=u" (__sinr), "=a" (__swtmp) : "0" (__x)); \
411 *__sinx = __sinr; \
412 *__cosx = __cosr
413
414__MATH_INLINE void
415__NTH (__sincos (double __x, double *__sinx, double *__cosx))
416{
417 __sincos_code;
418}
419
420__MATH_INLINE void
421__NTH (__sincosf (float __x, float *__sinx, float *__cosx))
422{
423 __sincos_code;
424}
425
426__MATH_INLINE void
427__NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx))
428{
429 __sincos_code;
430}
431# endif
432
433
434/* Optimized inline implementation, sometimes with reduced precision
435 and/or argument range. */
436
437# if __GNUC_PREREQ (3, 5)
438# define __expm1_code \
439 register long double __temp; \
440 __temp = __builtin_expm1l (__x); \
441 return __temp ? __temp : __x
442# else
443# define __expm1_code \
444 register long double __value; \
445 register long double __exponent; \
446 register long double __temp; \
447 __asm __volatile__ \
448 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \
449 "fmul %%st(1) # x * log2(e)\n\t" \
450 "fst %%st(1)\n\t" \
451 "frndint # int(x * log2(e))\n\t" \
452 "fxch\n\t" \
453 "fsub %%st(1) # fract(x * log2(e))\n\t" \
454 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
455 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
456 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
457 __asm __volatile__ \
458 ("fscale # 2^int(x * log2(e))\n\t" \
459 : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \
460 __temp -= 1.0; \
461 __temp += __value; \
462 return __temp ? __temp : __x
463# endif
464__inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
465
466# if __GNUC_PREREQ (3, 4)
467__inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x))
468# else
469# define __exp_code \
470 register long double __value; \
471 register long double __exponent; \
472 __asm __volatile__ \
473 ("fldl2e # e^x = 2^(x * log2(e))\n\t" \
474 "fmul %%st(1) # x * log2(e)\n\t" \
475 "fst %%st(1)\n\t" \
476 "frndint # int(x * log2(e))\n\t" \
477 "fxch\n\t" \
478 "fsub %%st(1) # fract(x * log2(e))\n\t" \
479 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
480 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
481 __value += 1.0; \
482 __asm __volatile__ \
483 ("fscale" \
484 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
485 return __value
486__inline_mathcodeNP (exp, __x, __exp_code)
487__inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
488# endif
489
490
491# if !__GNUC_PREREQ (3, 5)
492__inline_mathcodeNP (tan, __x, \
493 register long double __value; \
494 register long double __value2 __attribute__ ((__unused__)); \
495 __asm __volatile__ \
496 ("fptan" \
497 : "=t" (__value2), "=u" (__value) : "0" (__x)); \
498 return __value)
499# endif
500# endif /* __FAST_MATH__ */
501
502
503# if __GNUC_PREREQ (3, 4)
504__inline_mathcodeNP2_ (long double, __atan2l, __y, __x,
505 return __builtin_atan2l (__y, __x))
506# else
507# define __atan2_code \
508 register long double __value; \
509 __asm __volatile__ \
510 ("fpatan" \
511 : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \
512 return __value
513# ifdef __FAST_MATH__
514__inline_mathcodeNP2 (atan2, __y, __x, __atan2_code)
515# endif
516__inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code)
517# endif
518
519
520# if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
521__inline_mathcodeNP2 (fmod, __x, __y, \
522 register long double __value; \
523 __asm __volatile__ \
524 ("1: fprem\n\t" \
525 "fnstsw %%ax\n\t" \
526 "sahf\n\t" \
527 "jp 1b" \
528 : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
529 return __value)
530# endif
531
532
533# ifdef __FAST_MATH__
534# if !__GNUC_PREREQ (3,3)
535__inline_mathopNP (sqrt, "fsqrt")
536__inline_mathopNP_ (long double, __sqrtl, "fsqrt")
537# define __libc_sqrtl(n) __sqrtl (n)
538# else
539# define __libc_sqrtl(n) __builtin_sqrtl (n)
540# endif
541# endif
542
543# if __GNUC_PREREQ (2, 8)
544__inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
545# ifdef __USE_ISOC99
546__inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
547__inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
548# endif
549__inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
550# else
551__inline_mathop (fabs, "fabs")
552__inline_mathop_ (long double, __fabsl, "fabs")
553# endif
554
555# ifdef __FAST_MATH__
556# if !__GNUC_PREREQ (3, 4)
557/* The argument range of this inline version is reduced. */
558__inline_mathopNP (sin, "fsin")
559/* The argument range of this inline version is reduced. */
560__inline_mathopNP (cos, "fcos")
561
562__inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)")
563# endif
564
565# if !__GNUC_PREREQ (3, 5)
566__inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)")
567
568__inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x)))
569__inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x))
570# endif
571
572# if !__GNUC_PREREQ (3, 4)
573__inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)")
574# endif
575# endif /* __FAST_MATH__ */
576
577__inline_mathcode_ (long double, __sgn1l, __x, \
578 __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \
579 { __xld: __x }; \
580 __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \
581 __n.__xi[1] = 0x80000000; \
582 __n.__xi[0] = 0; \
583 return __n.__xld)
584
585
586# ifdef __FAST_MATH__
587/* The argument range of the inline version of sinhl is slightly reduced. */
588__inline_mathcodeNP (sinh, __x, \
589 register long double __exm1 = __expm1l (__fabsl (__x)); \
590 return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
591
592__inline_mathcodeNP (cosh, __x, \
593 register long double __ex = __expl (__x); \
594 return 0.5 * (__ex + 1.0 / __ex))
595
596__inline_mathcodeNP (tanh, __x, \
597 register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \
598 return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
599# endif
600
601__inline_mathcodeNP (floor, __x, \
602 register long double __value; \
603 register int __ignore; \
604 unsigned short int __cw; \
605 unsigned short int __cwtmp; \
606 __asm __volatile ("fnstcw %3\n\t" \
607 "movzwl %3, %1\n\t" \
608 "andl $0xf3ff, %1\n\t" \
609 "orl $0x0400, %1\n\t" /* rounding down */ \
610 "movw %w1, %2\n\t" \
611 "fldcw %2\n\t" \
612 "frndint\n\t" \
613 "fldcw %3" \
614 : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \
615 "=m" (__cw) \
616 : "0" (__x)); \
617 return __value)
618
619__inline_mathcodeNP (ceil, __x, \
620 register long double __value; \
621 register int __ignore; \
622 unsigned short int __cw; \
623 unsigned short int __cwtmp; \
624 __asm __volatile ("fnstcw %3\n\t" \
625 "movzwl %3, %1\n\t" \
626 "andl $0xf3ff, %1\n\t" \
627 "orl $0x0800, %1\n\t" /* rounding up */ \
628 "movw %w1, %2\n\t" \
629 "fldcw %2\n\t" \
630 "frndint\n\t" \
631 "fldcw %3" \
632 : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \
633 "=m" (__cw) \
634 : "0" (__x)); \
635 return __value)
636
637# ifdef __FAST_MATH__
638# define __ldexp_code \
639 register long double __value; \
640 __asm __volatile__ \
641 ("fscale" \
642 : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \
643 return __value
644
645__MATH_INLINE double
646__NTH (ldexp (double __x, int __y))
647{
648 __ldexp_code;
649}
650# endif
651
652
653/* Optimized versions for some non-standardized functions. */
654# ifdef __USE_ISOC99
655
656# ifdef __FAST_MATH__
657__inline_mathcodeNP (expm1, __x, __expm1_code)
658
659/* We cannot rely on M_SQRT being defined. So we do it for ourself
660 here. */
661# define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */
662
663# if !__GNUC_PREREQ (3, 5)
664__inline_mathcodeNP (log1p, __x, \
665 register long double __value; \
666 if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \
667 __value = logl (1.0 + __x); \
668 else \
669 __asm __volatile__ \
670 ("fldln2\n\t" \
671 "fxch\n\t" \
672 "fyl2xp1" \
673 : "=t" (__value) : "0" (__x) : "st(1)"); \
674 return __value)
675# endif
676
677
678/* The argument range of the inline version of asinhl is slightly reduced. */
679__inline_mathcodeNP (asinh, __x, \
680 register long double __y = __fabsl (__x); \
681 return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \
682 * __sgn1l (__x)))
683
684__inline_mathcodeNP (acosh, __x, \
685 return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0)))
686
687__inline_mathcodeNP (atanh, __x, \
688 register long double __y = __fabsl (__x); \
689 return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
690
691/* The argument range of the inline version of hypotl is slightly reduced. */
692__inline_mathcodeNP2 (hypot, __x, __y,
693 return __libc_sqrtl (__x * __x + __y * __y))
694
695# if !__GNUC_PREREQ (3, 5)
696__inline_mathcodeNP(logb, __x, \
697 register long double __value; \
698 register long double __junk; \
699 __asm __volatile__ \
700 ("fxtract\n\t" \
701 : "=t" (__junk), "=u" (__value) : "0" (__x)); \
702 return __value)
703# endif
704
705# endif
706# endif
707
708# ifdef __USE_ISOC99
709# ifdef __FAST_MATH__
710
711# if !__GNUC_PREREQ (3, 5)
712__inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)")
713# endif
714
715__MATH_INLINE float
716__NTH (ldexpf (float __x, int __y))
717{
718 __ldexp_code;
719}
720
721__MATH_INLINE long double
722__NTH (ldexpl (long double __x, int __y))
723{
724 __ldexp_code;
725}
726
727__inline_mathopNP (rint, "frndint")
728# endif /* __FAST_MATH__ */
729
730# define __lrint_code \
731 long int __lrintres; \
732 __asm__ __volatile__ \
733 ("fistpl %0" \
734 : "=m" (__lrintres) : "t" (__x) : "st"); \
735 return __lrintres
736__MATH_INLINE long int
737__NTH (lrintf (float __x))
738{
739 __lrint_code;
740}
741__MATH_INLINE long int
742__NTH (lrint (double __x))
743{
744 __lrint_code;
745}
746__MATH_INLINE long int
747__NTH (lrintl (long double __x))
748{
749 __lrint_code;
750}
751# undef __lrint_code
752
753# define __llrint_code \
754 long long int __llrintres; \
755 __asm__ __volatile__ \
756 ("fistpll %0" \
757 : "=m" (__llrintres) : "t" (__x) : "st"); \
758 return __llrintres
759__extension__
760__MATH_INLINE long long int
761__NTH (llrintf (float __x))
762{
763 __llrint_code;
764}
765__extension__
766__MATH_INLINE long long int
767__NTH (llrint (double __x))
768{
769 __llrint_code;
770}
771__extension__
772__MATH_INLINE long long int
773__NTH (llrintl (long double __x))
774{
775 __llrint_code;
776}
777# undef __llrint_code
778
779# endif
780
781
782# ifdef __USE_MISC
783
784# if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5)
785__inline_mathcodeNP2 (drem, __x, __y, \
786 register double __value; \
787 register int __clobbered; \
788 __asm __volatile__ \
789 ("1: fprem1\n\t" \
790 "fstsw %%ax\n\t" \
791 "sahf\n\t" \
792 "jp 1b" \
793 : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \
794 return __value)
795# endif
796
797
798/* This function is used in the `isfinite' macro. */
799__MATH_INLINE int
800__NTH (__finite (double __x))
801{
802 return (__extension__
803 (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
804 | 0x800fffffu) + 1) >> 31));
805}
806
807# endif /* __USE_MISC */
808
809/* Undefine some of the large macros which are not used anymore. */
810# undef __atan2_code
811# ifdef __FAST_MATH__
812# undef __expm1_code
813# undef __exp_code
814# undef __sincos_code
815# endif /* __FAST_MATH__ */
816
817# endif /* __NO_MATH_INLINES */
818
819
820/* This code is used internally in the GNU libc. */
821# ifdef __LIBC_INTERNAL_MATH_INLINES
822__inline_mathop (__ieee754_sqrt, "fsqrt")
823__inline_mathcode2_ (long double, __ieee754_atan2l, __y, __x,
824 register long double __value;
825 __asm __volatile__ ("fpatan\n\t"
826 : "=t" (__value)
827 : "0" (__x), "u" (__y) : "st(1)");
828 return __value;)
829# endif
830
831#endif /* !__SSE2_MATH__ && !__x86_64__ */
832