Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

450 lines
6.1 KiB

// 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));
}