|
|
// Copyright (c) 1996-1999 Microsoft Corporation
#ifdef DMSYNTH_MINIPORT
#include "common.h"
#else
#include "simple.h"
#include "float.h"
#endif
#ifdef _ALPHA_
#include <math.h>
#endif // _ALPHA_
#ifndef _ALPHA_
#ifndef DBG
extern "C" int _fltused = 1; #endif
// asm_fsave(rgbState)
//
// Store the floating point state into <rgbState> and reinitialize the FPU.
//
void __cdecl asm_fsave(char *rgbState) { _asm { mov eax, dword ptr rgbState fsave [eax] } }
// asm_frestore(rgbState)
//
// Restore a previously saved floating point state <rgbState>.
//
void __cdecl asm_frestore(const char *rgbState) { _asm { fwait mov eax, dword ptr rgbState frstor [eax] } }
// FLOATSAFE
//
// Saves floating point state on construction and restores on destruction.
//
struct FLOATSAFE { char m_rgbState[105]; FLOATSAFE::FLOATSAFE(void) { asm_fsave(m_rgbState); } FLOATSAFE::~FLOATSAFE(void) { asm_frestore(m_rgbState); } };
// asm_fdiv()
//
float __cdecl asm_fdiv(float flNum, float flDenom) { float flResult = (float) 0.0;
if (flDenom != (float) 0.0) { _asm { fld flNum fdiv flDenom fstp flResult fnclex ; clear the status word of exceptions } }
return(flResult); }
// asm__fsin()
//
float __cdecl asm_fsin(float flRad) { float flSine;
_asm { fld flRad fsin fstp flSine fnclex ; clear the status word of exceptions }
return(flSine); }
// asm__fcos()
//
float __cdecl asm_fcos(float flRad) { float flCosine;
_asm { fld flRad fcos fstp flCosine fnclex ; clear the status word of exceptions }
return(flCosine); }
// asm_flog2()
//
float __cdecl asm_flog2(float flX) { float flLog;
_asm { fld1 fld flX fyl2X fstp flLog; fnclex ; clear the status word of exceptions } return flLog; }
// asm_ftol()
//
long __cdecl asm_ftol(float flX) { long lResult; WORD wCW; WORD wNewCW;
_asm { fld flX // Push the float onto the stack
wait fnstcw wCW // Store the control word
wait mov ax,wCW // Setup our rounding
or ah,0x0c mov wNewCW,ax fldcw wNewCW // Set Control word to our new value
fistp lResult // Round off top of stack into result
fldcw wCW // Restore control word
fnclex // clear the status word of exceptions
}
return(lResult); }
// asm_fpow()
//
float __cdecl asm_fpow(float flX, float flY) { float flHalf = (float) 0.5; float flOne = (float) 1.0; float flResult = (float) 0.0;
if (flX == (float) 0.0 && flY > (float) 0.0) { flResult = (float) 0.0; } else if (flX == (float) 0.0 && flY <= (float) 0.0) { flResult = (float) 1.0; } else if (flY == (float) 0.0) { flResult = (float) 1.0; } else { BOOL fNeg = FALSE; // Ok, if X is negative the sign is positive if the Y is even
// and negative if Y is odd. Fractions can't be done.
if (flX < (float) 0.0) { long lY = asm_ftol(flY);
if ((float) lY == flY) // Only fix it if we have a integer poer
{ flX = -flX;
if (lY % 2) { fNeg = TRUE; } } }
flX = flY * asm_flog2(flX);
if (max(-flX,flX) < flOne) // Is the power is in the range which F2XM1 can handle?
{ _asm { fld flX // Put flX in ST[0]
f2xm1 // ST := 2^ST - 1
fadd flOne // ST := 2^mantissa
fstp flResult // Store result
fnclex // clear the status word of exceptions
} } else // Nope, we've got to scale first
{ _asm { fld flX // Put flX in ST[0]
fld ST // Duplicate ST
frndint // Integral value in ST
fsub ST(1),ST // Fractional value in ST(1)
fxch // Factional value in ST
f2xm1 // ST := 2^ST - 1
fadd flOne // ST := 2^frac
fscale // ST := 2^frac * 2^integral
fstp flResult // Store result
fnclex // clear the status word of exceptions
} }
if (fNeg) { flResult = -flResult; } }
return flResult; }
#endif // _ALPHA_
// fp_ftol()
//
STDAPI_(long) fp_ftol(float flX) { #ifdef _ALPHA_
return (long)flX; #else
FLOATSAFE fs; return(asm_ftol(flX)); #endif
}
// fp_ltof()
//
STDAPI_(float) fp_ltof(long lx) { #ifndef _ALPHA_
FLOATSAFE fs; #endif
return(float(lx)); }
// fp_fadd()
//
STDAPI_(float) fp_fadd(float flX, float flY) { #ifndef _ALPHA_
FLOATSAFE fs; #endif
return(flX + flY); }
// fp_fsub()
//
STDAPI_(float) fp_fsub(float flX, float flY) { #ifndef _ALPHA_
FLOATSAFE fs; #endif
return(flX - flY); }
// fp_fmul()
//
STDAPI_(float) fp_fmul(float flX, float flY) { #ifndef _ALPHA_
FLOATSAFE fs; #endif
return(flX * flY); }
// fp_fdiv()
//
STDAPI_(float) fp_fdiv(float flNum, float flDenom) { #ifdef _ALPHA_
return flNum/flDenom; #else
FLOATSAFE fs; return(asm_fdiv(flNum,flDenom)); #endif
}
// fp_fabs()
//
STDAPI_(float) fp_fabs(float flX) { #ifndef _ALPHA_
FLOATSAFE fs; #endif
return max(-flX,flX); }
// fp_fsin()
//
STDAPI_(float) fp_fsin(float flRad) { #ifdef _ALPHA_
return sin(flRad); #else
FLOATSAFE fs; return(asm_fsin(flRad)); #endif
}
// fp_fcos()
//
STDAPI_(float) fp_fcos(float flRad) { #ifdef _ALPHA_
return cos(flRad); #else
FLOATSAFE fs; return(asm_fcos(flRad)); #endif
}
// fp_fpow()
//
STDAPI_(float) fp_fpow(float flX, float flY) { #ifdef _ALPHA_
return pow(flX, flY); #else
FLOATSAFE fs; return(asm_fpow(flX,flY)); #endif
}
// fp_flog2()
//
STDAPI_(float) fp_flog2(float flX) { #ifdef _ALPHA_
return log(flX); #else
FLOATSAFE fs; return(asm_flog2(flX)); #endif
}
// fp_flog10()
//
STDAPI_(float) fp_flog10(float flX) { #ifdef _ALPHA_
return log10(flX); #else
FLOATSAFE fs; #define LOG2OF10 float(3.321928094887)
return(asm_fdiv(asm_flog2(flX),LOG2OF10)); #endif
}
// fp_fchs()
//
STDAPI_(float) fp_fchs(float flX) { #ifndef _ALPHA_
FLOATSAFE fs; #endif
return(-flX); }
// fp_fcmp()
//
STDAPI_(int) fp_fcmp(float flA, float flB) { #ifndef _ALPHA_
FLOATSAFE fs; #endif
if (flA > flB) return(1); if (flA < flB) return(-1);
return(0); }
// fp_fmin()
//
STDAPI_(float) fp_fmin(float flA, float flB) { #ifndef _ALPHA_
FLOATSAFE fs; #endif
return(min(flA,flB)); }
// fp_fmax()
//
STDAPI_(float) fp_fmax(float flA, float flB) { #ifndef _ALPHA_
FLOATSAFE fs; #endif
return(max(flA,flB)); }
|