1 2 #ifndef __GNUC__ 3 #error This file should be included only with GCC compiler 4 #endif 5 6 #ifndef __NO_ISOCEXT 7 #if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \ 8 || !defined __STRICT_ANSI__ || defined __cplusplus 9 10 #if __MINGW_GNUC_PREREQ(3, 3) 11 #define HUGE_VALF __builtin_huge_valf() 12 #define HUGE_VALL __builtin_huge_vall() 13 #define INFINITY __builtin_inf() 14 #define NAN __builtin_nan("") 15 #else 16 extern const float __INFF; 17 #define HUGE_VALF __INFF 18 extern const long double __INFL; 19 #define HUGE_VALL __INFL 20 #define INFINITY HUGE_VALF 21 extern const double __QNAN; 22 #define NAN __QNAN 23 #endif /* __MINGW_GNUC_PREREQ(3, 3) */ 24 25 /* Use the compiler's builtin define for FLT_EVAL_METHOD to 26 set float_t and double_t. */ 27 #if defined(__FLT_EVAL_METHOD__) 28 # if ( __FLT_EVAL_METHOD__== 0) 29 typedef float float_t; 30 typedef double double_t; 31 # elif (__FLT_EVAL_METHOD__ == 1) 32 typedef double float_t; 33 typedef double double_t; 34 # elif (__FLT_EVAL_METHOD__ == 2) 35 typedef long double float_t; 36 typedef long double double_t; 37 #endif 38 #else /* ix87 FPU default */ 39 typedef long double float_t; 40 typedef long double double_t; 41 #endif 42 43 /* 7.12.3.1 */ 44 /* 45 Return values for fpclassify. 46 These are based on Intel x87 fpu condition codes 47 in the high byte of status word and differ from 48 the return values for MS IEEE 754 extension _fpclass() 49 */ 50 #define FP_NAN 0x0100 51 #define FP_NORMAL 0x0400 52 #define FP_INFINITE (FP_NAN | FP_NORMAL) 53 #define FP_ZERO 0x4000 54 #define FP_SUBNORMAL (FP_NORMAL | FP_ZERO) 55 /* 0x0200 is signbit mask */ 56 57 /* 58 We can't inline float or double, because we want to ensure truncation 59 to semantic type before classification. 60 (A normal long double value might become subnormal when 61 converted to double, and zero when converted to float.) 62 */ 63 64 extern int __cdecl __fpclassifyl (long double); 65 extern int __cdecl __fpclassifyf (float); 66 extern int __cdecl __fpclassify (double); 67 68 #ifndef __CRT__NO_INLINE __fpclassifyl(long double x)69 __CRT_INLINE int __cdecl __fpclassifyl (long double x) { 70 unsigned short sw; 71 __asm__ __volatile__ ("fxam; fstsw %%ax;" : "=a" (sw): "t" (x)); 72 return sw & (FP_NAN | FP_NORMAL | FP_ZERO ); 73 } __fpclassify(double x)74 __CRT_INLINE int __cdecl __fpclassify (double x) { 75 unsigned short sw; 76 __asm__ __volatile__ ("fxam; fstsw %%ax;" : "=a" (sw): "t" (x)); 77 return sw & (FP_NAN | FP_NORMAL | FP_ZERO ); 78 } __fpclassifyf(float x)79 __CRT_INLINE int __cdecl __fpclassifyf (float x) { 80 unsigned short sw; 81 __asm__ __volatile__ ("fxam; fstsw %%ax;" : "=a" (sw): "t" (x)); 82 return sw & (FP_NAN | FP_NORMAL | FP_ZERO ); 83 } 84 #endif 85 86 #define fpclassify(x) (sizeof (x) == sizeof (float) ? __fpclassifyf (x) \ 87 : sizeof (x) == sizeof (double) ? __fpclassify (x) \ 88 : __fpclassifyl (x)) 89 90 /* 7.12.3.2 */ 91 #define isfinite(x) ((fpclassify(x) & FP_NAN) == 0) 92 93 /* 7.12.3.3 */ 94 #define isinf(x) (fpclassify(x) == FP_INFINITE) 95 96 /* 7.12.3.4 */ 97 /* We don't need to worry about truncation here: 98 A NaN stays a NaN. */ 99 100 extern int __cdecl __isnan (double); 101 extern int __cdecl __isnanf (float); 102 extern int __cdecl __isnanl (long double); 103 104 #ifndef __CRT__NO_INLINE __isnan(double _x)105 __CRT_INLINE int __cdecl __isnan (double _x) 106 { 107 unsigned short sw; 108 __asm__ __volatile__ ("fxam;" 109 "fstsw %%ax": "=a" (sw) : "t" (_x)); 110 return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL)) 111 == FP_NAN; 112 } 113 __isnanf(float _x)114 __CRT_INLINE int __cdecl __isnanf (float _x) 115 { 116 unsigned short sw; 117 __asm__ __volatile__ ("fxam;" 118 "fstsw %%ax": "=a" (sw) : "t" (_x)); 119 return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL)) 120 == FP_NAN; 121 } 122 __isnanl(long double _x)123 __CRT_INLINE int __cdecl __isnanl (long double _x) 124 { 125 unsigned short sw; 126 __asm__ __volatile__ ("fxam;" 127 "fstsw %%ax": "=a" (sw) : "t" (_x)); 128 return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL)) 129 == FP_NAN; 130 } 131 #endif 132 133 #define isnan(x) (sizeof (x) == sizeof (float) ? __isnanf (x) \ 134 : sizeof (x) == sizeof (double) ? __isnan (x) \ 135 : __isnanl (x)) 136 137 /* 7.12.3.5 */ 138 #define isnormal(x) (fpclassify(x) == FP_NORMAL) 139 140 /* 7.12.3.6 The signbit macro */ 141 extern int __cdecl __signbit (double); 142 extern int __cdecl __signbitf (float); 143 extern int __cdecl __signbitl (long double); 144 #ifndef __CRT__NO_INLINE __signbit(double x)145 __CRT_INLINE int __cdecl __signbit (double x) { 146 unsigned short stw; 147 __asm__ __volatile__ ( "fxam; fstsw %%ax;": "=a" (stw) : "t" (x)); 148 return stw & 0x0200; 149 } 150 __signbitf(float x)151 __CRT_INLINE int __cdecl __signbitf (float x) { 152 unsigned short stw; 153 __asm__ __volatile__ ("fxam; fstsw %%ax;": "=a" (stw) : "t" (x)); 154 return stw & 0x0200; 155 } 156 __signbitl(long double x)157 __CRT_INLINE int __cdecl __signbitl (long double x) { 158 unsigned short stw; 159 __asm__ __volatile__ ("fxam; fstsw %%ax;": "=a" (stw) : "t" (x)); 160 return stw & 0x0200; 161 } 162 #endif 163 164 #define signbit(x) (sizeof (x) == sizeof (float) ? __signbitf (x) \ 165 : sizeof (x) == sizeof (double) ? __signbit (x) \ 166 : __signbitl (x)) 167 168 /* 7.12.4 Trigonometric functions: Double in C89 */ 169 // Already in math.h 170 171 /* 7.12.5 Hyperbolic functions: Double in C89 */ 172 // Already in math.h 173 174 /* Inverse hyperbolic trig functions */ 175 /* 7.12.5.1 */ 176 extern double __cdecl acosh (double); 177 extern float __cdecl acoshf (float); 178 extern long double __cdecl acoshl (long double); 179 180 /* 7.12.5.2 */ 181 extern double __cdecl asinh (double); 182 extern float __cdecl asinhf (float); 183 extern long double __cdecl asinhl (long double); 184 185 /* 7.12.5.3 */ 186 extern double __cdecl atanh (double); 187 extern float __cdecl atanhf (float); 188 extern long double __cdecl atanhl (long double); 189 190 /* Exponentials and logarithms */ 191 /* 7.12.6.1 Double in C89 */ 192 // exp functions. Already in math.h 193 194 /* 7.12.6.2 */ 195 extern double __cdecl exp2(double); 196 extern float __cdecl exp2f(float); 197 extern long double __cdecl exp2l(long double); 198 199 /* 7.12.6.3 The expm1 functions */ 200 /* TODO: These could be inlined */ 201 extern double __cdecl expm1(double); 202 extern float __cdecl expm1f(float); 203 extern long double __cdecl expm1l(long double); 204 205 /* 7.12.6.4 Double in C89 */ 206 // frexp functions. Already in math.h 207 208 /* 7.12.6.5 */ 209 #define FP_ILOGB0 ((int)0x80000000) 210 #define FP_ILOGBNAN ((int)0x80000000) 211 extern int __cdecl ilogb (double); 212 extern int __cdecl ilogbf (float); 213 extern int __cdecl ilogbl (long double); 214 215 /* 7.12.6.6 Double in C89 */ 216 // ldexp functions. Already in math.h 217 218 /* 7.12.6.7 Double in C89 */ 219 // log functions. Already in math.h 220 221 /* 7.12.6.8 Double in C89 */ 222 // log10 functions. Already in math.h 223 224 /* 7.12.6.9 */ 225 extern double __cdecl log1p(double); 226 extern float __cdecl log1pf(float); 227 extern long double __cdecl log1pl(long double); 228 229 /* 7.12.6.10 */ 230 extern double __cdecl log2 (double); 231 extern float __cdecl log2f (float); 232 extern long double __cdecl log2l (long double); 233 234 /* 7.12.6.11 */ 235 extern double __cdecl logb (double); 236 extern float __cdecl logbf (float); 237 extern long double __cdecl logbl (long double); 238 239 /* Inline versions. GCC-4.0+ can do a better fast-math optimization 240 with __builtins. */ 241 #ifndef __CRT__NO_INLINE 242 #if !(__MINGW_GNUC_PREREQ (4, 0) && defined (__FAST_MATH__)) logb(double x)243 __CRT_INLINE double __cdecl logb (double x) 244 { 245 double res = 0.0; 246 __asm__ __volatile__ ("fxtract\n\t" 247 "fstp %%st" : "=t" (res) : "0" (x)); 248 return res; 249 } 250 logbf(float x)251 __CRT_INLINE float __cdecl logbf (float x) 252 { 253 float res = 0.0F; 254 __asm__ __volatile__ ("fxtract\n\t" 255 "fstp %%st" : "=t" (res) : "0" (x)); 256 return res; 257 } 258 logbl(long double x)259 __CRT_INLINE long double __cdecl logbl (long double x) 260 { 261 long double res = 0.0l; 262 __asm__ __volatile__ ("fxtract\n\t" 263 "fstp %%st" : "=t" (res) : "0" (x)); 264 return res; 265 } 266 #endif /* !defined __FAST_MATH__ || !__MINGW_GNUC_PREREQ (4, 0) */ 267 #endif /* __CRT__NO_INLINE */ 268 269 /* 7.12.6.12 Double in C89 */ 270 // modf functions. Already in math.h 271 272 /* 7.12.6.13 */ 273 extern double __cdecl scalbn (double, int); 274 extern float __cdecl scalbnf (float, int); 275 extern long double __cdecl scalbnl (long double, int); 276 277 extern double __cdecl scalbln (double, long); 278 extern float __cdecl scalblnf (float, long); 279 extern long double __cdecl scalblnl (long double, long); 280 281 /* 7.12.7.1 */ 282 /* Implementations adapted from Cephes versions */ 283 extern double __cdecl cbrt (double); 284 extern float __cdecl cbrtf (float); 285 extern long double __cdecl cbrtl (long double); 286 287 /* 7.12.7.2 The fabs functions: Double in C89 */ 288 // Already in math.h 289 290 /* 7.12.7.3 */ 291 // hypot functions. Already in math.h 292 293 /* 7.12.7.4 The pow functions. Double in C89 */ 294 // Already in math.h 295 296 /* 7.12.7.5 The sqrt functions. Double in C89. */ 297 // Already in math.h 298 299 /* 7.12.8.1 The erf functions */ 300 extern double __cdecl erf (double); 301 extern float __cdecl erff (float); 302 extern long double __cdecl erfl (long double); 303 304 /* 7.12.8.2 The erfc functions */ 305 extern double __cdecl erfc (double); 306 extern float __cdecl erfcf (float); 307 extern long double __cdecl erfcl (long double); 308 309 /* 7.12.8.3 The lgamma functions */ 310 extern double __cdecl lgamma (double); 311 extern float __cdecl lgammaf (float); 312 extern long double __cdecl lgammal (long double); 313 314 /* 7.12.8.4 The tgamma functions */ 315 extern double __cdecl tgamma (double); 316 extern float __cdecl tgammaf (float); 317 extern long double __cdecl tgammal (long double); 318 319 /* 7.12.9.1 Double in C89 */ 320 // ceil functions. Already in math.h 321 322 /* 7.12.9.2 Double in C89 */ 323 // floor functions. Already in math.h 324 325 /* 7.12.9.3 */ 326 extern double __cdecl nearbyint ( double); 327 extern float __cdecl nearbyintf (float); 328 extern long double __cdecl nearbyintl (long double); 329 330 /* 7.12.9.4 */ 331 /* round, using fpu control word settings */ 332 extern double __cdecl rint (double); 333 extern float __cdecl rintf (float); 334 extern long double __cdecl rintl (long double); 335 336 /* 7.12.9.5 */ 337 extern long __cdecl lrint (double); 338 extern long __cdecl lrintf (float); 339 extern long __cdecl lrintl (long double); 340 341 __MINGW_EXTENSION long long __cdecl llrint (double); 342 __MINGW_EXTENSION long long __cdecl llrintf (float); 343 __MINGW_EXTENSION long long __cdecl llrintl (long double); 344 345 /* Inline versions of above. 346 GCC 4.0+ can do a better fast-math job with __builtins. */ 347 348 #ifndef __CRT__NO_INLINE 349 #if !(__MINGW_GNUC_PREREQ (4, 0) && defined __FAST_MATH__ ) rint(double x)350 __CRT_INLINE double __cdecl rint (double x) 351 { 352 double retval = 0.0; 353 __asm__ __volatile__ ("frndint;": "=t" (retval) : "0" (x)); 354 return retval; 355 } 356 rintf(float x)357 __CRT_INLINE float __cdecl rintf (float x) 358 { 359 float retval = 0.0; 360 __asm__ __volatile__ ("frndint;" : "=t" (retval) : "0" (x) ); 361 return retval; 362 } 363 rintl(long double x)364 __CRT_INLINE long double __cdecl rintl (long double x) 365 { 366 long double retval = 0.0l; 367 __asm__ __volatile__ ("frndint;" : "=t" (retval) : "0" (x) ); 368 return retval; 369 } 370 lrint(double x)371 __CRT_INLINE long __cdecl lrint (double x) 372 { 373 long retval = 0; 374 __asm__ __volatile__ \ 375 ("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \ 376 return retval; 377 } 378 lrintf(float x)379 __CRT_INLINE long __cdecl lrintf (float x) 380 { 381 long retval = 0; 382 __asm__ __volatile__ \ 383 ("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \ 384 return retval; 385 } 386 lrintl(long double x)387 __CRT_INLINE long __cdecl lrintl (long double x) 388 { 389 long retval = 0; 390 __asm__ __volatile__ \ 391 ("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \ 392 return retval; 393 } 394 llrint(double x)395 __MINGW_EXTENSION __CRT_INLINE long long __cdecl llrint (double x) 396 { 397 __MINGW_EXTENSION long long retval = 0ll; 398 __asm__ __volatile__ \ 399 ("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \ 400 return retval; 401 } 402 llrintf(float x)403 __MINGW_EXTENSION __CRT_INLINE long long __cdecl llrintf (float x) 404 { 405 __MINGW_EXTENSION long long retval = 0ll; 406 __asm__ __volatile__ \ 407 ("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \ 408 return retval; 409 } 410 llrintl(long double x)411 __MINGW_EXTENSION __CRT_INLINE long long __cdecl llrintl (long double x) 412 { 413 __MINGW_EXTENSION long long retval = 0ll; 414 __asm__ __volatile__ \ 415 ("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \ 416 return retval; 417 } 418 #endif /* !__FAST_MATH__ || !__MINGW_GNUC_PREREQ (4,0) */ 419 #endif /* !__CRT__NO_INLINE */ 420 421 /* 7.12.9.6 */ 422 /* round away from zero, regardless of fpu control word settings */ 423 extern double __cdecl round (double); 424 extern float __cdecl roundf (float); 425 extern long double __cdecl roundl (long double); 426 427 /* 7.12.9.7 */ 428 extern long __cdecl lround (double); 429 extern long __cdecl lroundf (float); 430 extern long __cdecl lroundl (long double); 431 __MINGW_EXTENSION long long __cdecl llround (double); 432 __MINGW_EXTENSION long long __cdecl llroundf (float); 433 __MINGW_EXTENSION long long __cdecl llroundl (long double); 434 435 /* 7.12.9.8 */ 436 /* round towards zero, regardless of fpu control word settings */ 437 extern double __cdecl trunc (double); 438 extern float __cdecl truncf (float); 439 extern long double __cdecl truncl (long double); 440 441 /* 7.12.10.1 Double in C89 */ 442 // fmod functions. Already in math.h 443 444 /* 7.12.10.2 */ 445 extern double __cdecl remainder (double, double); 446 extern float __cdecl remainderf (float, float); 447 extern long double __cdecl remainderl (long double, long double); 448 449 /* 7.12.10.3 */ 450 extern double __cdecl remquo(double, double, int *); 451 extern float __cdecl remquof(float, float, int *); 452 extern long double __cdecl remquol(long double, long double, int *); 453 454 /* 7.12.11.1 */ 455 extern double __cdecl copysign (double, double); /* in libmoldname.a */ 456 extern float __cdecl copysignf (float, float); 457 extern long double __cdecl copysignl (long double, long double); 458 459 /* 7.12.11.2 Return a NaN */ 460 extern double __cdecl nan(const char *tagp); 461 extern float __cdecl nanf(const char *tagp); 462 extern long double __cdecl nanl(const char *tagp); 463 464 #ifndef __STRICT_ANSI__ 465 #define _nan() nan("") 466 #define _nanf() nanf("") 467 #define _nanl() nanl("") 468 #endif 469 470 /* 7.12.11.3 */ 471 extern double __cdecl nextafter (double, double); /* in libmoldname.a */ 472 extern float __cdecl nextafterf (float, float); 473 extern long double __cdecl nextafterl (long double, long double); 474 475 /* 7.12.11.4 The nexttoward functions */ 476 extern double __cdecl nexttoward (double, long double); 477 extern float __cdecl nexttowardf (float, long double); 478 extern long double __cdecl nexttowardl (long double, long double); 479 480 /* 7.12.12.1 */ 481 /* x > y ? (x - y) : 0.0 */ 482 extern double __cdecl fdim (double x, double y); 483 extern float __cdecl fdimf (float x, float y); 484 extern long double __cdecl fdiml (long double x, long double y); 485 486 /* fmax and fmin. 487 NaN arguments are treated as missing data: if one argument is a NaN 488 and the other numeric, then these functions choose the numeric 489 value. */ 490 491 /* 7.12.12.2 */ 492 extern double __cdecl fmax (double, double); 493 extern float __cdecl fmaxf (float, float); 494 extern long double __cdecl fmaxl (long double, long double); 495 496 /* 7.12.12.3 */ 497 extern double __cdecl fmin (double, double); 498 extern float __cdecl fminf (float, float); 499 extern long double __cdecl fminl (long double, long double); 500 501 /* 7.12.13.1 */ 502 /* return x * y + z as a ternary op */ 503 extern double __cdecl fma (double, double, double); 504 extern float __cdecl fmaf (float, float, float); 505 extern long double __cdecl fmal (long double, long double, long double); 506 507 /* 7.12.14 */ 508 /* 509 * With these functions, comparisons involving quiet NaNs set the FP 510 * condition code to "unordered". The IEEE floating-point spec 511 * dictates that the result of floating-point comparisons should be 512 * false whenever a NaN is involved, with the exception of the != op, 513 * which always returns true: yes, (NaN != NaN) is true). 514 */ 515 516 #if __GNUC__ >= 3 517 518 #define isgreater(x, y) __builtin_isgreater(x, y) 519 #define isgreaterequal(x, y) __builtin_isgreaterequal(x, y) 520 #define isless(x, y) __builtin_isless(x, y) 521 #define islessequal(x, y) __builtin_islessequal(x, y) 522 #define islessgreater(x, y) __builtin_islessgreater(x, y) 523 #define isunordered(x, y) __builtin_isunordered(x, y) 524 525 #else 526 /* helper */ 527 #ifndef __CRT__NO_INLINE 528 __CRT_INLINE int __cdecl __fp_unordered_compare(long double x,long double y)529 __fp_unordered_compare (long double x, long double y){ 530 unsigned short retval; 531 __asm__ __volatile__ ("fucom %%st(1);" 532 "fnstsw;": "=a" (retval) : "t" (x), "u" (y)); 533 return retval; 534 } 535 #endif 536 537 #define isgreater(x, y) ((__fp_unordered_compare(x, y) & 0x4500) == 0) 538 #define isless(x, y) ((__fp_unordered_compare (y, x) & 0x4500) == 0) 539 #define isgreaterequal(x, y) ((__fp_unordered_compare (x, y) & FP_INFINITE) == 0) 540 #define islessequal(x, y) ((__fp_unordered_compare(y, x) & FP_INFINITE) == 0) 541 #define islessgreater(x, y) ((__fp_unordered_compare(x, y) & FP_SUBNORMAL) == 0) 542 #define isunordered(x, y) ((__fp_unordered_compare(x, y) & 0x4500) == 0x4500) 543 544 #endif 545 546 #endif /* C99 or non strict ANSI or C++ */ 547 #endif /* __NO_ISOCEXT */ 548