//===----------------------------------------------------------------------===//
#include "llvm/Support/ScaledNumber.h"
-
#include "llvm/Support/DataTypes.h"
#include "gtest/gtest.h"
EXPECT_EQ(SP32(0, 0), getQuotient32(0, 0));
EXPECT_EQ(SP32(0, 0), getQuotient32(0, 1));
EXPECT_EQ(SP32(0, 0), getQuotient32(0, 73));
- EXPECT_EQ(SP32(UINT32_MAX, INT16_MAX), getQuotient32(1, 0));
- EXPECT_EQ(SP32(UINT32_MAX, INT16_MAX), getQuotient32(6, 0));
+ EXPECT_EQ(SP32(UINT32_MAX, MaxScale), getQuotient32(1, 0));
+ EXPECT_EQ(SP32(UINT32_MAX, MaxScale), getQuotient32(6, 0));
// Powers of two.
EXPECT_EQ(SP32(1u << 31, -31), getQuotient32(1, 1));
EXPECT_EQ(SP64(0, 0), getQuotient64(0, 0));
EXPECT_EQ(SP64(0, 0), getQuotient64(0, 1));
EXPECT_EQ(SP64(0, 0), getQuotient64(0, 73));
- EXPECT_EQ(SP64(UINT64_MAX, INT16_MAX), getQuotient64(1, 0));
- EXPECT_EQ(SP64(UINT64_MAX, INT16_MAX), getQuotient64(6, 0));
+ EXPECT_EQ(SP64(UINT64_MAX, MaxScale), getQuotient64(1, 0));
+ EXPECT_EQ(SP64(UINT64_MAX, MaxScale), getQuotient64(6, 0));
// Powers of two.
EXPECT_EQ(SP64(1, 0), getQuotient64(1, 1));
}
TEST(ScaledNumberHelpersTest, matchScales) {
- typedef std::tuple<uint32_t, int16_t, uint32_t, int16_t> Pair32;
- typedef std::tuple<uint64_t, int16_t, uint64_t, int16_t> Pair64;
-
#define MATCH_SCALES(T, LDIn, LSIn, RDIn, RSIn, LDOut, RDOut, SOut) \
do { \
T LDx = LDIn; \
MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 59, 4, 9, UINT64_C(1) << 63, 0);
}
+TEST(ScaledNumberHelpersTest, getSum) {
+ // Zero.
+ EXPECT_EQ(SP32(1, 0), getSum32(0, 0, 1, 0));
+ EXPECT_EQ(SP32(8, -3), getSum32(0, 0, 8, -3));
+ EXPECT_EQ(SP32(UINT32_MAX, 0), getSum32(0, 0, UINT32_MAX, 0));
+
+ // Basic.
+ EXPECT_EQ(SP32(2, 0), getSum32(1, 0, 1, 0));
+ EXPECT_EQ(SP32(3, 0), getSum32(1, 0, 2, 0));
+ EXPECT_EQ(SP32(67, 0), getSum32(7, 0, 60, 0));
+
+ // Different scales.
+ EXPECT_EQ(SP32(3, 0), getSum32(1, 0, 1, 1));
+ EXPECT_EQ(SP32(4, 0), getSum32(2, 0, 1, 1));
+
+ // Loss of precision.
+ EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(1, 32, 1, 0));
+ EXPECT_EQ(SP32(UINT32_C(1) << 31, -31), getSum32(1, -32, 1, 0));
+
+ // Not quite loss of precision.
+ EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, 1), getSum32(1, 32, 1, 1));
+ EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, -32), getSum32(1, -32, 1, -1));
+
+ // Overflow.
+ EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(1, 0, UINT32_MAX, 0));
+
+ // Reverse operand order.
+ EXPECT_EQ(SP32(1, 0), getSum32(1, 0, 0, 0));
+ EXPECT_EQ(SP32(8, -3), getSum32(8, -3, 0, 0));
+ EXPECT_EQ(SP32(UINT32_MAX, 0), getSum32(UINT32_MAX, 0, 0, 0));
+ EXPECT_EQ(SP32(3, 0), getSum32(2, 0, 1, 0));
+ EXPECT_EQ(SP32(67, 0), getSum32(60, 0, 7, 0));
+ EXPECT_EQ(SP32(3, 0), getSum32(1, 1, 1, 0));
+ EXPECT_EQ(SP32(4, 0), getSum32(1, 1, 2, 0));
+ EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(1, 0, 1, 32));
+ EXPECT_EQ(SP32(UINT32_C(1) << 31, -31), getSum32(1, 0, 1, -32));
+ EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, 1), getSum32(1, 1, 1, 32));
+ EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, -32), getSum32(1, -1, 1, -32));
+ EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(UINT32_MAX, 0, 1, 0));
+
+ // Zero.
+ EXPECT_EQ(SP64(1, 0), getSum64(0, 0, 1, 0));
+ EXPECT_EQ(SP64(8, -3), getSum64(0, 0, 8, -3));
+ EXPECT_EQ(SP64(UINT64_MAX, 0), getSum64(0, 0, UINT64_MAX, 0));
+
+ // Basic.
+ EXPECT_EQ(SP64(2, 0), getSum64(1, 0, 1, 0));
+ EXPECT_EQ(SP64(3, 0), getSum64(1, 0, 2, 0));
+ EXPECT_EQ(SP64(67, 0), getSum64(7, 0, 60, 0));
+
+ // Different scales.
+ EXPECT_EQ(SP64(3, 0), getSum64(1, 0, 1, 1));
+ EXPECT_EQ(SP64(4, 0), getSum64(2, 0, 1, 1));
+
+ // Loss of precision.
+ EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(1, 64, 1, 0));
+ EXPECT_EQ(SP64(UINT64_C(1) << 63, -63), getSum64(1, -64, 1, 0));
+
+ // Not quite loss of precision.
+ EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, 1), getSum64(1, 64, 1, 1));
+ EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, -64), getSum64(1, -64, 1, -1));
+
+ // Overflow.
+ EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(1, 0, UINT64_MAX, 0));
+
+ // Reverse operand order.
+ EXPECT_EQ(SP64(1, 0), getSum64(1, 0, 0, 0));
+ EXPECT_EQ(SP64(8, -3), getSum64(8, -3, 0, 0));
+ EXPECT_EQ(SP64(UINT64_MAX, 0), getSum64(UINT64_MAX, 0, 0, 0));
+ EXPECT_EQ(SP64(3, 0), getSum64(2, 0, 1, 0));
+ EXPECT_EQ(SP64(67, 0), getSum64(60, 0, 7, 0));
+ EXPECT_EQ(SP64(3, 0), getSum64(1, 1, 1, 0));
+ EXPECT_EQ(SP64(4, 0), getSum64(1, 1, 2, 0));
+ EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(1, 0, 1, 64));
+ EXPECT_EQ(SP64(UINT64_C(1) << 63, -63), getSum64(1, 0, 1, -64));
+ EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, 1), getSum64(1, 1, 1, 64));
+ EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, -64), getSum64(1, -1, 1, -64));
+ EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(UINT64_MAX, 0, 1, 0));
+}
+
+TEST(ScaledNumberHelpersTest, getDifference) {
+ // Basic.
+ EXPECT_EQ(SP32(0, 0), getDifference32(1, 0, 1, 0));
+ EXPECT_EQ(SP32(1, 0), getDifference32(2, 0, 1, 0));
+ EXPECT_EQ(SP32(53, 0), getDifference32(60, 0, 7, 0));
+
+ // Equals "0", different scales.
+ EXPECT_EQ(SP32(0, 0), getDifference32(2, 0, 1, 1));
+
+ // Subtract "0".
+ EXPECT_EQ(SP32(1, 0), getDifference32(1, 0, 0, 0));
+ EXPECT_EQ(SP32(8, -3), getDifference32(8, -3, 0, 0));
+ EXPECT_EQ(SP32(UINT32_MAX, 0), getDifference32(UINT32_MAX, 0, 0, 0));
+
+ // Loss of precision.
+ EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, 1),
+ getDifference32((UINT32_C(1) << 31) + 1, 1, 1, 0));
+ EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, -31),
+ getDifference32((UINT32_C(1) << 31) + 1, -31, 1, -32));
+
+ // Not quite loss of precision.
+ EXPECT_EQ(SP32(UINT32_MAX, 0), getDifference32(1, 32, 1, 0));
+ EXPECT_EQ(SP32(UINT32_MAX, -32), getDifference32(1, 0, 1, -32));
+
+ // Saturate to "0".
+ EXPECT_EQ(SP32(0, 0), getDifference32(0, 0, 1, 0));
+ EXPECT_EQ(SP32(0, 0), getDifference32(0, 0, 8, -3));
+ EXPECT_EQ(SP32(0, 0), getDifference32(0, 0, UINT32_MAX, 0));
+ EXPECT_EQ(SP32(0, 0), getDifference32(7, 0, 60, 0));
+ EXPECT_EQ(SP32(0, 0), getDifference32(1, 0, 1, 1));
+ EXPECT_EQ(SP32(0, 0), getDifference32(1, -32, 1, 0));
+ EXPECT_EQ(SP32(0, 0), getDifference32(1, -32, 1, -1));
+
+ // Regression tests for cases that failed during bringup.
+ EXPECT_EQ(SP32(UINT32_C(1) << 26, -31),
+ getDifference32(1, 0, UINT32_C(31) << 27, -32));
+
+ // Basic.
+ EXPECT_EQ(SP64(0, 0), getDifference64(1, 0, 1, 0));
+ EXPECT_EQ(SP64(1, 0), getDifference64(2, 0, 1, 0));
+ EXPECT_EQ(SP64(53, 0), getDifference64(60, 0, 7, 0));
+
+ // Equals "0", different scales.
+ EXPECT_EQ(SP64(0, 0), getDifference64(2, 0, 1, 1));
+
+ // Subtract "0".
+ EXPECT_EQ(SP64(1, 0), getDifference64(1, 0, 0, 0));
+ EXPECT_EQ(SP64(8, -3), getDifference64(8, -3, 0, 0));
+ EXPECT_EQ(SP64(UINT64_MAX, 0), getDifference64(UINT64_MAX, 0, 0, 0));
+
+ // Loss of precision.
+ EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, 1),
+ getDifference64((UINT64_C(1) << 63) + 1, 1, 1, 0));
+ EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, -63),
+ getDifference64((UINT64_C(1) << 63) + 1, -63, 1, -64));
+
+ // Not quite loss of precision.
+ EXPECT_EQ(SP64(UINT64_MAX, 0), getDifference64(1, 64, 1, 0));
+ EXPECT_EQ(SP64(UINT64_MAX, -64), getDifference64(1, 0, 1, -64));
+
+ // Saturate to "0".
+ EXPECT_EQ(SP64(0, 0), getDifference64(0, 0, 1, 0));
+ EXPECT_EQ(SP64(0, 0), getDifference64(0, 0, 8, -3));
+ EXPECT_EQ(SP64(0, 0), getDifference64(0, 0, UINT64_MAX, 0));
+ EXPECT_EQ(SP64(0, 0), getDifference64(7, 0, 60, 0));
+ EXPECT_EQ(SP64(0, 0), getDifference64(1, 0, 1, 1));
+ EXPECT_EQ(SP64(0, 0), getDifference64(1, -64, 1, 0));
+ EXPECT_EQ(SP64(0, 0), getDifference64(1, -64, 1, -1));
+}
+
} // end namespace