LLVM API Documentation

ScaledNumber.cpp
Go to the documentation of this file.
00001 //==- lib/Support/ScaledNumber.cpp - Support for scaled numbers -*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // Implementation of some scaled number algorithms.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/Support/ScaledNumber.h"
00015 
00016 #include "llvm/ADT/APFloat.h"
00017 #include "llvm/Support/Debug.h"
00018 
00019 using namespace llvm;
00020 using namespace llvm::ScaledNumbers;
00021 
00022 std::pair<uint64_t, int16_t> ScaledNumbers::multiply64(uint64_t LHS,
00023                                                        uint64_t RHS) {
00024   // Separate into two 32-bit digits (U.L).
00025   auto getU = [](uint64_t N) { return N >> 32; };
00026   auto getL = [](uint64_t N) { return N & UINT32_MAX; };
00027   uint64_t UL = getU(LHS), LL = getL(LHS), UR = getU(RHS), LR = getL(RHS);
00028 
00029   // Compute cross products.
00030   uint64_t P1 = UL * UR, P2 = UL * LR, P3 = LL * UR, P4 = LL * LR;
00031 
00032   // Sum into two 64-bit digits.
00033   uint64_t Upper = P1, Lower = P4;
00034   auto addWithCarry = [&](uint64_t N) {
00035     uint64_t NewLower = Lower + (getL(N) << 32);
00036     Upper += getU(N) + (NewLower < Lower);
00037     Lower = NewLower;
00038   };
00039   addWithCarry(P2);
00040   addWithCarry(P3);
00041 
00042   // Check whether the upper digit is empty.
00043   if (!Upper)
00044     return std::make_pair(Lower, 0);
00045 
00046   // Shift as little as possible to maximize precision.
00047   unsigned LeadingZeros = countLeadingZeros(Upper);
00048   int Shift = 64 - LeadingZeros;
00049   if (LeadingZeros)
00050     Upper = Upper << LeadingZeros | Lower >> Shift;
00051   return getRounded(Upper, Shift,
00052                     Shift && (Lower & UINT64_C(1) << (Shift - 1)));
00053 }
00054 
00055 static uint64_t getHalf(uint64_t N) { return (N >> 1) + (N & 1); }
00056 
00057 std::pair<uint32_t, int16_t> ScaledNumbers::divide32(uint32_t Dividend,
00058                                                      uint32_t Divisor) {
00059   assert(Dividend && "expected non-zero dividend");
00060   assert(Divisor && "expected non-zero divisor");
00061 
00062   // Use 64-bit math and canonicalize the dividend to gain precision.
00063   uint64_t Dividend64 = Dividend;
00064   int Shift = 0;
00065   if (int Zeros = countLeadingZeros(Dividend64)) {
00066     Shift -= Zeros;
00067     Dividend64 <<= Zeros;
00068   }
00069   uint64_t Quotient = Dividend64 / Divisor;
00070   uint64_t Remainder = Dividend64 % Divisor;
00071 
00072   // If Quotient needs to be shifted, leave the rounding to getAdjusted().
00073   if (Quotient > UINT32_MAX)
00074     return getAdjusted<uint32_t>(Quotient, Shift);
00075 
00076   // Round based on the value of the next bit.
00077   return getRounded<uint32_t>(Quotient, Shift, Remainder >= getHalf(Divisor));
00078 }
00079 
00080 std::pair<uint64_t, int16_t> ScaledNumbers::divide64(uint64_t Dividend,
00081                                                      uint64_t Divisor) {
00082   assert(Dividend && "expected non-zero dividend");
00083   assert(Divisor && "expected non-zero divisor");
00084 
00085   // Minimize size of divisor.
00086   int Shift = 0;
00087   if (int Zeros = countTrailingZeros(Divisor)) {
00088     Shift -= Zeros;
00089     Divisor >>= Zeros;
00090   }
00091 
00092   // Check for powers of two.
00093   if (Divisor == 1)
00094     return std::make_pair(Dividend, Shift);
00095 
00096   // Maximize size of dividend.
00097   if (int Zeros = countLeadingZeros(Dividend)) {
00098     Shift -= Zeros;
00099     Dividend <<= Zeros;
00100   }
00101 
00102   // Start with the result of a divide.
00103   uint64_t Quotient = Dividend / Divisor;
00104   Dividend %= Divisor;
00105 
00106   // Continue building the quotient with long division.
00107   while (!(Quotient >> 63) && Dividend) {
00108     // Shift Dividend and check for overflow.
00109     bool IsOverflow = Dividend >> 63;
00110     Dividend <<= 1;
00111     --Shift;
00112 
00113     // Get the next bit of Quotient.
00114     Quotient <<= 1;
00115     if (IsOverflow || Divisor <= Dividend) {
00116       Quotient |= 1;
00117       Dividend -= Divisor;
00118     }
00119   }
00120 
00121   return getRounded(Quotient, Shift, Dividend >= getHalf(Divisor));
00122 }
00123 
00124 int ScaledNumbers::compareImpl(uint64_t L, uint64_t R, int ScaleDiff) {
00125   assert(ScaleDiff >= 0 && "wrong argument order");
00126   assert(ScaleDiff < 64 && "numbers too far apart");
00127 
00128   uint64_t L_adjusted = L >> ScaleDiff;
00129   if (L_adjusted < R)
00130     return -1;
00131   if (L_adjusted > R)
00132     return 1;
00133 
00134   return L > L_adjusted << ScaleDiff ? 1 : 0;
00135 }
00136 
00137 static void appendDigit(std::string &Str, unsigned D) {
00138   assert(D < 10);
00139   Str += '0' + D % 10;
00140 }
00141 
00142 static void appendNumber(std::string &Str, uint64_t N) {
00143   while (N) {
00144     appendDigit(Str, N % 10);
00145     N /= 10;
00146   }
00147 }
00148 
00149 static bool doesRoundUp(char Digit) {
00150   switch (Digit) {
00151   case '5':
00152   case '6':
00153   case '7':
00154   case '8':
00155   case '9':
00156     return true;
00157   default:
00158     return false;
00159   }
00160 }
00161 
00162 static std::string toStringAPFloat(uint64_t D, int E, unsigned Precision) {
00163   assert(E >= ScaledNumbers::MinScale);
00164   assert(E <= ScaledNumbers::MaxScale);
00165 
00166   // Find a new E, but don't let it increase past MaxScale.
00167   int LeadingZeros = ScaledNumberBase::countLeadingZeros64(D);
00168   int NewE = std::min(ScaledNumbers::MaxScale, E + 63 - LeadingZeros);
00169   int Shift = 63 - (NewE - E);
00170   assert(Shift <= LeadingZeros);
00171   assert(Shift == LeadingZeros || NewE == ScaledNumbers::MaxScale);
00172   D <<= Shift;
00173   E = NewE;
00174 
00175   // Check for a denormal.
00176   unsigned AdjustedE = E + 16383;
00177   if (!(D >> 63)) {
00178     assert(E == ScaledNumbers::MaxScale);
00179     AdjustedE = 0;
00180   }
00181 
00182   // Build the float and print it.
00183   uint64_t RawBits[2] = {D, AdjustedE};
00184   APFloat Float(APFloat::x87DoubleExtended, APInt(80, RawBits));
00185   SmallVector<char, 24> Chars;
00186   Float.toString(Chars, Precision, 0);
00187   return std::string(Chars.begin(), Chars.end());
00188 }
00189 
00190 static std::string stripTrailingZeros(const std::string &Float) {
00191   size_t NonZero = Float.find_last_not_of('0');
00192   assert(NonZero != std::string::npos && "no . in floating point string");
00193 
00194   if (Float[NonZero] == '.')
00195     ++NonZero;
00196 
00197   return Float.substr(0, NonZero + 1);
00198 }
00199 
00200 std::string ScaledNumberBase::toString(uint64_t D, int16_t E, int Width,
00201                                        unsigned Precision) {
00202   if (!D)
00203     return "0.0";
00204 
00205   // Canonicalize exponent and digits.
00206   uint64_t Above0 = 0;
00207   uint64_t Below0 = 0;
00208   uint64_t Extra = 0;
00209   int ExtraShift = 0;
00210   if (E == 0) {
00211     Above0 = D;
00212   } else if (E > 0) {
00213     if (int Shift = std::min(int16_t(countLeadingZeros64(D)), E)) {
00214       D <<= Shift;
00215       E -= Shift;
00216 
00217       if (!E)
00218         Above0 = D;
00219     }
00220   } else if (E > -64) {
00221     Above0 = D >> -E;
00222     Below0 = D << (64 + E);
00223   } else if (E == -64) {
00224     // Special case: shift by 64 bits is undefined behavior.
00225     Below0 = D;
00226   } else if (E > -120) {
00227     Below0 = D >> (-E - 64);
00228     Extra = D << (128 + E);
00229     ExtraShift = -64 - E;
00230   }
00231 
00232   // Fall back on APFloat for very small and very large numbers.
00233   if (!Above0 && !Below0)
00234     return toStringAPFloat(D, E, Precision);
00235 
00236   // Append the digits before the decimal.
00237   std::string Str;
00238   size_t DigitsOut = 0;
00239   if (Above0) {
00240     appendNumber(Str, Above0);
00241     DigitsOut = Str.size();
00242   } else
00243     appendDigit(Str, 0);
00244   std::reverse(Str.begin(), Str.end());
00245 
00246   // Return early if there's nothing after the decimal.
00247   if (!Below0)
00248     return Str + ".0";
00249 
00250   // Append the decimal and beyond.
00251   Str += '.';
00252   uint64_t Error = UINT64_C(1) << (64 - Width);
00253 
00254   // We need to shift Below0 to the right to make space for calculating
00255   // digits.  Save the precision we're losing in Extra.
00256   Extra = (Below0 & 0xf) << 56 | (Extra >> 8);
00257   Below0 >>= 4;
00258   size_t SinceDot = 0;
00259   size_t AfterDot = Str.size();
00260   do {
00261     if (ExtraShift) {
00262       --ExtraShift;
00263       Error *= 5;
00264     } else
00265       Error *= 10;
00266 
00267     Below0 *= 10;
00268     Extra *= 10;
00269     Below0 += (Extra >> 60);
00270     Extra = Extra & (UINT64_MAX >> 4);
00271     appendDigit(Str, Below0 >> 60);
00272     Below0 = Below0 & (UINT64_MAX >> 4);
00273     if (DigitsOut || Str.back() != '0')
00274       ++DigitsOut;
00275     ++SinceDot;
00276   } while (Error && (Below0 << 4 | Extra >> 60) >= Error / 2 &&
00277            (!Precision || DigitsOut <= Precision || SinceDot < 2));
00278 
00279   // Return early for maximum precision.
00280   if (!Precision || DigitsOut <= Precision)
00281     return stripTrailingZeros(Str);
00282 
00283   // Find where to truncate.
00284   size_t Truncate =
00285       std::max(Str.size() - (DigitsOut - Precision), AfterDot + 1);
00286 
00287   // Check if there's anything to truncate.
00288   if (Truncate >= Str.size())
00289     return stripTrailingZeros(Str);
00290 
00291   bool Carry = doesRoundUp(Str[Truncate]);
00292   if (!Carry)
00293     return stripTrailingZeros(Str.substr(0, Truncate));
00294 
00295   // Round with the first truncated digit.
00296   for (std::string::reverse_iterator I(Str.begin() + Truncate), E = Str.rend();
00297        I != E; ++I) {
00298     if (*I == '.')
00299       continue;
00300     if (*I == '9') {
00301       *I = '0';
00302       continue;
00303     }
00304 
00305     ++*I;
00306     Carry = false;
00307     break;
00308   }
00309 
00310   // Add "1" in front if we still need to carry.
00311   return stripTrailingZeros(std::string(Carry, '1') + Str.substr(0, Truncate));
00312 }
00313 
00314 raw_ostream &ScaledNumberBase::print(raw_ostream &OS, uint64_t D, int16_t E,
00315                                      int Width, unsigned Precision) {
00316   return OS << toString(D, E, Width, Precision);
00317 }
00318 
00319 void ScaledNumberBase::dump(uint64_t D, int16_t E, int Width) {
00320   print(dbgs(), D, E, Width, 0) << "[" << Width << ":" << D << "*2^" << E
00321                                 << "]";
00322 }