MathUtil: fix IsQNAN()

The constants were one nibble too short and the lower 51 bits don't
actually have to be zero.
This commit is contained in:
Tillmann Karras
2014-03-09 19:34:58 +01:00
parent d71aef8843
commit 9ef64245fa
3 changed files with 41 additions and 24 deletions

View File

@ -20,16 +20,18 @@ inline void Clamp(T* val, const T& min, const T& max)
*val = max;
}
// The most significant bit of the fraction is an is-quiet bit on all architectures we care about.
static const u64 DOUBLE_SIGN = 0x8000000000000000ULL,
DOUBLE_EXP = 0x7FF0000000000000ULL,
DOUBLE_FRAC = 0x000FFFFFFFFFFFFFULL,
DOUBLE_ZERO = 0x0000000000000000ULL;
DOUBLE_EXP = 0x7FF0000000000000ULL,
DOUBLE_FRAC = 0x000FFFFFFFFFFFFFULL,
DOUBLE_ZERO = 0x0000000000000000ULL,
DOUBLE_QBIT = 0x0008000000000000ULL;
static const u32 FLOAT_SIGN = 0x80000000,
FLOAT_EXP = 0x7F800000,
FLOAT_FRAC = 0x007FFFFF,
FLOAT_ZERO = 0x00000000;
FLOAT_EXP = 0x7F800000,
FLOAT_FRAC = 0x007FFFFF,
FLOAT_ZERO = 0x00000000;
union IntDouble {
double d;
@ -40,34 +42,41 @@ union IntFloat {
u32 i;
};
inline bool IsINF(double d)
{
IntDouble x; x.d = d;
return (x.i & ~DOUBLE_SIGN) == DOUBLE_EXP;
}
inline bool IsNAN(double d)
{
IntDouble x; x.d = d;
return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) );
return ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
((x.i & DOUBLE_FRAC) != DOUBLE_ZERO);
}
inline bool IsQNAN(double d)
{
IntDouble x; x.d = d;
return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
((x.i & 0x0007fffffffffffULL) == 0x000000000000000ULL) &&
((x.i & 0x000800000000000ULL) == 0x000800000000000ULL) );
return ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
((x.i & DOUBLE_QBIT) == DOUBLE_QBIT);
}
inline bool IsSNAN(double d)
{
IntDouble x; x.d = d;
return( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) &&
((x.i & 0x0008000000000000ULL) == DOUBLE_ZERO) );
return ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) &&
((x.i & DOUBLE_QBIT) == DOUBLE_ZERO);
}
inline float FlushToZero(float f)
{
IntFloat x; x.f = f;
if ((x.i & FLOAT_EXP) == 0)
{
x.i &= FLOAT_SIGN; // turn into signed zero
}
return x.f;
}
@ -75,7 +84,9 @@ inline double FlushToZero(double d)
{
IntDouble x; x.d = d;
if ((x.i & DOUBLE_EXP) == 0)
{
x.i &= DOUBLE_SIGN; // turn into signed zero
}
return x.d;
}