[llvm-commits] CVS: llvm/lib/Support/APInt.cpp

Reid Spencer reid at x10sys.com
Sat Feb 24 02:01:59 PST 2007



Changes in directory llvm/lib/Support:

APInt.cpp updated: 1.33 -> 1.34
---
Log message:

1. Fix last bug in KnuthDiv. All divide tests pass up to 1024 bits now.
2. Clean up comments, style, coding standards, etc.
3. Simplify a constructor.

Extended testing revealed some additional bugs in shifting. I'll fix these
tomorrow.


---
Diffs of the changes:  (+54 -62)

 APInt.cpp |  116 ++++++++++++++++++++++++++++----------------------------------
 1 files changed, 54 insertions(+), 62 deletions(-)


Index: llvm/lib/Support/APInt.cpp
diff -u llvm/lib/Support/APInt.cpp:1.33 llvm/lib/Support/APInt.cpp:1.34
--- llvm/lib/Support/APInt.cpp:1.33	Fri Feb 23 21:58:46 2007
+++ llvm/lib/Support/APInt.cpp	Sat Feb 24 04:01:42 2007
@@ -2,8 +2,9 @@
 //
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by Sheng Zhou and is distributed under the
-// University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file was developed by Sheng Zhou and Reid Spencer and is distributed 
+// under the // University of Illinois Open Source License. See LICENSE.TXT 
+// for details.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -20,14 +21,13 @@
 #include <cstring>
 #include <cstdlib>
 #ifndef NDEBUG
-#include <iostream>
 #include <iomanip>
 #endif
 
 using namespace llvm;
 
 // A utility function for allocating memory, checking for allocation failures,
-// and ensuring the contents is zeroed.
+// and ensuring the contents are zeroed.
 inline static uint64_t* getClearedMemory(uint32_t numWords) {
   uint64_t * result = new uint64_t[numWords];
   assert(result && "APInt memory allocation fails!");
@@ -36,6 +36,7 @@
 }
 
 // A utility function for allocating memory and checking for allocation failure.
+// The content is not zero'd
 inline static uint64_t* getMemory(uint32_t numWords) {
   uint64_t * result = new uint64_t[numWords];
   assert(result && "APInt memory allocation fails!");
@@ -60,38 +61,31 @@
   assert(BitWidth <= IntegerType::MAX_INT_BITS && "bitwidth too large");
   assert(bigVal && "Null pointer detected!");
   if (isSingleWord())
-    VAL = bigVal[0] & (~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitWidth));
+    VAL = bigVal[0];
   else {
-    pVal = getMemory(getNumWords());
-    // Calculate the actual length of bigVal[].
-    uint32_t maxN = std::max<uint32_t>(numWords, getNumWords());
-    uint32_t minN = std::min<uint32_t>(numWords, getNumWords());
-    memcpy(pVal, bigVal, (minN - 1) * APINT_WORD_SIZE);
-    pVal[minN-1] = bigVal[minN-1] & 
-                    (~uint64_t(0ULL) >> 
-                     (APINT_BITS_PER_WORD - BitWidth % APINT_BITS_PER_WORD));
-    if (maxN == getNumWords())
-      memset(pVal+numWords, 0, (getNumWords() - numWords) * APINT_WORD_SIZE);
+    // Get memory, cleared to 0
+    pVal = getClearedMemory(getNumWords());
+    // Calculate the number of words to copy
+    uint32_t words = std::min<uint32_t>(numWords, getNumWords());
+    // Copy the words from bigVal to pVal
+    memcpy(pVal, bigVal, words * APINT_WORD_SIZE);
   }
+  // Make sure unused high bits are cleared
+  clearUnusedBits();
 }
 
-/// @brief Create a new APInt by translating the char array represented
-/// integer value.
 APInt::APInt(uint32_t numbits, const char StrStart[], uint32_t slen, 
              uint8_t radix) 
   : BitWidth(numbits), VAL(0) {
   fromString(numbits, StrStart, slen, radix);
 }
 
-/// @brief Create a new APInt by translating the string represented
-/// integer value.
 APInt::APInt(uint32_t numbits, const std::string& Val, uint8_t radix)
   : BitWidth(numbits), VAL(0) {
   assert(!Val.empty() && "String empty?");
   fromString(numbits, Val.c_str(), Val.size(), radix);
 }
 
-/// @brief Copy constructor
 APInt::APInt(const APInt& that)
   : BitWidth(that.BitWidth), VAL(0) {
   if (isSingleWord()) 
@@ -107,8 +101,6 @@
     delete[] pVal;
 }
 
-/// @brief Copy assignment operator. Create a new object from the given
-/// APInt one by initialization.
 APInt& APInt::operator=(const APInt& RHS) {
   assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
   if (isSingleWord()) 
@@ -118,8 +110,6 @@
   return *this;
 }
 
-/// @brief Assignment operator. Assigns a common case integer value to 
-/// the APInt.
 APInt& APInt::operator=(uint64_t RHS) {
   if (isSingleWord()) 
     VAL = RHS;
@@ -134,15 +124,13 @@
 /// "digit" integer array,  x[]. x[] is modified to reflect the addition and
 /// 1 is returned if there is a carry out, otherwise 0 is returned.
 /// @returns the carry of the addition.
-static uint64_t add_1(uint64_t dest[], 
-                             uint64_t x[], uint32_t len, 
-                             uint64_t y) {
+static uint64_t add_1(uint64_t dest[], uint64_t x[], uint32_t len, uint64_t y) {
   for (uint32_t i = 0; i < len; ++i) {
     dest[i] = y + x[i];
     if (dest[i] < y)
-      y = 1;
+      y = 1; // Carry one to next digit.
     else {
-      y = 0;
+      y = 0; // No need to carry so exit early
       break;
     }
   }
@@ -216,7 +204,7 @@
 }
 
 /// sub - This function subtracts the integer array x[] by
-/// integer array y[], and returns the borrow-out carry.
+/// integer array y[], and returns the borrow-out.
 static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, 
                 uint32_t len) {
   bool borrow = false;
@@ -243,10 +231,8 @@
 /// mul_1 - This function performs the multiplication operation on a
 /// large integer (represented as an integer array) and a uint64_t integer.
 /// @returns the carry of the multiplication.
-static uint64_t mul_1(uint64_t dest[], 
-                             uint64_t x[], uint32_t len, 
-                             uint64_t y) {
-  // Split y into high 32-bit part and low 32-bit part.
+static uint64_t mul_1(uint64_t dest[], uint64_t x[], uint32_t len, uint64_t y) {
+  // Split y into high 32-bit part (hy)  and low 32-bit part (ly)
   uint64_t ly = y & 0xffffffffULL, hy = y >> 32;
   uint64_t carry = 0, lx, hx;
   for (uint32_t i = 0; i < len; ++i) {
@@ -277,10 +263,9 @@
 /// mul - This function multiplies integer array x[] by integer array y[] and
 /// stores the result into integer array dest[].
 /// Note the array dest[]'s size should no less than xlen + ylen.
-static void mul(uint64_t dest[], uint64_t x[], uint32_t xlen,
-                uint64_t y[], uint32_t ylen) {
+static void mul(uint64_t dest[], uint64_t x[], uint32_t xlen, uint64_t y[], 
+                uint32_t ylen) {
   dest[xlen] = mul_1(dest, x, xlen, y[0]);
-
   for (uint32_t i = 1; i < ylen; ++i) {
     uint64_t ly = y[i] & 0xffffffffULL, hy = y[i] >> 32;
     uint64_t carry = 0, lx = 0, hx = 0;
@@ -1053,43 +1038,50 @@
     if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) {
       qp--;
       rp += v[n-1];
-      if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) {
+      if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2]))
         qp--;
-        //rp += v[n-1];
-      }
     }
     DEBUG(cerr << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n');
 
     // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with
     // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation
     // consists of a simple multiplication by a one-place number, combined with
-    // a subtraction. The digits (u[j+n]...u[j]) should be kept positive;
-    bool borrow = false;
+    // a subtraction. 
+    bool isNegative = false;
     for (uint32_t i = 0; i < n; ++i) {
-      uint64_t u_tmp = borrow ? uint64_t(u[j+i] - 1) : uint64_t(u[j+i]);
+      uint64_t u_tmp = uint64_t(u[j+i]) | (uint64_t(u[j+i+1]) << 32);
       uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]);
+      bool borrow = subtrahend > u_tmp;
       DEBUG(cerr << "KnuthDiv: u_tmp == " << u_tmp 
-                 << ", subtrahend == " << subtrahend << '\n');
+                 << ", subtrahend == " << subtrahend
+                 << ", borrow = " << borrow << '\n');
 
-      borrow = subtrahend > u_tmp || (borrow && u[j+i] == 0);
-      u[j+i] = u_tmp - subtrahend;
-    }
-    if (borrow) {
-      borrow = u[j+n] == 0;            // Was result negative?
-      u[j+n]--;  // handle the borrow
+      uint64_t result = u_tmp - subtrahend;
+      uint32_t k = j + i;
+      u[k++] = result & (b-1); // subtract low word
+      u[k++] = result >> 32;   // subtract high word
+      while (borrow && k <= m+n) { // deal with borrow to the left
+        borrow = u[k] == 0;
+        u[k]--;
+        k++;
+      }
+      isNegative |= borrow;
+      DEBUG(cerr << "KnuthDiv: u[j+i] == " << u[j+i] << ",  u[j+i+1] == " << 
+                    u[j+i+1] << '\n'); 
     }
     DEBUG(cerr << "KnuthDiv: after subtraction:");
     DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]);
     DEBUG(cerr << '\n');
-    // if the result of this step is actually negative, (u[j+n]...u[j]) should
-    // be left as the true value plus b**(n+1), namely as the b's complement of
+    // The digits (u[j+n]...u[j]) should be kept positive; if the result of 
+    // this step is actually negative, (u[j+n]...u[j]) should be left as the 
+    // true value plus b**(n+1), namely as the b's complement of
     // the true value, and a "borrow" to the left should be remembered.
     //
-    if (borrow) {
-      bool carry = true;
-      for (uint32_t i = 0; i <= n; ++i) {
-        u[j+i] = ~u[j+i] + carry; // b's complement
-        carry = u[j+i] == 0;
+    if (isNegative) {
+      bool carry = true;  // true because b's complement is "complement + 1"
+      for (uint32_t i = 0; i <= m+n; ++i) {
+        u[i] = ~u[i] + carry; // b's complement
+        carry = carry && u[i] == 0;
       }
     }
     DEBUG(cerr << "KnuthDiv: after complement:");
@@ -1099,7 +1091,7 @@
     // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was 
     // negative, go to step D6; otherwise go on to step D7.
     q[j] = qp;
-    if (borrow) {
+    if (isNegative) {
       // D6. [Add back]. The probability that this step is necessary is very 
       // small, on the order of only 2/b. Make sure that test data accounts for
       // this possibility. Decrease q[j] by 1 
@@ -1516,12 +1508,12 @@
 #ifndef NDEBUG
 void APInt::dump() const
 {
-  std::cerr << "APInt(" << BitWidth << ")=" << std::setbase(16);
+  cerr << "APInt(" << BitWidth << ")=" << std::setbase(16);
   if (isSingleWord())
-    std::cerr << VAL;
+    cerr << VAL;
   else for (unsigned i = getNumWords(); i > 0; i--) {
-    std::cerr << pVal[i-1] << " ";
+    cerr << pVal[i-1] << " ";
   }
-  std::cerr << " (" << this->toString(10, false) << ")\n" << std::setbase(10);
+  cerr << " (" << this->toString(10, false) << ")\n" << std::setbase(10);
 }
 #endif






More information about the llvm-commits mailing list