|  | /** | 
|  | * This file has no copyright assigned and is placed in the Public Domain. | 
|  | * This file is part of the mingw-w64 runtime package. | 
|  | * No warranty is given; refer to the file DISCLAIMER.PD within this package. | 
|  | */ | 
|  | #ifndef _MINGWEX_FASTMATH_H_ | 
|  | #define _MINGWEX_FASTMATH_H_ | 
|  |  | 
|  | /* Fast math inlines | 
|  | No range or domain checks. No setting of errno.  No tweaks to | 
|  | protect precision near range limits. */ | 
|  |  | 
|  | /* For now this is an internal header with just the functions that | 
|  | are currently used in building libmingwex.a math components */ | 
|  |  | 
|  | /* FIXME: We really should get rid of the code duplication using euther | 
|  | C++ templates or tgmath-type macros.  */ | 
|  |  | 
|  | static __inline__ double __fast_sqrt (double x) | 
|  | { | 
|  | double res; | 
|  | asm __volatile__ ("fsqrt" : "=t" (res) : "0" (x)); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | static __inline__ long double __fast_sqrtl (long double x) | 
|  | { | 
|  | long double res; | 
|  | asm __volatile__ ("fsqrt" : "=t" (res) : "0" (x)); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | static __inline__ float __fast_sqrtf (float x) | 
|  | { | 
|  | float res; | 
|  | asm __volatile__ ("fsqrt" : "=t" (res) : "0" (x)); | 
|  | return res; | 
|  | } | 
|  |  | 
|  |  | 
|  | static __inline__ double __fast_log (double x) | 
|  | { | 
|  | double res; | 
|  | asm __volatile__ | 
|  | ("fldln2\n\t" | 
|  | "fxch\n\t" | 
|  | "fyl2x" | 
|  | : "=t" (res) : "0" (x) : "st(1)"); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | static __inline__ long double __fast_logl (long double x) | 
|  | { | 
|  | long double res; | 
|  | asm __volatile__ | 
|  | ("fldln2\n\t" | 
|  | "fxch\n\t" | 
|  | "fyl2x" | 
|  | : "=t" (res) : "0" (x) : "st(1)"); | 
|  | return res; | 
|  | } | 
|  |  | 
|  |  | 
|  | static __inline__ float __fast_logf (float x) | 
|  | { | 
|  | float res; | 
|  | asm __volatile__ | 
|  | ("fldln2\n\t" | 
|  | "fxch\n\t" | 
|  | "fyl2x" | 
|  | : "=t" (res) : "0" (x) : "st(1)"); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | static __inline__ double __fast_log1p (double x) | 
|  | { | 
|  | double res; | 
|  | /* fyl2xp1 accurate only for |x| <= 1.0 - 0.5 * sqrt (2.0) */ | 
|  | if (fabs (x) >= 1.0 - 0.5 * 1.41421356237309504880) | 
|  | res = __fast_log (1.0 + x); | 
|  | else | 
|  | asm __volatile__ | 
|  | ("fldln2\n\t" | 
|  | "fxch\n\t" | 
|  | "fyl2xp1" | 
|  | : "=t" (res) : "0" (x) : "st(1)"); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | static __inline__ long double __fast_log1pl (long double x) | 
|  | { | 
|  | long double res; | 
|  | /* fyl2xp1 accurate only for |x| <= 1.0 - 0.5 * sqrt (2.0) */ | 
|  | if (fabsl (x) >= 1.0L - 0.5L * 1.41421356237309504880L) | 
|  | res = __fast_logl (1.0L + x); | 
|  | else | 
|  | asm __volatile__ | 
|  | ("fldln2\n\t" | 
|  | "fxch\n\t" | 
|  | "fyl2xp1" | 
|  | : "=t" (res) : "0" (x) : "st(1)"); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | static __inline__ float __fast_log1pf (float x) | 
|  | { | 
|  | float res; | 
|  | /* fyl2xp1 accurate only for |x| <= 1.0 - 0.5 * sqrt (2.0) */ | 
|  | if (fabsf (x) >= 1.0 - 0.5 * 1.41421356237309504880) | 
|  | res = __fast_logf (1.0 + x); | 
|  | else | 
|  | asm __volatile__ | 
|  | ("fldln2\n\t" | 
|  | "fxch\n\t" | 
|  | "fyl2xp1" | 
|  | : "=t" (res) : "0" (x) : "st(1)"); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | #endif |