Serious-Engine/Sources/Engine/Math/Float.cpp
Ryan C. Gordon 24cb244d43 First attempt to hand-merge Ryan's Linux and Mac OS X port.
This was a _ton_ of changes, made 15 years ago, so there are probably some
problems to work out still.

Among others: Engine/Base/Stream.* was mostly abandoned and will need to be
re-ported.

Still, this is a pretty good start, and probably holds a world record for
lines of changes or something.  :)
2016-03-28 23:46:13 -04:00

175 lines
3.6 KiB
C++

/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
#include "Engine/StdH.h"
#include <Engine/Math/Float.h>
#if (defined __GNU_INLINE__)
#define MCW_PC 0x0300
#define _MCW_PC MCW_PC
#define _PC_24 0x0000
#define _PC_53 0x0200
#define _PC_64 0x0300
inline ULONG _control87(WORD newcw, WORD mask)
{
#if __POWERPC__
static WORD fpw=_PC_64;
if (mask != 0)
{
fpw &= ~mask;
fpw |= (newcw & mask);
}
return(fpw);
#else
WORD fpw = 0;
// get the current FPU control word...
__asm__ __volatile__ ("fstcw %0" : "=m" (fpw) : : "memory");
if (mask != 0)
{
fpw &= ~mask;
fpw |= (newcw & mask);
__asm__ __volatile__ (" fldcw %0" : : "m" (fpw) : "memory");
}
return(fpw);
#endif
}
// (for intel compiler...)
#elif ((defined __MSVC_INLINE__) && (!defined _MSC_VER))
#define MCW_PC 0x0300
#define _MCW_PC MCW_PC
#define _PC_24 0x0000
#define _PC_53 0x0200
#define _PC_64 0x0300
inline ULONG _control87(WORD newcw, WORD mask)
{
WORD fpw = 0;
// get the current FPU control word...
__asm fstcw word ptr [fpw];
if (mask != 0)
{
fpw &= ~mask;
fpw |= (newcw & mask);
__asm fldcw word ptr [fpw];
}
return(fpw);
}
#elif (!defined _MSC_VER)
#error Implement for your platform, or add a stub conditional here.
#endif
/* Get current precision setting of FPU. */
enum FPUPrecisionType GetFPUPrecision(void)
{
// get control flags from FPU
ULONG fpcw = _control87( 0, 0);
// extract the precision from the flags
switch(fpcw&_MCW_PC) {
case _PC_24:
return FPT_24BIT;
break;
case _PC_53:
return FPT_53BIT;
break;
case _PC_64:
return FPT_64BIT;
break;
default:
ASSERT(FALSE);
return FPT_24BIT;
};
}
/* Set current precision setting of FPU. */
void SetFPUPrecision(enum FPUPrecisionType fptNew)
{
ULONG fpcw;
// create FPU flags from the precision
switch(fptNew) {
case FPT_24BIT:
fpcw=_PC_24;
break;
case FPT_53BIT:
fpcw=_PC_53;
break;
case FPT_64BIT:
fpcw=_PC_64;
break;
default:
ASSERT(FALSE);
fpcw=_PC_24;
};
// set the FPU precission
_control87( fpcw, MCW_PC);
}
/////////////////////////////////////////////////////////////////////
// CSetFPUPrecision
/*
* Constructor with automatic setting of FPU precision.
*/
CSetFPUPrecision::CSetFPUPrecision(enum FPUPrecisionType fptNew)
{
// remember old precision
sfp_fptOldPrecision = GetFPUPrecision();
// set new precision if needed
sfp_fptNewPrecision = fptNew;
if (sfp_fptNewPrecision!=sfp_fptOldPrecision) {
SetFPUPrecision(fptNew);
}
}
/*
* Destructor with automatic restoring of FPU precision.
*/
CSetFPUPrecision::~CSetFPUPrecision(void)
{
// check consistency
ASSERT(GetFPUPrecision()==sfp_fptNewPrecision);
// restore old precision if needed
if (sfp_fptNewPrecision!=sfp_fptOldPrecision) {
SetFPUPrecision(sfp_fptOldPrecision);
}
}
BOOL IsValidFloat(float f)
{
return _finite(f) && (*(ULONG*)&f)!=0xcdcdcdcdUL;
/* int iClass = _fpclass(f);
return
iClass==_FPCLASS_NN ||
iClass==_FPCLASS_ND ||
iClass==_FPCLASS_NZ ||
iClass==_FPCLASS_PZ ||
iClass==_FPCLASS_PD ||
iClass==_FPCLASS_PN;
*/
}
BOOL IsValidDouble(double f)
{
#ifdef _MSC_VER
return _finite(f) && (*(unsigned __int64*)&f)!=0xcdcdcdcdcdcdcdcdI64;
#else
return _finite(f) && (*(unsigned long long*)&f)!=0xcdcdcdcdcdcdcdcdll;
#endif
/* int iClass = _fpclass(f);
return
iClass==_FPCLASS_NN ||
iClass==_FPCLASS_ND ||
iClass==_FPCLASS_NZ ||
iClass==_FPCLASS_PZ ||
iClass==_FPCLASS_PD ||
iClass==_FPCLASS_PN;
*/
}