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:
parent
d71aef8843
commit
9ef64245fa
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,22 +33,19 @@ const u32 FPSCR_VXSQRT = (u32)1 << (31 - 22);
|
|||
const u32 FPSCR_VXCVI = (u32)1 << (31 - 23);
|
||||
|
||||
const u32 FPSCR_VX_ANY = FPSCR_VXSNAN | FPSCR_VXISI | FPSCR_VXIDI | FPSCR_VXZDZ |
|
||||
FPSCR_VXIMZ | FPSCR_VXVC | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI;
|
||||
FPSCR_VXIMZ | FPSCR_VXVC | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI;
|
||||
|
||||
const u32 FPSCR_ANY_X = FPSCR_OX | FPSCR_UX | FPSCR_ZX | FPSCR_XX | FPSCR_VX_ANY;
|
||||
|
||||
const u64 PPC_NAN_U64 = 0x7ff8000000000000ull;
|
||||
const double PPC_NAN = *(double* const)&PPC_NAN_U64;
|
||||
|
||||
inline bool IsINF(double x)
|
||||
{
|
||||
return ((*(u64*)&x) & ~DOUBLE_SIGN) == DOUBLE_EXP;
|
||||
}
|
||||
|
||||
inline void SetFPException(u32 mask)
|
||||
{
|
||||
if ((FPSCR.Hex & mask) != mask)
|
||||
{
|
||||
FPSCR.FX = 1;
|
||||
}
|
||||
FPSCR.Hex |= mask;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cmath>
|
||||
#include <gtest/gtest.h>
|
||||
#include <limits>
|
||||
|
||||
#include "Common/MathUtil.h"
|
||||
|
||||
|
@ -27,19 +27,28 @@ TEST(MathUtil, Clamp)
|
|||
EXPECT_EQ(0.0, ClampAndReturn(-1.0, 0.0, 2.0));
|
||||
}
|
||||
|
||||
TEST(MathUtil, IsINF)
|
||||
{
|
||||
EXPECT_TRUE(MathUtil::IsINF( std::numeric_limits<double>::infinity()));
|
||||
EXPECT_TRUE(MathUtil::IsINF(-std::numeric_limits<double>::infinity()));
|
||||
}
|
||||
|
||||
TEST(MathUtil, IsNAN)
|
||||
{
|
||||
EXPECT_TRUE(MathUtil::IsNAN(nan("")));
|
||||
EXPECT_TRUE(MathUtil::IsNAN(std::numeric_limits<double>::quiet_NaN()));
|
||||
EXPECT_TRUE(MathUtil::IsNAN(std::numeric_limits<double>::signaling_NaN()));
|
||||
}
|
||||
|
||||
TEST(MathUtil, IsQNAN)
|
||||
{
|
||||
// TODO
|
||||
EXPECT_TRUE(MathUtil::IsQNAN(std::numeric_limits<double>::quiet_NaN()));
|
||||
EXPECT_FALSE(MathUtil::IsQNAN(std::numeric_limits<double>::signaling_NaN()));
|
||||
}
|
||||
|
||||
TEST(MathUtil, IsSNAN)
|
||||
{
|
||||
// TODO
|
||||
EXPECT_FALSE(MathUtil::IsSNAN(std::numeric_limits<double>::quiet_NaN()));
|
||||
EXPECT_TRUE(MathUtil::IsSNAN(std::numeric_limits<double>::signaling_NaN()));
|
||||
}
|
||||
|
||||
TEST(MathUtil, Log2)
|
||||
|
|
Loading…
Reference in New Issue