[APInt] Implement tcDecrement as a counterpart to tcIncrement. This is for use in...
authorMichael Gottesman <mgottesman@apple.com>
Tue, 28 May 2013 19:50:20 +0000 (19:50 +0000)
committerMichael Gottesman <mgottesman@apple.com>
Tue, 28 May 2013 19:50:20 +0000 (19:50 +0000)
rdar://13852078

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182801 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/APInt.h
lib/Support/APInt.cpp
unittests/ADT/APIntTest.cpp

index fc1aedbc53e5aa55b51a3a64361b3fc2ddf53cd9..a9df4036be2d90047594e35b7cc560d1fe8b1331 100644 (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);
index 71c509592c1f18f73e07f7f33a8effaaa1e986ff..108675d1e9a224976e4a14134cc2ddf441df7126 100644 (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
index f129fa71c8e0671ea54316e8e881babc8a2d28da..3c0dfe1440447b2fd22128200d9479721d50dd2e 100644 (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);
+  }
+}
 }