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 _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);
/* from libmingwex */
float __cdecl _hypotf(float _X,float _Y);
@ -131,7 +131,7 @@ extern "C" {
float __cdecl fmodf(float _X,float _Y);
float __cdecl _hypotf(float _X,float _Y);
float __cdecl fabsf(float _X);
#if !defined(__ia64__)
#if !defined(__ia64__) && !defined(_M_IA64)
/* from libmingwex */
float __cdecl _copysignf (float _Number,float _Sign);
float __cdecl _chgsignf (float _X);
@ -142,57 +142,52 @@ extern "C" {
int __cdecl _fpclassf(float _X);
#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)
{
long double res;
__asm__ ("fabs;" : "=t" (res) : "0" (x));
__fabs(x, 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 _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)); }
#if !defined (__ia64__)
#if !defined (__ia64__) && !defined (_M_IA64)
__CRT_INLINE float __cdecl fabsf (float x)
{
float res;
__asm__ ("fabs;" : "=t" (res) : "0" (x));
__fabs(x, res);
return res;
}
__CRT_INLINE float __cdecl ldexpf (float x, int expn) { return (float) ldexp (x, expn); }
#endif
#else
// cplusplus
__CRT_INLINE long double __cdecl fabsl (long double x)
{
long double res;
__asm__ ("fabs;" : "=t" (res) : "0" (x));
return res;
}
#define _matherrl _matherr
__CRT_INLINE long double modfl(long double _X,long double *_Y) {
double _Di,_Df = modf((double)_X,&_Di);
*_Y = (long double)_Di;
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 asinf(float _X) { return ((float)asin((double)_X)); }
__CRT_INLINE float atanf(float _X) { return ((float)atan((double)_X)); }
@ -255,11 +250,26 @@ extern "C" {
#define FP_SUBNORMAL (FP_NORMAL | FP_ZERO)
/* 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
to semantic type before classification.
(A normal long double value might become subnormal when
to semantic type before classification.
(A normal long double value might become subnormal when
converted to double, and zero when converted to float.)
*/
@ -268,7 +278,7 @@ extern "C" {
__CRT_INLINE int __cdecl __fpclassifyl (long double x){
unsigned short sw;
__asm__ ("fxam; fstsw %%ax;" : "=a" (sw): "t" (x));
__fxam(x, sw);
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)
{
unsigned short sw;
__asm__ ("fxam;"
"fstsw %%ax": "=a" (sw) : "t" (_x));
__fxam(_x, sw);
return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL))
== FP_NAN;
}
@ -319,8 +328,7 @@ __CRT_INLINE int isinf (double d) {
__CRT_INLINE int __cdecl __isnanf (float _x)
{
unsigned short sw;
__asm__ ("fxam;"
"fstsw %%ax": "=a" (sw) : "t" (_x));
__fxam(_x, sw);
return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL))
== FP_NAN;
}
@ -328,8 +336,7 @@ __CRT_INLINE int isinf (double d) {
__CRT_INLINE int __cdecl __isnanl (long double _x)
{
unsigned short sw;
__asm__ ("fxam;"
"fstsw %%ax": "=a" (sw) : "t" (_x));
__fxam(_x, sw);
return (sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL))
== FP_NAN;
}
@ -345,19 +352,19 @@ __CRT_INLINE int isinf (double d) {
/* 7.12.3.6 The signbit macro */
__CRT_INLINE int __cdecl __signbit (double x) {
unsigned short stw;
__asm__ ( "fxam; fstsw %%ax;": "=a" (stw) : "t" (x));
__fxam(x, stw);
return stw & 0x0200;
}
__CRT_INLINE int __cdecl __signbitf (float x) {
unsigned short stw;
__asm__ ("fxam; fstsw %%ax;": "=a" (stw) : "t" (x));
__fxam(x, stw);
return stw & 0x0200;
}
__CRT_INLINE int __cdecl __signbitl (long double x) {
unsigned short stw;
__asm__ ("fxam; fstsw %%ax;": "=a" (stw) : "t" (x));
__fxam(x, stw);
return stw & 0x0200;
}
@ -387,27 +394,40 @@ __CRT_INLINE int isinf (double d) {
extern float __cdecl logbf (float);
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)
{
double res;
__asm__ ("fxtract\n\t"
"fstp %%st" : "=t" (res) : "0" (x));
__fxtract(x, res);
return res;
}
__CRT_INLINE float __cdecl logbf (float x)
{
float res;
__asm__ ("fxtract\n\t"
"fstp %%st" : "=t" (res) : "0" (x));
__fxtract(x, res);
return res;
}
__CRT_INLINE long double __cdecl logbl (long double x)
{
long double res;
__asm__ ("fxtract\n\t"
"fstp %%st" : "=t" (res) : "0" (x));
__fxtract(x, res);
return res;
}
@ -423,7 +443,7 @@ __CRT_INLINE int isinf (double d) {
extern long double __cdecl scalblnl (long double, long);
/* 7.12.7.1 */
/* Implementations adapted from Cephes versions */
/* Implementations adapted from Cephes versions */
extern double __cdecl cbrt (double);
extern float __cdecl cbrtf (float);
extern long double __cdecl cbrtl (long double);
@ -449,14 +469,14 @@ __CRT_INLINE int isinf (double d) {
extern float __cdecl erff (float);
/* TODO
extern long double __cdecl erfl (long double);
*/
*/
/* 7.12.8.2 The erfc functions */
extern double __cdecl erfc (double);
extern float __cdecl erfcf (float);
/* TODO
extern long double __cdecl erfcl (long double);
*/
*/
/* 7.12.8.3 The lgamma functions */
extern double __cdecl lgamma (double);
@ -485,74 +505,102 @@ __CRT_INLINE int isinf (double d) {
/* 7.12.9.4 */
/* 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)
{
double retval;
__asm__ ("frndint;": "=t" (retval) : "0" (x));
__frndint(x, retval);
return retval;
}
__CRT_INLINE float __cdecl rintf (float x)
{
float retval;
__asm__ ("frndint;" : "=t" (retval) : "0" (x) );
__frndint(x, retval);
return retval;
}
__CRT_INLINE long double __cdecl rintl (long double x)
{
long double retval;
__asm__ ("frndint;" : "=t" (retval) : "0" (x) );
__frndint(x, retval);
return retval;
}
/* 7.12.9.5 */
__CRT_INLINE long __cdecl lrint (double x)
{
long retval;
__asm__ __volatile__ \
("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \
return retval;
}
#if defined(__GNUC__)
__CRT_INLINE long __cdecl lrintf (float x)
#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)
{
long retval;
__asm__ __volatile__ \
("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \
return retval;
__fistpl(x, retval);
return retval;
}
__CRT_INLINE long __cdecl lrintl (long double x)
__CRT_INLINE long __cdecl lrintf (float x)
{
long retval;
__asm__ __volatile__ \
("fistpl %0" : "=m" (retval) : "t" (x) : "st"); \
return retval;
__fistpl(x, retval);
return retval;
}
__CRT_INLINE long long __cdecl llrint (double x)
__CRT_INLINE long __cdecl lrintl (long double x)
{
long long retval;
__asm__ __volatile__ \
("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \
return retval;
long retval;
__fistpl(x, retval);
return retval;
}
__CRT_INLINE long long __cdecl llrintf (float x)
__CRT_INLINE long long __cdecl llrint (double x)
{
long long retval;
__asm__ __volatile__ \
("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \
return retval;
__fistpll(x, retval);
return retval;
}
__CRT_INLINE long long __cdecl llrintl (long double x)
__CRT_INLINE long long __cdecl llrintf (float x)
{
long long retval;
__asm__ __volatile__ \
("fistpll %0" : "=m" (retval) : "t" (x) : "st"); \
return retval;
__fistpll(x, retval);
return retval;
}
__CRT_INLINE long long __cdecl llrintl (long double x)
{
long long retval;
__fistpll(x, retval);
return retval;
}
/* 7.12.9.6 */
@ -578,7 +626,7 @@ __CRT_INLINE int isinf (double d) {
extern long double __cdecl fmodl (long double, long double);
/* 7.12.10.2 */
/* 7.12.10.2 */
extern double __cdecl remainder (double, double);
extern float __cdecl remainderf (float, float);
extern long double __cdecl remainderl (long double, long double);
@ -633,22 +681,22 @@ __CRT_INLINE int isinf (double d) {
extern long double __cdecl fminl (long double, long double);
/* 7.12.13.1 */
/* return x * y + z as a ternary op */
/* return x * y + z as a ternary op */
extern double __cdecl fma (double, double, double);
extern float __cdecl fmaf (float, float, float);
extern long double __cdecl fmal (long double, long double, long double);
/* 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,
* false whenever a NaN is involved, with the exception of the != op,
* 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 isgreaterequal(x, y) __builtin_isgreaterequal(x, y)
@ -662,8 +710,20 @@ __CRT_INLINE int isinf (double d) {
__CRT_INLINE int __cdecl
__fp_unordered_compare (long double x, long double y){
unsigned short retval;
#if defined(__GNUC__)
__asm__ ("fucom %%st(1);"
"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;
}
@ -695,7 +755,7 @@ extern "C++" {
else _N = (unsigned int)(-_Y);
for(_Ty _Z = _Ty(1);;_X *= _X) {
if((_N & 1)!=0) _Z *= _X;
if((_N >>= 1)==0) return (_Y < 0 ? _Ty(1) / _Z : _Z);
if((_N >>= 1)==0) return (_Y < 0 ? _Ty(1) / _Z : _Z);
}
}
}
@ -735,47 +795,4 @@ extern "C++" {
#define _FPCLASS_PINF 0x0200 /* Positive Infinity */
#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 */