forked from OSchip/llvm-project
Support: Extract ScaledNumbers::compare()
llvm-svn: 211507
This commit is contained in:
parent
f7062b2313
commit
0067ff4678
|
@ -66,19 +66,6 @@ public:
|
|||
return IsNeg ? INT64_MIN : INT64_MAX;
|
||||
return IsNeg ? -int64_t(U) : int64_t(U);
|
||||
}
|
||||
|
||||
static int compare(uint64_t L, uint64_t R, int Shift) {
|
||||
assert(Shift >= 0);
|
||||
assert(Shift < 64);
|
||||
|
||||
uint64_t L_adjusted = L >> Shift;
|
||||
if (L_adjusted < R)
|
||||
return -1;
|
||||
if (L_adjusted > R)
|
||||
return 1;
|
||||
|
||||
return L > L_adjusted << Shift ? 1 : 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Simple representation of an unsigned floating point.
|
||||
|
@ -289,7 +276,9 @@ public:
|
|||
return joinSigned(scaleByInverse(Unsigned.first), Unsigned.second);
|
||||
}
|
||||
|
||||
int compare(const UnsignedFloat &X) const;
|
||||
int compare(const UnsignedFloat &X) const {
|
||||
return ScaledNumbers::compare(Digits, Exponent, X.Digits, X.Exponent);
|
||||
}
|
||||
int compareTo(uint64_t N) const {
|
||||
UnsignedFloat Float = getFloat(N);
|
||||
int Compare = compare(Float);
|
||||
|
@ -605,27 +594,6 @@ void UnsignedFloat<DigitsT>::shiftRight(int32_t Shift) {
|
|||
return;
|
||||
}
|
||||
|
||||
template <class DigitsT>
|
||||
int UnsignedFloat<DigitsT>::compare(const UnsignedFloat &X) const {
|
||||
// Check for zero.
|
||||
if (isZero())
|
||||
return X.isZero() ? 0 : -1;
|
||||
if (X.isZero())
|
||||
return 1;
|
||||
|
||||
// Check for the scale. Use lgFloor to be sure that the exponent difference
|
||||
// is always lower than 64.
|
||||
int32_t lgL = lgFloor(), lgR = X.lgFloor();
|
||||
if (lgL != lgR)
|
||||
return lgL < lgR ? -1 : 1;
|
||||
|
||||
// Compare digits.
|
||||
if (Exponent < X.Exponent)
|
||||
return UnsignedFloatBase::compare(Digits, X.Digits, X.Exponent - Exponent);
|
||||
|
||||
return -UnsignedFloatBase::compare(X.Digits, Digits, Exponent - X.Exponent);
|
||||
}
|
||||
|
||||
template <class T> struct isPodLike<UnsignedFloat<T>> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
|
|
@ -227,6 +227,40 @@ template <class DigitsT> int32_t getLgCeiling(DigitsT Digits, int16_t Scale) {
|
|||
return Lg.first + (Lg.second < 0);
|
||||
}
|
||||
|
||||
/// \brief Implementation for comparing scaled numbers.
|
||||
///
|
||||
/// Compare two 64-bit numbers with different scales. Given that the scale of
|
||||
/// \c L is higher than that of \c R by \c ScaleDiff, compare them. Return -1,
|
||||
/// 1, and 0 for less than, greater than, and equal, respectively.
|
||||
///
|
||||
/// \pre 0 <= ScaleDiff < 64.
|
||||
int compareImpl(uint64_t L, uint64_t R, int ScaleDiff);
|
||||
|
||||
/// \brief Compare two scaled numbers.
|
||||
///
|
||||
/// Compare two scaled numbers. Returns 0 for equal, -1 for less than, and 1
|
||||
/// for greater than.
|
||||
template <class DigitsT>
|
||||
int compare(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale) {
|
||||
// Check for zero.
|
||||
if (!LDigits)
|
||||
return RDigits ? -1 : 0;
|
||||
if (!RDigits)
|
||||
return 1;
|
||||
|
||||
// Check for the scale. Use getLgFloor to be sure that the scale difference
|
||||
// is always lower than 64.
|
||||
int32_t lgL = getLgFloor(LDigits, LScale), lgR = getLgFloor(RDigits, RScale);
|
||||
if (lgL != lgR)
|
||||
return lgL < lgR ? -1 : 1;
|
||||
|
||||
// Compare digits.
|
||||
if (LScale < RScale)
|
||||
return compareImpl(LDigits, RDigits, RScale - LScale);
|
||||
|
||||
return -compareImpl(RDigits, LDigits, LScale - RScale);
|
||||
}
|
||||
|
||||
} // end namespace ScaledNumbers
|
||||
} // end namespace llvm
|
||||
|
||||
|
|
|
@ -117,3 +117,16 @@ std::pair<uint64_t, int16_t> ScaledNumbers::divide64(uint64_t Dividend,
|
|||
|
||||
return getRounded(Quotient, Shift, Dividend >= getHalf(Divisor));
|
||||
}
|
||||
|
||||
int ScaledNumbers::compareImpl(uint64_t L, uint64_t R, int ScaleDiff) {
|
||||
assert(ScaleDiff >= 0 && "wrong argument order");
|
||||
assert(ScaleDiff < 64 && "numbers too far apart");
|
||||
|
||||
uint64_t L_adjusted = L >> ScaleDiff;
|
||||
if (L_adjusted < R)
|
||||
return -1;
|
||||
if (L_adjusted > R)
|
||||
return 1;
|
||||
|
||||
return L > L_adjusted << ScaleDiff ? 1 : 0;
|
||||
}
|
||||
|
|
|
@ -285,4 +285,41 @@ TEST(ScaledNumberHelpersTest, getLgCeiling) {
|
|||
EXPECT_EQ(INT32_MIN, getLgCeiling(UINT64_C(0), 1));
|
||||
}
|
||||
|
||||
TEST(ScaledNumberHelpersTest, Compare) {
|
||||
EXPECT_EQ(0, compare(UINT32_C(0), 0, UINT32_C(0), 1));
|
||||
EXPECT_EQ(0, compare(UINT32_C(0), 0, UINT32_C(0), -10));
|
||||
EXPECT_EQ(0, compare(UINT32_C(0), 0, UINT32_C(0), 20));
|
||||
EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(64), -3));
|
||||
EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(32), -2));
|
||||
EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(16), -1));
|
||||
EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(8), 0));
|
||||
EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(4), 1));
|
||||
EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(2), 2));
|
||||
EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(1), 3));
|
||||
EXPECT_EQ(-1, compare(UINT32_C(0), 0, UINT32_C(1), 3));
|
||||
EXPECT_EQ(-1, compare(UINT32_C(7), 0, UINT32_C(1), 3));
|
||||
EXPECT_EQ(-1, compare(UINT32_C(7), 0, UINT32_C(64), -3));
|
||||
EXPECT_EQ(1, compare(UINT32_C(9), 0, UINT32_C(1), 3));
|
||||
EXPECT_EQ(1, compare(UINT32_C(9), 0, UINT32_C(64), -3));
|
||||
EXPECT_EQ(1, compare(UINT32_C(9), 0, UINT32_C(0), 0));
|
||||
|
||||
EXPECT_EQ(0, compare(UINT64_C(0), 0, UINT64_C(0), 1));
|
||||
EXPECT_EQ(0, compare(UINT64_C(0), 0, UINT64_C(0), -10));
|
||||
EXPECT_EQ(0, compare(UINT64_C(0), 0, UINT64_C(0), 20));
|
||||
EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(64), -3));
|
||||
EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(32), -2));
|
||||
EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(16), -1));
|
||||
EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(8), 0));
|
||||
EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(4), 1));
|
||||
EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(2), 2));
|
||||
EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(1), 3));
|
||||
EXPECT_EQ(-1, compare(UINT64_C(0), 0, UINT64_C(1), 3));
|
||||
EXPECT_EQ(-1, compare(UINT64_C(7), 0, UINT64_C(1), 3));
|
||||
EXPECT_EQ(-1, compare(UINT64_C(7), 0, UINT64_C(64), -3));
|
||||
EXPECT_EQ(1, compare(UINT64_C(9), 0, UINT64_C(1), 3));
|
||||
EXPECT_EQ(1, compare(UINT64_C(9), 0, UINT64_C(64), -3));
|
||||
EXPECT_EQ(1, compare(UINT64_C(9), 0, UINT64_C(0), 0));
|
||||
EXPECT_EQ(-1, compare(UINT64_MAX, 0, UINT64_C(1), 64));
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
|
Loading…
Reference in New Issue