1 /* Inline math functions for i387. 2 Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2003,2004,2006,2007,2009, 3 2010 Free Software Foundation, Inc. 4 This file is part of the GNU C Library. 5 Contributed by John C. Bowman <bowman (at) math.ualberta.ca>, 1995. 6 7 The GNU C Library is free software; you can redistribute it and/or 8 modify it under the terms of the GNU Lesser General Public 9 License as published by the Free Software Foundation; either 10 version 2.1 of the License, or (at your option) any later version. 11 12 The GNU C Library is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Lesser General Public License for more details. 16 17 You should have received a copy of the GNU Lesser General Public 18 License along with the GNU C Library; if not, write to the Free 19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 20 02111-1307 USA. */ 21 22 #ifndef _MATH_H 23 # error "Never use <bits/mathinline.h> directly; include <math.h> instead." 24 #endif 25 26 #ifndef __extern_inline 27 # define __MATH_INLINE __inline 28 #else 29 # define __MATH_INLINE __extern_inline 30 #endif 31 32 33 #if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2 34 /* GCC 2.97 and up have builtins that actually can be used. */ 35 # if !__GNUC_PREREQ (2,97) 36 /* ISO C99 defines some macros to perform unordered comparisons. The 37 ix87 FPU supports this with special opcodes and we should use them. 38 These must not be inline functions since we have to be able to handle 39 all floating-point types. */ 40 # undef isgreater 41 # undef isgreaterequal 42 # undef isless 43 # undef islessequal 44 # undef islessgreater 45 # undef isunordered 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; }) 59 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; }) 65 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; }) 71 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; }) 77 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; }) 90 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; }) 96 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; }) 102 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; }) 108 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; }) 114 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 */ 122 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 __NTH (__signbitf (float __x)) 129 { 130 __extension__ union { float __f; int __i; } __u = { __f: __x }; 131 return __u.__i < 0; 132 } 133 __MATH_INLINE int 134 __NTH (__signbit (double __x)) 135 { 136 __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; 137 return __u.__i[1] < 0; 138 } 139 __MATH_INLINE int 140 __NTH (__signbitl (long double __x)) 141 { 142 __extension__ union { long double __l; int __i[3]; } __u = { __l: __x }; 143 return (__u.__i[2] & 0x8000) != 0; 144 } 145 # endif 146 #endif 147 148 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) 152 153 #if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \ 154 && defined __OPTIMIZE__) 155 156 /* The inline functions do not set errno or raise necessarily the 157 correct exceptions. */ 158 # undef math_errhandling 159 160 /* A macro to define float, double, and long double versions of various 161 math functions for the ix87 FPU. FUNC is the function name (which will 162 be suffixed with f and l for the float and long double version, 163 respectively). OP is the name of the FPU operation. 164 We define two sets of macros. The set with the additional NP 165 doesn't add a prototype declaration. */ 166 167 #if defined __USE_MISC || defined __USE_ISOC99 168 # define __inline_mathop(func, op) \ 169 __inline_mathop_ (double, func, op) \ 170 __inline_mathop_ (float, __CONCAT(func,f), op) \ 171 __inline_mathop_ (long double, __CONCAT(func,l), op) 172 # define __inline_mathopNP(func, op) \ 173 __inline_mathopNP_ (double, func, op) \ 174 __inline_mathopNP_ (float, __CONCAT(func,f), op) \ 175 __inline_mathopNP_ (long double, __CONCAT(func,l), op) 176 #else 177 # define __inline_mathop(func, op) \ 178 __inline_mathop_ (double, func, op) 179 # define __inline_mathopNP(func, op) \ 180 __inline_mathopNP_ (double, func, op) 181 #endif 182 183 #define __inline_mathop_(float_type, func, op) \ 184 __inline_mathop_decl_ (float_type, func, op, "0" (__x)) 185 #define __inline_mathopNP_(float_type, func, op) \ 186 __inline_mathop_declNP_ (float_type, func, op, "0" (__x)) 187 188 189 #if defined __USE_MISC || defined __USE_ISOC99 190 # define __inline_mathop_decl(func, op, params...) \ 191 __inline_mathop_decl_ (double, func, op, params) \ 192 __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \ 193 __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params) 194 # define __inline_mathop_declNP(func, op, params...) \ 195 __inline_mathop_declNP_ (double, func, op, params) \ 196 __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \ 197 __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params) 198 #else 199 # define __inline_mathop_decl(func, op, params...) \ 200 __inline_mathop_decl_ (double, func, op, params) 201 # define __inline_mathop_declNP(func, op, params...) \ 202 __inline_mathop_declNP_ (double, func, op, params) 203 #endif 204 205 #define __inline_mathop_decl_(float_type, func, op, params...) \ 206 __MATH_INLINE float_type func (float_type) __THROW; \ 207 __inline_mathop_declNP_ (float_type, func, op, params) 208 209 #define __inline_mathop_declNP_(float_type, func, op, params...) \ 210 __MATH_INLINE float_type __NTH (func (float_type __x)) \ 211 { \ 212 register float_type __result; \ 213 __asm __volatile__ (op : "=t" (__result) : params); \ 214 return __result; \ 215 } 216 217 218 #if defined __USE_MISC || defined __USE_ISOC99 219 # define __inline_mathcode(func, arg, code) \ 220 __inline_mathcode_ (double, func, arg, code) \ 221 __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \ 222 __inline_mathcode_ (long double, __CONCAT(func,l), arg, code) 223 # define __inline_mathcodeNP(func, arg, code) \ 224 __inline_mathcodeNP_ (double, func, arg, code) \ 225 __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \ 226 __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code) 227 # define __inline_mathcode2(func, arg1, arg2, code) \ 228 __inline_mathcode2_ (double, func, arg1, arg2, code) \ 229 __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \ 230 __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code) 231 # define __inline_mathcodeNP2(func, arg1, arg2, code) \ 232 __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \ 233 __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \ 234 __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code) 235 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \ 236 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \ 237 __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \ 238 __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code) 239 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \ 240 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \ 241 __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \ 242 __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code) 243 #else 244 # define __inline_mathcode(func, arg, code) \ 245 __inline_mathcode_ (double, func, (arg), code) 246 # define __inline_mathcodeNP(func, arg, code) \ 247 __inline_mathcodeNP_ (double, func, (arg), code) 248 # define __inline_mathcode2(func, arg1, arg2, code) \ 249 __inline_mathcode2_ (double, func, arg1, arg2, code) 250 # define __inline_mathcodeNP2(func, arg1, arg2, code) \ 251 __inline_mathcodeNP2_ (double, func, arg1, arg2, code) 252 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \ 253 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) 254 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \ 255 __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) 256 #endif 257 258 #define __inline_mathcode_(float_type, func, arg, code) \ 259 __MATH_INLINE float_type func (float_type) __THROW; \ 260 __inline_mathcodeNP_(float_type, func, arg, code) 261 262 #define __inline_mathcodeNP_(float_type, func, arg, code) \ 263 __MATH_INLINE float_type __NTH (func (float_type arg)) \ 264 { \ 265 code; \ 266 } 267 268 269 #define __inline_mathcode2_(float_type, func, arg1, arg2, code) \ 270 __MATH_INLINE float_type func (float_type, float_type) __THROW; \ 271 __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code) 272 273 #define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \ 274 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2)) \ 275 { \ 276 code; \ 277 } 278 279 #define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \ 280 __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \ 281 __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) 282 283 #define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \ 284 __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2, \ 285 float_type arg3)) \ 286 { \ 287 code; \ 288 } 289 #endif 290 291 292 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ 293 /* Miscellaneous functions */ 294 295 __inline_mathcode (__sgn, __x, \ 296 return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0)) 297 298 /* __FAST_MATH__ is defined by gcc -ffast-math. */ 299 #ifdef __FAST_MATH__ 300 __inline_mathcode (__pow2, __x, \ 301 register long double __value; \ 302 register long double __exponent; \ 303 __extension__ long long int __p = (long long int) __x; \ 304 if (__x == (long double) __p) \ 305 { \ 306 __asm __volatile__ \ 307 ("fscale" \ 308 : "=t" (__value) : "0" (1.0), "u" (__x)); \ 309 return __value; \ 310 } \ 311 __asm __volatile__ \ 312 ("fld %%st(0)\n\t" \ 313 "frndint # int(x)\n\t" \ 314 "fxch\n\t" \ 315 "fsub %%st(1) # fract(x)\n\t" \ 316 "f2xm1 # 2^(fract(x)) - 1\n\t" \ 317 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ 318 __value += 1.0; \ 319 __asm __volatile__ \ 320 ("fscale" \ 321 : "=t" (__value) : "0" (__value), "u" (__exponent)); \ 322 return __value) 323 324 # ifdef __USE_GNU 325 # define __sincos_code \ 326 register long double __cosr; \ 327 register long double __sinr; \ 328 __asm __volatile__ \ 329 ("fsincos\n\t" \ 330 "fnstsw %%ax\n\t" \ 331 "testl $0x400, %%eax\n\t" \ 332 "jz 1f\n\t" \ 333 "fldpi\n\t" \ 334 "fadd %%st(0)\n\t" \ 335 "fxch %%st(1)\n\t" \ 336 "2: fprem1\n\t" \ 337 "fnstsw %%ax\n\t" \ 338 "testl $0x400, %%eax\n\t" \ 339 "jnz 2b\n\t" \ 340 "fstp %%st(1)\n\t" \ 341 "fsincos\n\t" \ 342 "1:" \ 343 : "=t" (__cosr), "=u" (__sinr) : "0" (__x)); \ 344 *__sinx = __sinr; \ 345 *__cosx = __cosr 346 347 __MATH_INLINE void 348 __NTH (__sincos (double __x, double *__sinx, double *__cosx)) 349 { 350 __sincos_code; 351 } 352 353 __MATH_INLINE void 354 __NTH (__sincosf (float __x, float *__sinx, float *__cosx)) 355 { 356 __sincos_code; 357 } 358 359 __MATH_INLINE void 360 __NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx)) 361 { 362 __sincos_code; 363 } 364 # endif 365 366 367 /* Optimized inline implementation, sometimes with reduced precision 368 and/or argument range. */ 369 370 # if __GNUC_PREREQ (3, 5) 371 # define __expm1_code \ 372 register long double __temp; \ 373 __temp = __builtin_expm1l (__x); \ 374 return __temp ? __temp : __x 375 # else 376 # define __expm1_code \ 377 register long double __value; \ 378 register long double __exponent; \ 379 register long double __temp; \ 380 __asm __volatile__ \ 381 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \ 382 "fmul %%st(1) # x * log2(e)\n\t" \ 383 "fst %%st(1)\n\t" \ 384 "frndint # int(x * log2(e))\n\t" \ 385 "fxch\n\t" \ 386 "fsub %%st(1) # fract(x * log2(e))\n\t" \ 387 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \ 388 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \ 389 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ 390 __asm __volatile__ \ 391 ("fscale # 2^int(x * log2(e))\n\t" \ 392 : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \ 393 __temp -= 1.0; \ 394 __temp += __value; \ 395 return __temp ? __temp : __x 396 # endif 397 __inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code) 398 399 # if __GNUC_PREREQ (3, 4) 400 __inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x)) 401 # else 402 # define __exp_code \ 403 register long double __value; \ 404 register long double __exponent; \ 405 __asm __volatile__ \ 406 ("fldl2e # e^x = 2^(x * log2(e))\n\t" \ 407 "fmul %%st(1) # x * log2(e)\n\t" \ 408 "fst %%st(1)\n\t" \ 409 "frndint # int(x * log2(e))\n\t" \ 410 "fxch\n\t" \ 411 "fsub %%st(1) # fract(x * log2(e))\n\t" \ 412 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \ 413 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ 414 __value += 1.0; \ 415 __asm __volatile__ \ 416 ("fscale" \ 417 : "=t" (__value) : "0" (__value), "u" (__exponent)); \ 418 return __value 419 __inline_mathcodeNP (exp, __x, __exp_code) 420 __inline_mathcodeNP_ (long double, __expl, __x, __exp_code) 421 # endif 422 423 424 # if !__GNUC_PREREQ (3, 5) 425 __inline_mathcodeNP (tan, __x, \ 426 register long double __value; \ 427 register long double __value2 __attribute__ ((__unused__)); \ 428 __asm __volatile__ \ 429 ("fptan" \ 430 : "=t" (__value2), "=u" (__value) : "0" (__x)); \ 431 return __value) 432 # endif 433 #endif /* __FAST_MATH__ */ 434 435 436 #if __GNUC_PREREQ (3, 4) 437 __inline_mathcodeNP2_ (long double, __atan2l, __y, __x, 438 return __builtin_atan2l (__y, __x)) 439 #else 440 # define __atan2_code \ 441 register long double __value; \ 442 __asm __volatile__ \ 443 ("fpatan" \ 444 : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \ 445 return __value 446 # ifdef __FAST_MATH__ 447 __inline_mathcodeNP2 (atan2, __y, __x, __atan2_code) 448 # endif 449 __inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code) 450 #endif 451 452 453 #if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) 454 __inline_mathcodeNP2 (fmod, __x, __y, \ 455 register long double __value; \ 456 __asm __volatile__ \ 457 ("1: fprem\n\t" \ 458 "fnstsw %%ax\n\t" \ 459 "sahf\n\t" \ 460 "jp 1b" \ 461 : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \ 462 return __value) 463 #endif 464 465 466 #ifdef __FAST_MATH__ 467 # if !__GNUC_PREREQ (3,3) 468 __inline_mathopNP (sqrt, "fsqrt") 469 __inline_mathopNP_ (long double, __sqrtl, "fsqrt") 470 # define __libc_sqrtl(n) __sqrtl (n) 471 # else 472 # define __libc_sqrtl(n) __builtin_sqrtl (n) 473 # endif 474 #endif 475 476 #if __GNUC_PREREQ (2, 8) 477 __inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x)) 478 # if defined __USE_MISC || defined __USE_ISOC99 479 __inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x)) 480 __inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x)) 481 # endif 482 __inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x)) 483 #else 484 __inline_mathop (fabs, "fabs") 485 __inline_mathop_ (long double, __fabsl, "fabs") 486 #endif 487 488 #ifdef __FAST_MATH__ 489 # if !__GNUC_PREREQ (3, 4) 490 /* The argument range of this inline version is reduced. */ 491 __inline_mathopNP (sin, "fsin") 492 /* The argument range of this inline version is reduced. */ 493 __inline_mathopNP (cos, "fcos") 494 495 __inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)") 496 # endif 497 498 # if !__GNUC_PREREQ (3, 5) 499 __inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)") 500 501 __inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x))) 502 __inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x)) 503 # endif 504 505 # if !__GNUC_PREREQ (3, 4) 506 __inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)") 507 # endif 508 #endif /* __FAST_MATH__ */ 509 510 __inline_mathcode_ (long double, __sgn1l, __x, \ 511 __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \ 512 { __xld: __x }; \ 513 __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \ 514 __n.__xi[1] = 0x80000000; \ 515 __n.__xi[0] = 0; \ 516 return __n.__xld) 517 518 519 #ifdef __FAST_MATH__ 520 /* The argument range of the inline version of sinhl is slightly reduced. */ 521 __inline_mathcodeNP (sinh, __x, \ 522 register long double __exm1 = __expm1l (__fabsl (__x)); \ 523 return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x)) 524 525 __inline_mathcodeNP (cosh, __x, \ 526 register long double __ex = __expl (__x); \ 527 return 0.5 * (__ex + 1.0 / __ex)) 528 529 __inline_mathcodeNP (tanh, __x, \ 530 register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \ 531 return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x)) 532 #endif 533 534 __inline_mathcodeNP (floor, __x, \ 535 register long double __value; \ 536 register int __ignore; \ 537 unsigned short int __cw; \ 538 unsigned short int __cwtmp; \ 539 __asm __volatile ("fnstcw %3\n\t" \ 540 "movzwl %3, %1\n\t" \ 541 "andl $0xf3ff, %1\n\t" \ 542 "orl $0x0400, %1\n\t" /* rounding down */ \ 543 "movw %w1, %2\n\t" \ 544 "fldcw %2\n\t" \ 545 "frndint\n\t" \ 546 "fldcw %3" \ 547 : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \ 548 "=m" (__cw) \ 549 : "0" (__x)); \ 550 return __value) 551 552 __inline_mathcodeNP (ceil, __x, \ 553 register long double __value; \ 554 register int __ignore; \ 555 unsigned short int __cw; \ 556 unsigned short int __cwtmp; \ 557 __asm __volatile ("fnstcw %3\n\t" \ 558 "movzwl %3, %1\n\t" \ 559 "andl $0xf3ff, %1\n\t" \ 560 "orl $0x0800, %1\n\t" /* rounding up */ \ 561 "movw %w1, %2\n\t" \ 562 "fldcw %2\n\t" \ 563 "frndint\n\t" \ 564 "fldcw %3" \ 565 : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \ 566 "=m" (__cw) \ 567 : "0" (__x)); \ 568 return __value) 569 570 #ifdef __FAST_MATH__ 571 # define __ldexp_code \ 572 register long double __value; \ 573 __asm __volatile__ \ 574 ("fscale" \ 575 : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \ 576 return __value 577 578 __MATH_INLINE double 579 __NTH (ldexp (double __x, int __y)) 580 { 581 __ldexp_code; 582 } 583 #endif 584 585 586 /* Optimized versions for some non-standardized functions. */ 587 #if defined __USE_ISOC99 || defined __USE_MISC 588 589 # ifdef __FAST_MATH__ 590 __inline_mathcodeNP (expm1, __x, __expm1_code) 591 592 /* We cannot rely on M_SQRT being defined. So we do it for ourself 593 here. */ 594 # define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */ 595 596 # if !__GNUC_PREREQ (3, 5) 597 __inline_mathcodeNP (log1p, __x, \ 598 register long double __value; \ 599 if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \ 600 __value = logl (1.0 + __x); \ 601 else \ 602 __asm __volatile__ \ 603 ("fldln2\n\t" \ 604 "fxch\n\t" \ 605 "fyl2xp1" \ 606 : "=t" (__value) : "0" (__x) : "st(1)"); \ 607 return __value) 608 # endif 609 610 611 /* The argument range of the inline version of asinhl is slightly reduced. */ 612 __inline_mathcodeNP (asinh, __x, \ 613 register long double __y = __fabsl (__x); \ 614 return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \ 615 * __sgn1l (__x))) 616 617 __inline_mathcodeNP (acosh, __x, \ 618 return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0))) 619 620 __inline_mathcodeNP (atanh, __x, \ 621 register long double __y = __fabsl (__x); \ 622 return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x)) 623 624 /* The argument range of the inline version of hypotl is slightly reduced. */ 625 __inline_mathcodeNP2 (hypot, __x, __y, 626 return __libc_sqrtl (__x * __x + __y * __y)) 627 628 # if !__GNUC_PREREQ (3, 5) 629 __inline_mathcodeNP(logb, __x, \ 630 register long double __value; \ 631 register long double __junk; \ 632 __asm __volatile__ \ 633 ("fxtract\n\t" \ 634 : "=t" (__junk), "=u" (__value) : "0" (__x)); \ 635 return __value) 636 # endif 637 638 # endif 639 #endif 640 641 #ifdef __USE_ISOC99 642 # ifdef __FAST_MATH__ 643 644 # if !__GNUC_PREREQ (3, 5) 645 __inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)") 646 # endif 647 648 __MATH_INLINE float 649 __NTH (ldexpf (float __x, int __y)) 650 { 651 __ldexp_code; 652 } 653 654 __MATH_INLINE long double 655 __NTH (ldexpl (long double __x, int __y)) 656 { 657 __ldexp_code; 658 } 659 660 __inline_mathopNP (rint, "frndint") 661 # endif /* __FAST_MATH__ */ 662 663 # define __lrint_code \ 664 long int __lrintres; \ 665 __asm__ __volatile__ \ 666 ("fistpl %0" \ 667 : "=m" (__lrintres) : "t" (__x) : "st"); \ 668 return __lrintres 669 __MATH_INLINE long int 670 __NTH (lrintf (float __x)) 671 { 672 __lrint_code; 673 } 674 __MATH_INLINE long int 675 __NTH (lrint (double __x)) 676 { 677 __lrint_code; 678 } 679 __MATH_INLINE long int 680 __NTH (lrintl (long double __x)) 681 { 682 __lrint_code; 683 } 684 # undef __lrint_code 685 686 # define __llrint_code \ 687 long long int __llrintres; \ 688 __asm__ __volatile__ \ 689 ("fistpll %0" \ 690 : "=m" (__llrintres) : "t" (__x) : "st"); \ 691 return __llrintres 692 __MATH_INLINE long long int 693 __NTH (llrintf (float __x)) 694 { 695 __llrint_code; 696 } 697 __MATH_INLINE long long int 698 __NTH (llrint (double __x)) 699 { 700 __llrint_code; 701 } 702 __MATH_INLINE long long int 703 __NTH (llrintl (long double __x)) 704 { 705 __llrint_code; 706 } 707 # undef __llrint_code 708 709 #endif 710 711 712 #ifdef __USE_MISC 713 714 # if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) 715 __inline_mathcodeNP2 (drem, __x, __y, \ 716 register double __value; \ 717 register int __clobbered; \ 718 __asm __volatile__ \ 719 ("1: fprem1\n\t" \ 720 "fstsw %%ax\n\t" \ 721 "sahf\n\t" \ 722 "jp 1b" \ 723 : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \ 724 return __value) 725 # endif 726 727 728 /* This function is used in the `isfinite' macro. */ 729 __MATH_INLINE int 730 __NTH (__finite (double __x)) 731 { 732 return (__extension__ 733 (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1] 734 | 0x800fffffu) + 1) >> 31)); 735 } 736 737 /* Miscellaneous functions */ 738 # ifdef __FAST_MATH__ 739 __inline_mathcode (__coshm1, __x, \ 740 register long double __exm1 = __expm1l (__fabsl (__x)); \ 741 return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1) 742 743 __inline_mathcode (__acosh1p, __x, \ 744 return log1pl (__x + __libc_sqrtl (__x) * __libc_sqrtl (__x + 2.0))) 745 746 # endif /* __FAST_MATH__ */ 747 #endif /* __USE_MISC */ 748 749 /* Undefine some of the large macros which are not used anymore. */ 750 #undef __atan2_code 751 #ifdef __FAST_MATH__ 752 # undef __expm1_code 753 # undef __exp_code 754 # undef __sincos_code 755 #endif /* __FAST_MATH__ */ 756 757 #endif /* __NO_MATH_INLINES */ 758 759 760 /* This code is used internally in the GNU libc. */ 761 #ifdef __LIBC_INTERNAL_MATH_INLINES 762 __inline_mathop (__ieee754_sqrt, "fsqrt") 763 __inline_mathcode2 (__ieee754_atan2, __y, __x, 764 register long double __value; 765 __asm __volatile__ ("fpatan\n\t" 766 : "=t" (__value) 767 : "0" (__x), "u" (__y) : "st(1)"); 768 return __value;) 769 #endif 770 771 #endif /* __GNUC__ */ 772