[APInt] Implement tcDecrement as a counterpart to tcIncrement. This is for use in APFloat IEEE-754R 2008 nextUp/nextDown function.

rdar://13852078

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182801 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Michael Gottesman 2013-05-28 19:50:20 +00:00
parent e274b476de
commit a32edcfbc5
3 changed files with 82 additions and 0 deletions

View File

@ -1642,6 +1642,9 @@ public:
/// Increment a bignum in-place. Return the carry flag.
static integerPart tcIncrement(integerPart *, unsigned int);
/// Decrement a bignum in-place. Return the borrow flag.
static integerPart tcDecrement(integerPart *, unsigned int);
/// Set the least significant BITS and clear the rest.
static void tcSetLeastSignificantBits(integerPart *, unsigned int,
unsigned int bits);

View File

@ -2888,6 +2888,20 @@ APInt::tcIncrement(integerPart *dst, unsigned int parts)
return i == parts;
}
/* Decrement a bignum in-place, return the borrow flag. */
integerPart
APInt::tcDecrement(integerPart *dst, unsigned int parts) {
for (unsigned int i = 0; i < parts; i++) {
// If the current word is non-zero, then the decrement has no effect on the
// higher-order words of the integer and no borrow can occur. Exit early.
if (dst[i]--)
return 0;
}
// If every word was zero, then there is a borrow.
return 1;
}
/* Set the least significant BITS bits of a bignum, clear the
rest. */
void

View File

@ -532,4 +532,69 @@ TEST(APIntTest, Splat) {
EXPECT_EQ(APInt(15, 0xDB6D), APInt::getSplat(15, ValB));
}
TEST(APIntTest, tcDecrement) {
// Test single word decrement.
// No out borrow.
{
integerPart singleWord = ~integerPart(0) << (integerPartWidth - 1);
integerPart carry = APInt::tcDecrement(&singleWord, 1);
EXPECT_EQ(carry, integerPart(0));
EXPECT_EQ(singleWord, ~integerPart(0) >> 1);
}
// With out borrow.
{
integerPart singleWord = 0;
integerPart carry = APInt::tcDecrement(&singleWord, 1);
EXPECT_EQ(carry, integerPart(1));
EXPECT_EQ(singleWord, ~integerPart(0));
}
// Test multiword decrement.
// No across word borrow, no out borrow.
{
integerPart test[4] = {0x1, 0x1, 0x1, 0x1};
integerPart expected[4] = {0x0, 0x1, 0x1, 0x1};
APInt::tcDecrement(test, 4);
EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0);
}
// 1 across word borrow, no out borrow.
{
integerPart test[4] = {0x0, 0xF, 0x1, 0x1};
integerPart expected[4] = {~integerPart(0), 0xE, 0x1, 0x1};
integerPart carry = APInt::tcDecrement(test, 4);
EXPECT_EQ(carry, integerPart(0));
EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0);
}
// 2 across word borrow, no out borrow.
{
integerPart test[4] = {0x0, 0x0, 0xC, 0x1};
integerPart expected[4] = {~integerPart(0), ~integerPart(0), 0xB, 0x1};
integerPart carry = APInt::tcDecrement(test, 4);
EXPECT_EQ(carry, integerPart(0));
EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0);
}
// 3 across word borrow, no out borrow.
{
integerPart test[4] = {0x0, 0x0, 0x0, 0x1};
integerPart expected[4] = {~integerPart(0), ~integerPart(0), ~integerPart(0), 0x0};
integerPart carry = APInt::tcDecrement(test, 4);
EXPECT_EQ(carry, integerPart(0));
EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0);
}
// 3 across word borrow, with out borrow.
{
integerPart test[4] = {0x0, 0x0, 0x0, 0x0};
integerPart expected[4] = {~integerPart(0), ~integerPart(0), ~integerPart(0), ~integerPart(0)};
integerPart carry = APInt::tcDecrement(test, 4);
EXPECT_EQ(carry, integerPart(1));
EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0);
}
}
}