FloatUtils: Remove union type punning from ClassifyX functions

Type-punning via unions is undefined behavior in C++

Also take the liberty of cleaning these up a little bit by removing
unnecessary else usages.
This commit is contained in:
Lioncash 2018-05-09 09:51:38 -04:00
parent fe218ea3f6
commit f29e7fea2a
1 changed files with 46 additions and 56 deletions

View File

@ -11,80 +11,70 @@ namespace Common
{ {
u32 ClassifyDouble(double dvalue) u32 ClassifyDouble(double dvalue)
{ {
// TODO: Optimize the below to be as fast as possible. u64 ivalue;
IntDouble value(dvalue); std::memcpy(&ivalue, &dvalue, sizeof(ivalue));
u64 sign = value.i & DOUBLE_SIGN;
u64 exp = value.i & DOUBLE_EXP; const u64 sign = ivalue & DOUBLE_SIGN;
const u64 exp = ivalue & DOUBLE_EXP;
if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP) if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP)
{ {
// Nice normalized number. // Nice normalized number.
return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN; return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
} }
else
const u64 mantissa = ivalue & DOUBLE_FRAC;
if (mantissa)
{ {
u64 mantissa = value.i & DOUBLE_FRAC; if (exp)
if (mantissa) return PPC_FPCLASS_QNAN;
{
if (exp) // Denormalized number.
{ return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
return PPC_FPCLASS_QNAN;
}
else
{
// Denormalized number.
return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
}
}
else if (exp)
{
// Infinite
return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
}
else
{
// Zero
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
}
} }
if (exp)
{
// Infinite
return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
}
// Zero
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
} }
u32 ClassifyFloat(float fvalue) u32 ClassifyFloat(float fvalue)
{ {
// TODO: Optimize the below to be as fast as possible. u32 ivalue;
IntFloat value(fvalue); std::memcpy(&ivalue, &fvalue, sizeof(ivalue));
u32 sign = value.i & FLOAT_SIGN;
u32 exp = value.i & FLOAT_EXP; const u32 sign = ivalue & FLOAT_SIGN;
const u32 exp = ivalue & FLOAT_EXP;
if (exp > FLOAT_ZERO && exp < FLOAT_EXP) if (exp > FLOAT_ZERO && exp < FLOAT_EXP)
{ {
// Nice normalized number. // Nice normalized number.
return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN; return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
} }
else
const u32 mantissa = ivalue & FLOAT_FRAC;
if (mantissa)
{ {
u32 mantissa = value.i & FLOAT_FRAC; if (exp)
if (mantissa) return PPC_FPCLASS_QNAN; // Quiet NAN
{
if (exp) // Denormalized number.
{ return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
return PPC_FPCLASS_QNAN; // Quiet NAN
}
else
{
// Denormalized number.
return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
}
}
else if (exp)
{
// Infinite
return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
}
else
{
// Zero
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
}
} }
if (exp)
{
// Infinite
return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
}
// Zero
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
} }
const std::array<BaseAndDec, 32> frsqrte_expected = {{ const std::array<BaseAndDec, 32> frsqrte_expected = {{