modified include/crt/math.h

Ported <math.h> to Visual C++
   Fixed some miscellaneous stupidity. I see Arch has been committing to MinGW-W64 too

svn path=/trunk/; revision=41440
This commit is contained in:
KJK::Hyperion 2009-06-17 23:25:22 +00:00
parent abdf1ae486
commit 5632264d33

View file

@ -100,7 +100,7 @@ extern "C" {
_CRTIMP double __cdecl _y1(double _X); _CRTIMP double __cdecl _y1(double _X);
_CRTIMP double __cdecl _yn(int _X,double _Y); _CRTIMP double __cdecl _yn(int _X,double _Y);
#if(defined(_X86_) && !defined(__x86_64)) #if defined(__i386__) || defined(_M_IX86)
_CRTIMP int __cdecl _set_SSE2_enable(int _Flag); _CRTIMP int __cdecl _set_SSE2_enable(int _Flag);
/* from libmingwex */ /* from libmingwex */
float __cdecl _hypotf(float _X,float _Y); float __cdecl _hypotf(float _X,float _Y);
@ -131,7 +131,7 @@ extern "C" {
float __cdecl fmodf(float _X,float _Y); float __cdecl fmodf(float _X,float _Y);
float __cdecl _hypotf(float _X,float _Y); float __cdecl _hypotf(float _X,float _Y);
float __cdecl fabsf(float _X); float __cdecl fabsf(float _X);
#if !defined(__ia64__) #if !defined(__ia64__) && !defined(_M_IA64)
/* from libmingwex */ /* from libmingwex */
float __cdecl _copysignf (float _Number,float _Sign); float __cdecl _copysignf (float _Number,float _Sign);
float __cdecl _chgsignf (float _X); float __cdecl _chgsignf (float _X);
@ -142,57 +142,52 @@ extern "C" {
int __cdecl _fpclassf(float _X); int __cdecl _fpclassf(float _X);
#endif #endif
#ifndef __cplusplus #if defined(__GNUC__)
#define __fabs(x, res) \
__asm__ ("fabs;" : "=t" (res) : "0" (x))
#elif defined(_MSC_VER)
#define __fabs(x, res) \
__asm { fld [(x)] } \
__asm { fabs } \
__asm { fstp [(res)] }
#endif
__CRT_INLINE long double __cdecl fabsl (long double x) __CRT_INLINE long double __cdecl fabsl (long double x)
{ {
long double res; long double res;
__asm__ ("fabs;" : "=t" (res) : "0" (x)); __fabs(x, res);
return res; return res;
} }
#define _hypotl(x,y) ((long double)_hypot((double)(x),(double)(y)))
#define _matherrl _matherr
__CRT_INLINE long double _chgsignl(long double _Number) { return _chgsign((double)(_Number)); } __CRT_INLINE long double _chgsignl(long double _Number) { return _chgsign((double)(_Number)); }
__CRT_INLINE long double _copysignl(long double _Number,long double _Sign) { return _copysign((double)(_Number),(double)(_Sign)); } __CRT_INLINE long double _copysignl(long double _Number,long double _Sign) { return _copysign((double)(_Number),(double)(_Sign)); }
__CRT_INLINE long double _hypotl(long double _X,long double _Y) { return _hypot((double)(_X),(double)(_Y)); }
__CRT_INLINE float frexpf(float _X,int *_Y) { return ((float)frexp((double)_X,_Y)); } __CRT_INLINE float frexpf(float _X,int *_Y) { return ((float)frexp((double)_X,_Y)); }
#if !defined (__ia64__) #if !defined (__ia64__) && !defined (_M_IA64)
__CRT_INLINE float __cdecl fabsf (float x) __CRT_INLINE float __cdecl fabsf (float x)
{ {
float res; float res;
__asm__ ("fabs;" : "=t" (res) : "0" (x)); __fabs(x, res);
return res; return res;
} }
__CRT_INLINE float __cdecl ldexpf (float x, int expn) { return (float) ldexp (x, expn); } __CRT_INLINE float __cdecl ldexpf (float x, int expn) { return (float) ldexp (x, expn); }
#endif #endif
#else
// cplusplus #define _matherrl _matherr
__CRT_INLINE long double __cdecl fabsl (long double x)
{
long double res;
__asm__ ("fabs;" : "=t" (res) : "0" (x));
return res;
}
__CRT_INLINE long double modfl(long double _X,long double *_Y) { __CRT_INLINE long double modfl(long double _X,long double *_Y) {
double _Di,_Df = modf((double)_X,&_Di); double _Di,_Df = modf((double)_X,&_Di);
*_Y = (long double)_Di; *_Y = (long double)_Di;
return (_Df); return (_Df);
} }
__CRT_INLINE long double _chgsignl(long double _Number) { return _chgsign(static_cast<double>(_Number)); }
__CRT_INLINE long double _copysignl(long double _Number,long double _Sign) { return _copysign(static_cast<double>(_Number),static_cast<double>(_Sign)); }
__CRT_INLINE float frexpf(float _X,int *_Y) { return ((float)frexp((double)_X,_Y)); }
#ifndef __ia64__
__CRT_INLINE float __cdecl fabsf (float x)
{
float res;
__asm__ ("fabs;" : "=t" (res) : "0" (x));
return res;
}
__CRT_INLINE float __cdecl ldexpf (float x, int expn) { return (float) ldexp (x, expn); }
#endif
#endif
#ifndef __x86_64 #if !defined(__x86_64) && !defined(_M_AMD64)
__CRT_INLINE float acosf(float _X) { return ((float)acos((double)_X)); } __CRT_INLINE float acosf(float _X) { return ((float)acos((double)_X)); }
__CRT_INLINE float asinf(float _X) { return ((float)asin((double)_X)); } __CRT_INLINE float asinf(float _X) { return ((float)asin((double)_X)); }
__CRT_INLINE float atanf(float _X) { return ((float)atan((double)_X)); } __CRT_INLINE float atanf(float _X) { return ((float)atan((double)_X)); }
@ -255,6 +250,21 @@ extern "C" {
#define FP_SUBNORMAL (FP_NORMAL | FP_ZERO) #define FP_SUBNORMAL (FP_NORMAL | FP_ZERO)
/* 0x0200 is signbit mask */ /* 0x0200 is signbit mask */
#if defined(__GNUC__)
#define __fxam(x, sw) \
__asm__ ("fxam; fstsw %%ax;" : "=a" (sw): "t" (x))
#elif defined(_MSC_VER)
#define __fxam(x, sw) \
__asm { fld [(x)] } \
__asm { fxam } \
__asm { wait } \
__asm { fnstsw [(sw)] } \
__asm { fstp st(0) }
#endif
/* /*
We can't __CRT_INLINE float or double, because we want to ensure truncation We can't __CRT_INLINE float or double, because we want to ensure truncation
@ -268,7 +278,7 @@ extern "C" {
__CRT_INLINE int __cdecl __fpclassifyl (long double x){ __CRT_INLINE int __cdecl __fpclassifyl (long double x){
unsigned short sw; unsigned short sw;
__asm__ ("fxam; fstsw %%ax;" : "=a" (sw): "t" (x)); __fxam(x, sw);
return sw & (FP_NAN | FP_NORMAL | FP_ZERO ); return sw & (FP_NAN | FP_NORMAL | FP_ZERO );
} }
@ -310,8 +320,7 @@ __CRT_INLINE int isinf (double d) {
__CRT_INLINE int __cdecl __isnan (double _x) __CRT_INLINE int __cdecl __isnan (double _x)
{ {
unsigned short sw; unsigned short sw;
__asm__ ("fxam;" __fxam(_x, sw);
"fstsw %%ax": "=a" (sw) : "t" (_x));
return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL)) return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL))
== FP_NAN; == FP_NAN;
} }
@ -319,8 +328,7 @@ __CRT_INLINE int isinf (double d) {
__CRT_INLINE int __cdecl __isnanf (float _x) __CRT_INLINE int __cdecl __isnanf (float _x)
{ {
unsigned short sw; unsigned short sw;
__asm__ ("fxam;" __fxam(_x, sw);
"fstsw %%ax": "=a" (sw) : "t" (_x));
return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL)) return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL))
== FP_NAN; == FP_NAN;
} }
@ -328,8 +336,7 @@ __CRT_INLINE int isinf (double d) {
__CRT_INLINE int __cdecl __isnanl (long double _x) __CRT_INLINE int __cdecl __isnanl (long double _x)
{ {
unsigned short sw; unsigned short sw;
__asm__ ("fxam;" __fxam(_x, sw);
"fstsw %%ax": "=a" (sw) : "t" (_x));
return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL)) return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL))
== FP_NAN; == FP_NAN;
} }
@ -345,19 +352,19 @@ __CRT_INLINE int isinf (double d) {
/* 7.12.3.6 The signbit macro */ /* 7.12.3.6 The signbit macro */
__CRT_INLINE int __cdecl __signbit (double x) { __CRT_INLINE int __cdecl __signbit (double x) {
unsigned short stw; unsigned short stw;
__asm__ ( "fxam; fstsw %%ax;": "=a" (stw) : "t" (x)); __fxam(x, stw);
return stw & 0x0200; return stw & 0x0200;
} }
__CRT_INLINE int __cdecl __signbitf (float x) { __CRT_INLINE int __cdecl __signbitf (float x) {
unsigned short stw; unsigned short stw;
__asm__ ("fxam; fstsw %%ax;": "=a" (stw) : "t" (x)); __fxam(x, stw);
return stw & 0x0200; return stw & 0x0200;
} }
__CRT_INLINE int __cdecl __signbitl (long double x) { __CRT_INLINE int __cdecl __signbitl (long double x) {
unsigned short stw; unsigned short stw;
__asm__ ("fxam; fstsw %%ax;": "=a" (stw) : "t" (x)); __fxam(x, stw);
return stw & 0x0200; return stw & 0x0200;
} }
@ -387,27 +394,40 @@ __CRT_INLINE int isinf (double d) {
extern float __cdecl logbf (float); extern float __cdecl logbf (float);
extern long double __cdecl logbl (long double); extern long double __cdecl logbl (long double);
#if defined(__GNUC__)
#define __fxtract(x, res) \
__asm__ ("fxtract\n\t" \
"fstp %%st" : "=t" (res) : "0" (x))
#elif defined(_MSC_VER)
#define __fxtract(x, res) \
__asm { fld [(x)] } \
__asm { fxtract } \
__asm { fstp st(0) } \
__asm { fstp [(res)] }
#endif
__CRT_INLINE double __cdecl logb (double x) __CRT_INLINE double __cdecl logb (double x)
{ {
double res; double res;
__asm__ ("fxtract\n\t" __fxtract(x, res);
"fstp %%st" : "=t" (res) : "0" (x));
return res; return res;
} }
__CRT_INLINE float __cdecl logbf (float x) __CRT_INLINE float __cdecl logbf (float x)
{ {
float res; float res;
__asm__ ("fxtract\n\t" __fxtract(x, res);
"fstp %%st" : "=t" (res) : "0" (x));
return res; return res;
} }
__CRT_INLINE long double __cdecl logbl (long double x) __CRT_INLINE long double __cdecl logbl (long double x)
{ {
long double res; long double res;
__asm__ ("fxtract\n\t" __fxtract(x, res);
"fstp %%st" : "=t" (res) : "0" (x));
return res; return res;
} }
@ -485,73 +505,101 @@ __CRT_INLINE int isinf (double d) {
/* 7.12.9.4 */ /* 7.12.9.4 */
/* round, using fpu control word settings */ /* round, using fpu control word settings */
#if defined(__GNUC__)
#define __frndint(x, res) \
__asm__ ("fabs;" : "=t" (res) : "0" (x))
#elif defined(_MSC_VER)
#define __frndint(x, res) \
__asm { fld [(x)] } \
__asm { frndint } \
__asm { fstp [(res)] }
#endif
__CRT_INLINE double __cdecl rint (double x) __CRT_INLINE double __cdecl rint (double x)
{ {
double retval; double retval;
__asm__ ("frndint;": "=t" (retval) : "0" (x)); __frndint(x, retval);
return retval; return retval;
} }
__CRT_INLINE float __cdecl rintf (float x) __CRT_INLINE float __cdecl rintf (float x)
{ {
float retval; float retval;
__asm__ ("frndint;" : "=t" (retval) : "0" (x) ); __frndint(x, retval);
return retval; return retval;
} }
__CRT_INLINE long double __cdecl rintl (long double x) __CRT_INLINE long double __cdecl rintl (long double x)
{ {
long double retval; long double retval;
__asm__ ("frndint;" : "=t" (retval) : "0" (x) ); __frndint(x, retval);
return retval; return retval;
} }
/* 7.12.9.5 */ /* 7.12.9.5 */
#if defined(__GNUC__)
#define __fistpl(x, res) \
__asm__ __volatile__("fistpl %0" : "=m" (res) : "t" (x) : "st")
#define __fistpll(x, res) \
__asm__ __volatile__("fistpll %0" : "=m" (res) : "t" (x) : "st")
#elif defined(_MSC_VER)
#define __fistpl(x, res) \
__asm { fld [(x)] } \
__asm { fistp [(res)] }
#define __fistpll(x, res) \
__asm { fld [(x)] } \
__asm { fistp [(res)] }
#endif
__CRT_INLINE long __cdecl lrint (double x) __CRT_INLINE long __cdecl lrint (double x)
{ {
long retval; long retval;
__asm__ __volatile__ \ __fistpl(x, retval);
("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \
return retval; return retval;
} }
__CRT_INLINE long __cdecl lrintf (float x) __CRT_INLINE long __cdecl lrintf (float x)
{ {
long retval; long retval;
__asm__ __volatile__ \ __fistpl(x, retval);
("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \
return retval; return retval;
} }
__CRT_INLINE long __cdecl lrintl (long double x) __CRT_INLINE long __cdecl lrintl (long double x)
{ {
long retval; long retval;
__asm__ __volatile__ \ __fistpl(x, retval);
("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \
return retval; return retval;
} }
__CRT_INLINE long long __cdecl llrint (double x) __CRT_INLINE long long __cdecl llrint (double x)
{ {
long long retval; long long retval;
__asm__ __volatile__ \ __fistpll(x, retval);
("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \
return retval; return retval;
} }
__CRT_INLINE long long __cdecl llrintf (float x) __CRT_INLINE long long __cdecl llrintf (float x)
{ {
long long retval; long long retval;
__asm__ __volatile__ \ __fistpll(x, retval);
("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \
return retval; return retval;
} }
__CRT_INLINE long long __cdecl llrintl (long double x) __CRT_INLINE long long __cdecl llrintl (long double x)
{ {
long long retval; long long retval;
__asm__ __volatile__ \ __fistpll(x, retval);
("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \
return retval; return retval;
} }
@ -648,7 +696,7 @@ __CRT_INLINE int isinf (double d) {
* which always returns true: yes, (NaN != NaN) is true). * which always returns true: yes, (NaN != NaN) is true).
*/ */
#if __GNUC__ >= 3 #if defined(__GNUC__) && __GNUC__ >= 3
#define isgreater(x, y) __builtin_isgreater(x, y) #define isgreater(x, y) __builtin_isgreater(x, y)
#define isgreaterequal(x, y) __builtin_isgreaterequal(x, y) #define isgreaterequal(x, y) __builtin_isgreaterequal(x, y)
@ -662,8 +710,20 @@ __CRT_INLINE int isinf (double d) {
__CRT_INLINE int __cdecl __CRT_INLINE int __cdecl
__fp_unordered_compare (long double x, long double y){ __fp_unordered_compare (long double x, long double y){
unsigned short retval; unsigned short retval;
#if defined(__GNUC__)
__asm__ ("fucom %%st(1);" __asm__ ("fucom %%st(1);"
"fnstsw;": "=a" (retval) : "t" (x), "u" (y)); "fnstsw;": "=a" (retval) : "t" (x), "u" (y));
#elif defined(_MSC_VER)
__asm {
fld [x]
fld [y]
fxch st(1)
fucom st(1)
fnstsw [retval]
fstp st(0)
fstp st(0)
}
#endif
return retval; return retval;
} }
@ -735,47 +795,4 @@ extern "C++" {
#define _FPCLASS_PINF 0x0200 /* Positive Infinity */ #define _FPCLASS_PINF 0x0200 /* Positive Infinity */
#endif /* __MINGW_FPCLASS_DEFINED */ #endif /* __MINGW_FPCLASS_DEFINED */
/* 7.12.14 */
/*
* With these functions, comparisons involving quiet NaNs set the FP
* condition code to "unordered". The IEEE floating-point spec
* dictates that the result of floating-point comparisons should be
* false whenever a NaN is involved, with the exception of the != op,
* which always returns true: yes, (NaN != NaN) is true).
*/
#if __GNUC__ >= 3
#define isgreater(x, y) __builtin_isgreater(x, y)
#define isgreaterequal(x, y) __builtin_isgreaterequal(x, y)
#define isless(x, y) __builtin_isless(x, y)
#define islessequal(x, y) __builtin_islessequal(x, y)
#define islessgreater(x, y) __builtin_islessgreater(x, y)
#define isunordered(x, y) __builtin_isunordered(x, y)
#else
/* helper */
__CRT_INLINE int __cdecl
__fp_unordered_compare (long double x, long double y){
unsigned short retval;
__asm__ ("fucom %%st(1);"
"fnstsw;": "=a" (retval) : "t" (x), "u" (y));
return retval;
}
#define isgreater(x, y) ((__fp_unordered_compare(x, y) \
& 0x4500) == 0)
#define isless(x, y) ((__fp_unordered_compare (y, x) \
& 0x4500) == 0)
#define isgreaterequal(x, y) ((__fp_unordered_compare (x, y) \
& FP_INFINITE) == 0)
#define islessequal(x, y) ((__fp_unordered_compare(y, x) \
& FP_INFINITE) == 0)
#define islessgreater(x, y) ((__fp_unordered_compare(x, y) \
& FP_SUBNORMAL) == 0)
#define isunordered(x, y) ((__fp_unordered_compare(x, y) \
& 0x4500) == 0x4500)
#endif
#endif /* !_INC_MATH */ #endif /* !_INC_MATH */