mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-21 18:22:53 +01:00
[Fixed Point] Add floating point methods to APFixedPoint.
This adds methods to APFixedPoint for converting to and from floating point values. Differential Revision: https://reviews.llvm.org/D85961
This commit is contained in:
parent
5f5f4fe543
commit
ad6d96ea4f
@ -22,6 +22,9 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class APFloat;
|
||||
struct fltSemantics;
|
||||
|
||||
/// The fixed point semantics work similarly to fltSemantics. The width
|
||||
/// specifies the whole bit width of the underlying scaled integer (with padding
|
||||
/// if any). The scale represents the number of fractional bits in this type.
|
||||
@ -63,6 +66,15 @@ public:
|
||||
FixedPointSemantics
|
||||
getCommonSemantics(const FixedPointSemantics &Other) const;
|
||||
|
||||
/// Returns true if this fixed-point semantic with its value bits interpreted
|
||||
/// as an integer can fit in the given floating point semantic without
|
||||
/// overflowing to infinity.
|
||||
/// For example, a signed 8-bit fixed-point semantic has a maximum and
|
||||
/// minimum integer representation of 127 and -128, respectively. If both of
|
||||
/// these values can be represented (possibly inexactly) in the floating
|
||||
/// point semantic without overflowing, this returns true.
|
||||
bool fitsInFloatSemantics(const fltSemantics &FloatSema) const;
|
||||
|
||||
/// Return the FixedPointSemantics for an integer type.
|
||||
static FixedPointSemantics GetIntegerSemantics(unsigned Width,
|
||||
bool IsSigned) {
|
||||
@ -153,12 +165,13 @@ public:
|
||||
/// If the overflow parameter is provided, and the integral value is not able
|
||||
/// to be fully stored in the provided width and sign, the overflow parameter
|
||||
/// is set to true.
|
||||
///
|
||||
/// If the overflow parameter is provided, set this value to true or false to
|
||||
/// indicate if this operation results in an overflow.
|
||||
APSInt convertToInt(unsigned DstWidth, bool DstSign,
|
||||
bool *Overflow = nullptr) const;
|
||||
|
||||
/// Convert this fixed point number to a floating point value with the
|
||||
/// provided semantics.
|
||||
APFloat convertToFloat(const fltSemantics &FloatSema) const;
|
||||
|
||||
void toString(SmallVectorImpl<char> &Str) const;
|
||||
std::string toString() const {
|
||||
SmallString<40> S;
|
||||
@ -186,6 +199,10 @@ public:
|
||||
static APFixedPoint getMax(const FixedPointSemantics &Sema);
|
||||
static APFixedPoint getMin(const FixedPointSemantics &Sema);
|
||||
|
||||
/// Given a floating point semantic, return the next floating point semantic
|
||||
/// with a larger exponent and larger or equal mantissa.
|
||||
static const fltSemantics *promoteFloatSemantics(const fltSemantics *S);
|
||||
|
||||
/// Create an APFixedPoint with a value equal to that of the provided integer,
|
||||
/// and in the same semantics as the provided target semantics. If the value
|
||||
/// is not able to fit in the specified fixed point semantics, and the
|
||||
@ -194,6 +211,17 @@ public:
|
||||
const FixedPointSemantics &DstFXSema,
|
||||
bool *Overflow = nullptr);
|
||||
|
||||
/// Create an APFixedPoint with a value equal to that of the provided
|
||||
/// floating point value, in the provided target semantics. If the value is
|
||||
/// not able to fit in the specified fixed point semantics and the overflow
|
||||
/// parameter is specified, it is set to true.
|
||||
/// For NaN, the Overflow flag is always set. For +inf and -inf, if the
|
||||
/// semantic is saturating, the value saturates. Otherwise, the Overflow flag
|
||||
/// is set.
|
||||
static APFixedPoint getFromFloatValue(const APFloat &Value,
|
||||
const FixedPointSemantics &DstFXSema,
|
||||
bool *Overflow = nullptr);
|
||||
|
||||
private:
|
||||
APSInt Val;
|
||||
FixedPointSemantics Sema;
|
||||
@ -204,6 +232,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, const APFixedPoint &FX) {
|
||||
return OS;
|
||||
}
|
||||
|
||||
} // namespace llvm
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -12,6 +12,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/APFixedPoint.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -124,6 +125,29 @@ APFixedPoint APFixedPoint::getMin(const FixedPointSemantics &Sema) {
|
||||
return APFixedPoint(Val, Sema);
|
||||
}
|
||||
|
||||
bool FixedPointSemantics::fitsInFloatSemantics(
|
||||
const fltSemantics &FloatSema) const {
|
||||
// A fixed point semantic fits in a floating point semantic if the maximum
|
||||
// and minimum values as integers of the fixed point semantic can fit in the
|
||||
// floating point semantic.
|
||||
|
||||
// If these values do not fit, then a floating point rescaling of the true
|
||||
// maximum/minimum value will not fit either, so the floating point semantic
|
||||
// cannot be used to perform such a rescaling.
|
||||
|
||||
APSInt MaxInt = APFixedPoint::getMax(*this).getValue();
|
||||
APFloat F(FloatSema);
|
||||
APFloat::opStatus Status = F.convertFromAPInt(MaxInt, MaxInt.isSigned(),
|
||||
APFloat::rmNearestTiesToAway);
|
||||
if ((Status & APFloat::opOverflow) || !isSigned())
|
||||
return !(Status & APFloat::opOverflow);
|
||||
|
||||
APSInt MinInt = APFixedPoint::getMin(*this).getValue();
|
||||
Status = F.convertFromAPInt(MinInt, MinInt.isSigned(),
|
||||
APFloat::rmNearestTiesToAway);
|
||||
return !(Status & APFloat::opOverflow);
|
||||
}
|
||||
|
||||
FixedPointSemantics FixedPointSemantics::getCommonSemantics(
|
||||
const FixedPointSemantics &Other) const {
|
||||
unsigned CommonScale = std::max(getScale(), Other.getScale());
|
||||
@ -417,6 +441,54 @@ APSInt APFixedPoint::convertToInt(unsigned DstWidth, bool DstSign,
|
||||
return Result.extOrTrunc(DstWidth);
|
||||
}
|
||||
|
||||
const fltSemantics *APFixedPoint::promoteFloatSemantics(const fltSemantics *S) {
|
||||
if (S == &APFloat::BFloat())
|
||||
return &APFloat::IEEEdouble();
|
||||
else if (S == &APFloat::IEEEhalf())
|
||||
return &APFloat::IEEEsingle();
|
||||
else if (S == &APFloat::IEEEsingle())
|
||||
return &APFloat::IEEEdouble();
|
||||
else if (S == &APFloat::IEEEdouble())
|
||||
return &APFloat::IEEEquad();
|
||||
llvm_unreachable("Could not promote float type!");
|
||||
}
|
||||
|
||||
APFloat APFixedPoint::convertToFloat(const fltSemantics &FloatSema) const {
|
||||
// For some operations, rounding mode has an effect on the result, while
|
||||
// other operations are lossless and should never result in rounding.
|
||||
// To signify which these operations are, we define two rounding modes here.
|
||||
APFloat::roundingMode RM = APFloat::rmNearestTiesToEven;
|
||||
APFloat::roundingMode LosslessRM = APFloat::rmTowardZero;
|
||||
|
||||
// Make sure that we are operating in a type that works with this fixed-point
|
||||
// semantic.
|
||||
const fltSemantics *OpSema = &FloatSema;
|
||||
while (!Sema.fitsInFloatSemantics(*OpSema))
|
||||
OpSema = promoteFloatSemantics(OpSema);
|
||||
|
||||
// Convert the fixed point value bits as an integer. If the floating point
|
||||
// value does not have the required precision, we will round according to the
|
||||
// given mode.
|
||||
APFloat Flt(*OpSema);
|
||||
APFloat::opStatus S = Flt.convertFromAPInt(Val, Sema.isSigned(), RM);
|
||||
|
||||
// If we cared about checking for precision loss, we could look at this
|
||||
// status.
|
||||
(void)S;
|
||||
|
||||
// Scale down the integer value in the float to match the correct scaling
|
||||
// factor.
|
||||
APFloat ScaleFactor(std::pow(2, -(int)Sema.getScale()));
|
||||
bool Ignored;
|
||||
ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);
|
||||
Flt.multiply(ScaleFactor, LosslessRM);
|
||||
|
||||
if (OpSema != &FloatSema)
|
||||
Flt.convert(FloatSema, RM, &Ignored);
|
||||
|
||||
return Flt;
|
||||
}
|
||||
|
||||
APFixedPoint APFixedPoint::getFromIntValue(const APSInt &Value,
|
||||
const FixedPointSemantics &DstFXSema,
|
||||
bool *Overflow) {
|
||||
@ -425,4 +497,78 @@ APFixedPoint APFixedPoint::getFromIntValue(const APSInt &Value,
|
||||
return APFixedPoint(Value, IntFXSema).convert(DstFXSema, Overflow);
|
||||
}
|
||||
|
||||
} // namespace clang
|
||||
APFixedPoint
|
||||
APFixedPoint::getFromFloatValue(const APFloat &Value,
|
||||
const FixedPointSemantics &DstFXSema,
|
||||
bool *Overflow) {
|
||||
// For some operations, rounding mode has an effect on the result, while
|
||||
// other operations are lossless and should never result in rounding.
|
||||
// To signify which these operations are, we define two rounding modes here,
|
||||
// even though they are the same mode.
|
||||
APFloat::roundingMode RM = APFloat::rmTowardZero;
|
||||
APFloat::roundingMode LosslessRM = APFloat::rmTowardZero;
|
||||
|
||||
const fltSemantics &FloatSema = Value.getSemantics();
|
||||
|
||||
if (Value.isNaN()) {
|
||||
// Handle NaN immediately.
|
||||
if (Overflow)
|
||||
*Overflow = true;
|
||||
return APFixedPoint(DstFXSema);
|
||||
}
|
||||
|
||||
// Make sure that we are operating in a type that works with this fixed-point
|
||||
// semantic.
|
||||
const fltSemantics *OpSema = &FloatSema;
|
||||
while (!DstFXSema.fitsInFloatSemantics(*OpSema))
|
||||
OpSema = promoteFloatSemantics(OpSema);
|
||||
|
||||
APFloat Val = Value;
|
||||
|
||||
bool Ignored;
|
||||
if (&FloatSema != OpSema)
|
||||
Val.convert(*OpSema, LosslessRM, &Ignored);
|
||||
|
||||
// Scale up the float so that the 'fractional' part of the mantissa ends up in
|
||||
// the integer range instead. Rounding mode is irrelevant here.
|
||||
// It is fine if this overflows to infinity even for saturating types,
|
||||
// since we will use floating point comparisons to check for saturation.
|
||||
APFloat ScaleFactor(std::pow(2, DstFXSema.getScale()));
|
||||
ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);
|
||||
Val.multiply(ScaleFactor, LosslessRM);
|
||||
|
||||
// Convert to the integral representation of the value. This rounding mode
|
||||
// is significant.
|
||||
APSInt Res(DstFXSema.getWidth(), !DstFXSema.isSigned());
|
||||
Val.convertToInteger(Res, RM, &Ignored);
|
||||
|
||||
// Round the integral value and scale back. This makes the
|
||||
// overflow calculations below work properly. If we do not round here,
|
||||
// we risk checking for overflow with a value that is outside the
|
||||
// representable range of the fixed-point semantic even though no overflow
|
||||
// would occur had we rounded first.
|
||||
ScaleFactor = APFloat(std::pow(2, -(int)DstFXSema.getScale()));
|
||||
ScaleFactor.convert(*OpSema, LosslessRM, &Ignored);
|
||||
Val.roundToIntegral(RM);
|
||||
Val.multiply(ScaleFactor, LosslessRM);
|
||||
|
||||
// Check for overflow/saturation by checking if the floating point value
|
||||
// is outside the range representable by the fixed-point value.
|
||||
APFloat FloatMax = getMax(DstFXSema).convertToFloat(*OpSema);
|
||||
APFloat FloatMin = getMin(DstFXSema).convertToFloat(*OpSema);
|
||||
bool Overflowed = false;
|
||||
if (DstFXSema.isSaturated()) {
|
||||
if (Val > FloatMax)
|
||||
Res = getMax(DstFXSema).getValue();
|
||||
else if (Val < FloatMin)
|
||||
Res = getMin(DstFXSema).getValue();
|
||||
} else
|
||||
Overflowed = Val > FloatMax || Val < FloatMin;
|
||||
|
||||
if (Overflow)
|
||||
*Overflow = Overflowed;
|
||||
|
||||
return APFixedPoint(Res, DstFXSema);
|
||||
}
|
||||
|
||||
} // namespace llvm
|
||||
|
@ -7,13 +7,15 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/APFixedPoint.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using llvm::APFixedPoint;
|
||||
using llvm::FixedPointSemantics;
|
||||
using llvm::APFloat;
|
||||
using llvm::APInt;
|
||||
using llvm::APSInt;
|
||||
using llvm::FixedPointSemantics;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -641,4 +643,282 @@ TEST(FixedPoint, ModularWrapAround) {
|
||||
4294967295ULL << 32);
|
||||
}
|
||||
|
||||
enum OvfKind { MinSat, MaxSat };
|
||||
|
||||
void CheckFloatToFixedConversion(APFloat &Val, const FixedPointSemantics &Sema,
|
||||
int64_t ExpectedNonSat) {
|
||||
bool Ovf;
|
||||
ASSERT_EQ(APFixedPoint::getFromFloatValue(Val, Sema, &Ovf).getValue(),
|
||||
ExpectedNonSat);
|
||||
ASSERT_EQ(Ovf, false);
|
||||
ASSERT_EQ(
|
||||
APFixedPoint::getFromFloatValue(Val, Saturated(Sema), &Ovf).getValue(),
|
||||
ExpectedNonSat);
|
||||
ASSERT_EQ(Ovf, false);
|
||||
}
|
||||
|
||||
void CheckFloatToFixedConversion(APFloat &Val, const FixedPointSemantics &Sema,
|
||||
OvfKind ExpectedOvf) {
|
||||
bool Ovf;
|
||||
(void)APFixedPoint::getFromFloatValue(Val, Sema, &Ovf);
|
||||
ASSERT_EQ(Ovf, true);
|
||||
ASSERT_EQ(
|
||||
APFixedPoint::getFromFloatValue(Val, Saturated(Sema), &Ovf).getValue(),
|
||||
(ExpectedOvf == MinSat ? APFixedPoint::getMin(Sema)
|
||||
: APFixedPoint::getMax(Sema))
|
||||
.getValue());
|
||||
ASSERT_EQ(Ovf, false);
|
||||
}
|
||||
|
||||
TEST(FixedPoint, FloatToFixed) {
|
||||
APFloat Val(0.0f);
|
||||
|
||||
// Simple exact fraction
|
||||
Val = APFloat(0.75f);
|
||||
CheckFloatToFixedConversion(Val, getSAccumSema(), 3ULL << 5);
|
||||
CheckFloatToFixedConversion(Val, getAccumSema(), 3ULL << 13);
|
||||
CheckFloatToFixedConversion(Val, getLAccumSema(), 3ULL << 29);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSAccumSema(), 3ULL << 6);
|
||||
CheckFloatToFixedConversion(Val, getUAccumSema(), 3ULL << 14);
|
||||
CheckFloatToFixedConversion(Val, getULAccumSema(), 3ULL << 30);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getSFractSema(), 3ULL << 5);
|
||||
CheckFloatToFixedConversion(Val, getFractSema(), 3ULL << 13);
|
||||
CheckFloatToFixedConversion(Val, getLFractSema(), 3ULL << 29);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSFractSema(), 3ULL << 6);
|
||||
CheckFloatToFixedConversion(Val, getUFractSema(), 3ULL << 14);
|
||||
CheckFloatToFixedConversion(Val, getULFractSema(), 3ULL << 30);
|
||||
|
||||
// Simple negative exact fraction
|
||||
Val = APFloat(-0.75f);
|
||||
CheckFloatToFixedConversion(Val, getSAccumSema(), -3ULL << 5);
|
||||
CheckFloatToFixedConversion(Val, getAccumSema(), -3ULL << 13);
|
||||
CheckFloatToFixedConversion(Val, getLAccumSema(), -3ULL << 29);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSAccumSema(), MinSat);
|
||||
CheckFloatToFixedConversion(Val, getUAccumSema(), MinSat);
|
||||
CheckFloatToFixedConversion(Val, getULAccumSema(), MinSat);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getSFractSema(), -3ULL << 5);
|
||||
CheckFloatToFixedConversion(Val, getFractSema(), -3ULL << 13);
|
||||
CheckFloatToFixedConversion(Val, getLFractSema(), -3ULL << 29);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSFractSema(), MinSat);
|
||||
CheckFloatToFixedConversion(Val, getUFractSema(), MinSat);
|
||||
CheckFloatToFixedConversion(Val, getULFractSema(), MinSat);
|
||||
|
||||
// Highly precise fraction
|
||||
Val = APFloat(0.999999940395355224609375f);
|
||||
CheckFloatToFixedConversion(Val, getSAccumSema(), 0x7FULL);
|
||||
CheckFloatToFixedConversion(Val, getAccumSema(), 0x7FFFULL);
|
||||
CheckFloatToFixedConversion(Val, getLAccumSema(), 0xFFFFFFULL << 7);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSAccumSema(), 0xFFULL);
|
||||
CheckFloatToFixedConversion(Val, getUAccumSema(), 0xFFFFULL);
|
||||
CheckFloatToFixedConversion(Val, getULAccumSema(), 0xFFFFFFULL << 8);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getSFractSema(), 0x7FULL);
|
||||
CheckFloatToFixedConversion(Val, getFractSema(), 0x7FFFULL);
|
||||
CheckFloatToFixedConversion(Val, getLFractSema(), 0xFFFFFFULL << 7);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSFractSema(), 0xFFULL);
|
||||
CheckFloatToFixedConversion(Val, getUFractSema(), 0xFFFFULL);
|
||||
CheckFloatToFixedConversion(Val, getULFractSema(), 0xFFFFFFULL << 8);
|
||||
|
||||
// Integral and fraction
|
||||
Val = APFloat(17.99609375f);
|
||||
CheckFloatToFixedConversion(Val, getSAccumSema(), 0x11FFULL >> 1);
|
||||
CheckFloatToFixedConversion(Val, getAccumSema(), 0x11FFULL << 7);
|
||||
CheckFloatToFixedConversion(Val, getLAccumSema(), 0x11FFULL << 23);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSAccumSema(), 0x11FFULL);
|
||||
CheckFloatToFixedConversion(Val, getUAccumSema(), 0x11FFULL << 8);
|
||||
CheckFloatToFixedConversion(Val, getULAccumSema(), 0x11FFULL << 24);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getSFractSema(), MaxSat);
|
||||
CheckFloatToFixedConversion(Val, getFractSema(), MaxSat);
|
||||
CheckFloatToFixedConversion(Val, getLFractSema(), MaxSat);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSFractSema(), MaxSat);
|
||||
CheckFloatToFixedConversion(Val, getUFractSema(), MaxSat);
|
||||
CheckFloatToFixedConversion(Val, getULFractSema(), MaxSat);
|
||||
|
||||
// Negative integral and fraction
|
||||
Val = APFloat(-17.99609375f);
|
||||
CheckFloatToFixedConversion(Val, getSAccumSema(), -0x11FELL >> 1);
|
||||
CheckFloatToFixedConversion(Val, getAccumSema(), -0x11FFULL << 7);
|
||||
CheckFloatToFixedConversion(Val, getLAccumSema(), -0x11FFULL << 23);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSAccumSema(), MinSat);
|
||||
CheckFloatToFixedConversion(Val, getUAccumSema(), MinSat);
|
||||
CheckFloatToFixedConversion(Val, getULAccumSema(), MinSat);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getSFractSema(), MinSat);
|
||||
CheckFloatToFixedConversion(Val, getFractSema(), MinSat);
|
||||
CheckFloatToFixedConversion(Val, getLFractSema(), MinSat);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSFractSema(), MinSat);
|
||||
CheckFloatToFixedConversion(Val, getUFractSema(), MinSat);
|
||||
CheckFloatToFixedConversion(Val, getULFractSema(), MinSat);
|
||||
|
||||
// Very large value
|
||||
Val = APFloat(1.0e38f);
|
||||
CheckFloatToFixedConversion(Val, getSAccumSema(), MaxSat);
|
||||
CheckFloatToFixedConversion(Val, getAccumSema(), MaxSat);
|
||||
CheckFloatToFixedConversion(Val, getLAccumSema(), MaxSat);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSAccumSema(), MaxSat);
|
||||
CheckFloatToFixedConversion(Val, getUAccumSema(), MaxSat);
|
||||
CheckFloatToFixedConversion(Val, getULAccumSema(), MaxSat);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getSFractSema(), MaxSat);
|
||||
CheckFloatToFixedConversion(Val, getFractSema(), MaxSat);
|
||||
CheckFloatToFixedConversion(Val, getLFractSema(), MaxSat);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSFractSema(), MaxSat);
|
||||
CheckFloatToFixedConversion(Val, getUFractSema(), MaxSat);
|
||||
CheckFloatToFixedConversion(Val, getULFractSema(), MaxSat);
|
||||
|
||||
// Very small value
|
||||
Val = APFloat(1.0e-38f);
|
||||
CheckFloatToFixedConversion(Val, getSAccumSema(), 0);
|
||||
CheckFloatToFixedConversion(Val, getAccumSema(), 0);
|
||||
CheckFloatToFixedConversion(Val, getLAccumSema(), 0);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSAccumSema(), 0);
|
||||
CheckFloatToFixedConversion(Val, getUAccumSema(), 0);
|
||||
CheckFloatToFixedConversion(Val, getULAccumSema(), 0);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getSFractSema(), 0);
|
||||
CheckFloatToFixedConversion(Val, getFractSema(), 0);
|
||||
CheckFloatToFixedConversion(Val, getLFractSema(), 0);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSFractSema(), 0);
|
||||
CheckFloatToFixedConversion(Val, getUFractSema(), 0);
|
||||
CheckFloatToFixedConversion(Val, getULFractSema(), 0);
|
||||
|
||||
// Half conversion
|
||||
Val = APFloat(0.99951171875f);
|
||||
bool Ignored;
|
||||
Val.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getSAccumSema(), 0x7FULL);
|
||||
CheckFloatToFixedConversion(Val, getAccumSema(), 0x7FFULL << 4);
|
||||
CheckFloatToFixedConversion(Val, getLAccumSema(), 0x7FFULL << 20);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSAccumSema(), 0xFFULL);
|
||||
CheckFloatToFixedConversion(Val, getUAccumSema(), 0xFFEULL << 4);
|
||||
CheckFloatToFixedConversion(Val, getULAccumSema(), 0xFFEULL << 20);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getSFractSema(), 0x7FULL);
|
||||
CheckFloatToFixedConversion(Val, getFractSema(), 0x7FFULL << 4);
|
||||
CheckFloatToFixedConversion(Val, getLFractSema(), 0x7FFULL << 20);
|
||||
|
||||
CheckFloatToFixedConversion(Val, getUSFractSema(), 0xFFULL);
|
||||
CheckFloatToFixedConversion(Val, getUFractSema(), 0xFFEULL << 4);
|
||||
CheckFloatToFixedConversion(Val, getULFractSema(), 0xFFEULL << 20);
|
||||
}
|
||||
|
||||
void CheckFixedToFloatConversion(int64_t Val, const FixedPointSemantics &Sema,
|
||||
float Result) {
|
||||
APFixedPoint FXVal(Val, Sema);
|
||||
APFloat APRes(Result);
|
||||
ASSERT_EQ(FXVal.convertToFloat(APFloat::IEEEsingle()), APRes);
|
||||
}
|
||||
|
||||
void CheckFixedToHalfConversion(int64_t Val, const FixedPointSemantics &Sema,
|
||||
float Result) {
|
||||
APFixedPoint FXVal(Val, Sema);
|
||||
APFloat APRes(Result);
|
||||
bool Ignored;
|
||||
APRes.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored);
|
||||
ASSERT_EQ(FXVal.convertToFloat(APFloat::IEEEhalf()), APRes);
|
||||
}
|
||||
|
||||
TEST(FixedPoint, FixedToFloat) {
|
||||
int64_t Val = 0x1ULL;
|
||||
CheckFixedToFloatConversion(Val, getSAccumSema(), 0.0078125f);
|
||||
CheckFixedToFloatConversion(Val, getFractSema(), 0.000030517578125f);
|
||||
CheckFixedToFloatConversion(Val, getAccumSema(), 0.000030517578125f);
|
||||
CheckFixedToFloatConversion(Val, getLFractSema(),
|
||||
0.0000000004656612873077392578125f);
|
||||
|
||||
CheckFixedToFloatConversion(Val, getUSAccumSema(), 0.00390625f);
|
||||
CheckFixedToFloatConversion(Val, getUFractSema(), 0.0000152587890625f);
|
||||
CheckFixedToFloatConversion(Val, getUAccumSema(), 0.0000152587890625f);
|
||||
CheckFixedToFloatConversion(Val, getULFractSema(),
|
||||
0.00000000023283064365386962890625f);
|
||||
|
||||
Val = 0x7FULL;
|
||||
CheckFixedToFloatConversion(Val, getSAccumSema(), 0.9921875f);
|
||||
CheckFixedToFloatConversion(Val, getFractSema(), 0.003875732421875f);
|
||||
CheckFixedToFloatConversion(Val, getAccumSema(), 0.003875732421875f);
|
||||
CheckFixedToFloatConversion(Val, getLFractSema(),
|
||||
0.0000000591389834880828857421875f);
|
||||
|
||||
CheckFixedToFloatConversion(Val, getUSAccumSema(), 0.49609375f);
|
||||
CheckFixedToFloatConversion(Val, getUFractSema(), 0.0019378662109375f);
|
||||
CheckFixedToFloatConversion(Val, getUAccumSema(), 0.0019378662109375f);
|
||||
CheckFixedToFloatConversion(Val, getULFractSema(),
|
||||
0.00000002956949174404144287109375f);
|
||||
|
||||
Val = -0x1ULL;
|
||||
CheckFixedToFloatConversion(Val, getSAccumSema(), -0.0078125f);
|
||||
CheckFixedToFloatConversion(Val, getFractSema(), -0.000030517578125f);
|
||||
CheckFixedToFloatConversion(Val, getAccumSema(), -0.000030517578125f);
|
||||
CheckFixedToFloatConversion(Val, getLFractSema(),
|
||||
-0.0000000004656612873077392578125f);
|
||||
|
||||
|
||||
CheckFixedToFloatConversion(-0x80ULL, getSAccumSema(), -1.0f);
|
||||
CheckFixedToFloatConversion(-0x8000ULL, getFractSema(), -1.0f);
|
||||
CheckFixedToFloatConversion(-0x8000ULL, getAccumSema(), -1.0f);
|
||||
CheckFixedToFloatConversion(-0x80000000ULL, getLFractSema(), -1.0f);
|
||||
|
||||
Val = 0xAFAULL;
|
||||
CheckFixedToFloatConversion(Val, getSAccumSema(), 21.953125f);
|
||||
CheckFixedToFloatConversion(Val, getFractSema(), 0.08575439453125f);
|
||||
CheckFixedToFloatConversion(Val, getAccumSema(), 0.08575439453125f);
|
||||
CheckFixedToFloatConversion(Val, getLFractSema(),
|
||||
0.000001308508217334747314453125f);
|
||||
|
||||
CheckFixedToFloatConversion(Val, getUSAccumSema(), 10.9765625f);
|
||||
CheckFixedToFloatConversion(Val, getUFractSema(), 0.042877197265625f);
|
||||
CheckFixedToFloatConversion(Val, getUAccumSema(), 0.042877197265625f);
|
||||
CheckFixedToFloatConversion(Val, getULFractSema(),
|
||||
0.0000006542541086673736572265625f);
|
||||
|
||||
Val = -0xAFAULL;
|
||||
CheckFixedToFloatConversion(Val, getSAccumSema(), -21.953125f);
|
||||
CheckFixedToFloatConversion(Val, getFractSema(), -0.08575439453125f);
|
||||
CheckFixedToFloatConversion(Val, getAccumSema(), -0.08575439453125f);
|
||||
CheckFixedToFloatConversion(Val, getLFractSema(),
|
||||
-0.000001308508217334747314453125f);
|
||||
|
||||
Val = 0x40000080ULL;
|
||||
CheckFixedToFloatConversion(Val, getAccumSema(), 32768.00390625f);
|
||||
CheckFixedToFloatConversion(Val, getLFractSema(),
|
||||
0.500000059604644775390625f);
|
||||
|
||||
CheckFixedToFloatConversion(Val, getUAccumSema(), 16384.001953125f);
|
||||
CheckFixedToFloatConversion(Val, getULFractSema(),
|
||||
0.2500000298023223876953125f);
|
||||
|
||||
Val = 0x40000040ULL;
|
||||
CheckFixedToFloatConversion(Val, getAccumSema(), 32768.0f);
|
||||
CheckFixedToFloatConversion(Val, getLFractSema(), 0.5f);
|
||||
|
||||
CheckFixedToFloatConversion(Val, getUAccumSema(), 16384.0f);
|
||||
CheckFixedToFloatConversion(Val, getULFractSema(), 0.25f);
|
||||
|
||||
Val = 0x7FF0ULL;
|
||||
CheckFixedToHalfConversion(Val, getAccumSema(), 0.99951171875f);
|
||||
CheckFixedToHalfConversion(Val, getLFractSema(), 0.000015251338481903076171875f);
|
||||
|
||||
CheckFixedToHalfConversion(Val, getUAccumSema(), 0.499755859375f);
|
||||
CheckFixedToHalfConversion(Val, getULFractSema(), 0.0000076256692409515380859375f);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
Loading…
Reference in New Issue
Block a user