OSDN Git Service

Implement a getBitsNeeded method to determine how many bits are needed to
authorReid Spencer <rspencer@reidspencer.com>
Fri, 13 Apr 2007 19:19:07 +0000 (19:19 +0000)
committerReid Spencer <rspencer@reidspencer.com>
Fri, 13 Apr 2007 19:19:07 +0000 (19:19 +0000)
represent a string in binary form by an APInt.

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

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

index d9470ee..e232550 100644 (file)
@@ -840,6 +840,12 @@ public:
     assert(getActiveBits() <= 64 && "Too many bits for int64_t");
     return int64_t(pVal[0]);
   }
+
+  /// This method determines how many bits are required to hold the APInt
+  /// equivalent of the string given by \p str of length \p slen.
+  /// @brief Get bits required for string value.
+  static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix);
+
   /// countLeadingZeros - This function is an APInt version of the
   /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number
   /// of zeros from the most significant bit to the first one bit.
index 73ee3e1..a35b116 100644 (file)
@@ -659,6 +659,43 @@ APInt& APInt::flip(uint32_t bitPosition) {
   return *this;
 }
 
+uint32_t APInt::getBitsNeeded(const char* str, uint32_t slen, uint8_t radix) {
+  assert(str != 0 && "Invalid value string");
+  assert(slen > 0 && "Invalid string length");
+
+  // Each computation below needs to know if its negative
+  uint32_t isNegative = str[0] == '-';
+  if (isNegative) {
+    slen--;
+    str++;
+  }
+  // For radixes of power-of-two values, the bits required is accurately and
+  // easily computed
+  if (radix == 2)
+    return slen + isNegative;
+  if (radix == 8)
+    return slen * 3 + isNegative;
+  if (radix == 16)
+    return slen * 4 + isNegative;
+
+  // Otherwise it must be radix == 10, the hard case
+  assert(radix == 10 && "Invalid radix");
+
+  // This is grossly inefficient but accurate. We could probably do something
+  // with a computation of roughly slen*64/20 and then adjust by the value of
+  // the first few digits. But, I'm not sure how accurate that could be.
+
+  // Compute a sufficient number of bits that is always large enough but might
+  // be too large. This avoids the assertion in the constructor.
+  uint32_t sufficient = slen*64/18;
+
+  // Convert to the actual binary value.
+  APInt tmp(sufficient, str, slen, radix);
+
+  // Compute how many bits are required.
+  return isNegative + tmp.logBase2();
+}
+
 uint64_t APInt::getHashValue() const {
   // Put the bit width into the low order bits.
   uint64_t hash = BitWidth;