[llvm-commits] [llvm] r42984 - /llvm/trunk/lib/Support/APFloat.cpp

Neil Booth neil at daikokuya.co.uk
Mon Oct 15 08:00:55 PDT 2007


Author: neil
Date: Mon Oct 15 10:00:55 2007
New Revision: 42984

URL: http://llvm.org/viewvc/llvm-project?rev=42984&view=rev
Log:
Fast-track obviously over-large and over-small exponents during decimal->
integer conversion.  In some such cases this makes us one or two orders
of magnitude faster than NetBSD's libc.  Glibc seems to have a similar
fast path.

Also, tighten up some upper bounds to save a bit of memory.

Modified:
    llvm/trunk/lib/Support/APFloat.cpp

Modified: llvm/trunk/lib/Support/APFloat.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APFloat.cpp?rev=42984&r1=42983&r2=42984&view=diff

==============================================================================
--- llvm/trunk/lib/Support/APFloat.cpp (original)
+++ llvm/trunk/lib/Support/APFloat.cpp Mon Oct 15 10:00:55 2007
@@ -59,7 +59,7 @@
   /* A tight upper bound on number of parts required to hold the value
      pow(5, power) is
 
-       power * 1024 / (441 * integerPartWidth) + 1
+       power * 815 / (351 * integerPartWidth) + 1
        
      However, whilst the result may require only this many parts,
      because we are multiplying two values to get it, the
@@ -70,8 +70,8 @@
   const unsigned int maxExponent = 16383;
   const unsigned int maxPrecision = 113;
   const unsigned int maxPowerOfFiveExponent = maxExponent + maxPrecision - 1;
-  const unsigned int maxPowerOfFiveParts = 2 + ((maxPowerOfFiveExponent * 1024)
-                                                / (441 * integerPartWidth));
+  const unsigned int maxPowerOfFiveParts = 2 + ((maxPowerOfFiveExponent * 815)
+                                                / (351 * integerPartWidth));
 }
 
 /* Put a bunch of private, handy routines in an anonymous namespace.  */
@@ -226,12 +226,19 @@
        dddd.dddd[eE][+-]ddd
 
      where the decimal point and exponent are optional, fill out the
-     structure D.  If the value is zero, V->firstSigDigit
-     points to a zero, and the return exponent is zero.  */
+     structure D.  Exponent is appropriate if the significand is
+     treated as an integer, and normalizedExponent if the significand
+     is taken to have the decimal point after a single leading
+     non-zero digit.
+
+     If the value is zero, V->firstSigDigit points to a zero, and the
+     return exponent is zero.
+  */
   struct decimalInfo {
     const char *firstSigDigit;
     const char *lastSigDigit;
     int exponent;
+    int normalizedExponent;
   };
 
   void
@@ -243,6 +250,7 @@
 
     D->firstSigDigit = p;
     D->exponent = 0;
+    D->normalizedExponent = 0;
 
     for (;;) {
       if (*p == '.') {
@@ -270,8 +278,10 @@
         while (*p == '0');
       while (*p == '.');
 
-      /* Adjust the specified exponent for any decimal point.  */
+      /* Adjust the exponents for any decimal point.  */
       D->exponent += (dot - p) - (dot > p);
+      D->normalizedExponent = (D->exponent + (p - D->firstSigDigit)
+                               - (dot > D->firstSigDigit && dot < p));
     }
 
     D->lastSigDigit = p;
@@ -2079,19 +2089,45 @@
   /* Scan the text.  */
   interpretDecimal(p, &D);
 
+  /* Handle the quick cases.  First the case of no significant digits,
+     i.e. zero, and then exponents that are obviously too large or too
+     small.  Writing L for log 10 / log 2, a number d.ddddd*10^exp
+     definitely overflows if
+
+           (exp - 1) * L >= maxExponent
+
+     and definitely underflows to zero where
+
+           (exp + 1) * L <= minExponent - precision
+
+     With integer arithmetic the tightest bounds for L are
+
+           93/28 < L < 196/59            [ numerator <= 256 ]
+           42039/12655 < L < 28738/8651  [ numerator <= 65536 ]
+  */
+
   if (*D.firstSigDigit == '0') {
     category = fcZero;
     fs = opOK;
+  } else if ((D.normalizedExponent + 1) * 28738
+             <= 8651 * (semantics->minExponent - (int) semantics->precision)) {
+    /* Underflow to zero and round.  */
+    zeroSignificand();
+    fs = normalize(rounding_mode, lfLessThanHalf);
+  } else if ((D.normalizedExponent - 1) * 42039
+             >= 12655 * semantics->maxExponent) {
+    /* Overflow and round.  */
+    fs = handleOverflow(rounding_mode);
   } else {
     integerPart *decSignificand;
     unsigned int partCount;
 
     /* A tight upper bound on number of bits required to hold an
-       N-digit decimal integer is N * 256 / 77.  Allocate enough space
+       N-digit decimal integer is N * 196 / 59.  Allocate enough space
        to hold the full significand, and an extra part required by
        tcMultiplyPart.  */
     partCount = (D.lastSigDigit - D.firstSigDigit) + 1;
-    partCount = partCountForBits(1 + 256 * partCount / 77);
+    partCount = partCountForBits(1 + 196 * partCount / 59);
     decSignificand = new integerPart[partCount + 1];
     partCount = 0;
 





More information about the llvm-commits mailing list