Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 14 | pmbaty | 1 | //===- llvm/Support/ScaledNumber.h - Support for scaled numbers -*- C++ -*-===// |
| 2 | // |
||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
| 6 | // |
||
| 7 | //===----------------------------------------------------------------------===// |
||
| 8 | // |
||
| 9 | // This file contains functions (and a class) useful for working with scaled |
||
| 10 | // numbers -- in particular, pairs of integers where one represents digits and |
||
| 11 | // another represents a scale. The functions are helpers and live in the |
||
| 12 | // namespace ScaledNumbers. The class ScaledNumber is useful for modelling |
||
| 13 | // certain cost metrics that need simple, integer-like semantics that are easy |
||
| 14 | // to reason about. |
||
| 15 | // |
||
| 16 | // These might remind you of soft-floats. If you want one of those, you're in |
||
| 17 | // the wrong place. Look at include/llvm/ADT/APFloat.h instead. |
||
| 18 | // |
||
| 19 | //===----------------------------------------------------------------------===// |
||
| 20 | |||
| 21 | #ifndef LLVM_SUPPORT_SCALEDNUMBER_H |
||
| 22 | #define LLVM_SUPPORT_SCALEDNUMBER_H |
||
| 23 | |||
| 24 | #include "llvm/Support/MathExtras.h" |
||
| 25 | #include <algorithm> |
||
| 26 | #include <cstdint> |
||
| 27 | #include <limits> |
||
| 28 | #include <string> |
||
| 29 | #include <tuple> |
||
| 30 | #include <utility> |
||
| 31 | |||
| 32 | namespace llvm { |
||
| 33 | namespace ScaledNumbers { |
||
| 34 | |||
| 35 | /// Maximum scale; same as APFloat for easy debug printing. |
||
| 36 | const int32_t MaxScale = 16383; |
||
| 37 | |||
| 38 | /// Maximum scale; same as APFloat for easy debug printing. |
||
| 39 | const int32_t MinScale = -16382; |
||
| 40 | |||
| 41 | /// Get the width of a number. |
||
| 42 | template <class DigitsT> inline int getWidth() { return sizeof(DigitsT) * 8; } |
||
| 43 | |||
| 44 | /// Conditionally round up a scaled number. |
||
| 45 | /// |
||
| 46 | /// Given \c Digits and \c Scale, round up iff \c ShouldRound is \c true. |
||
| 47 | /// Always returns \c Scale unless there's an overflow, in which case it |
||
| 48 | /// returns \c 1+Scale. |
||
| 49 | /// |
||
| 50 | /// \pre adding 1 to \c Scale will not overflow INT16_MAX. |
||
| 51 | template <class DigitsT> |
||
| 52 | inline std::pair<DigitsT, int16_t> getRounded(DigitsT Digits, int16_t Scale, |
||
| 53 | bool ShouldRound) { |
||
| 54 | static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); |
||
| 55 | |||
| 56 | if (ShouldRound) |
||
| 57 | if (!++Digits) |
||
| 58 | // Overflow. |
||
| 59 | return std::make_pair(DigitsT(1) << (getWidth<DigitsT>() - 1), Scale + 1); |
||
| 60 | return std::make_pair(Digits, Scale); |
||
| 61 | } |
||
| 62 | |||
| 63 | /// Convenience helper for 32-bit rounding. |
||
| 64 | inline std::pair<uint32_t, int16_t> getRounded32(uint32_t Digits, int16_t Scale, |
||
| 65 | bool ShouldRound) { |
||
| 66 | return getRounded(Digits, Scale, ShouldRound); |
||
| 67 | } |
||
| 68 | |||
| 69 | /// Convenience helper for 64-bit rounding. |
||
| 70 | inline std::pair<uint64_t, int16_t> getRounded64(uint64_t Digits, int16_t Scale, |
||
| 71 | bool ShouldRound) { |
||
| 72 | return getRounded(Digits, Scale, ShouldRound); |
||
| 73 | } |
||
| 74 | |||
| 75 | /// Adjust a 64-bit scaled number down to the appropriate width. |
||
| 76 | /// |
||
| 77 | /// \pre Adding 64 to \c Scale will not overflow INT16_MAX. |
||
| 78 | template <class DigitsT> |
||
| 79 | inline std::pair<DigitsT, int16_t> getAdjusted(uint64_t Digits, |
||
| 80 | int16_t Scale = 0) { |
||
| 81 | static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); |
||
| 82 | |||
| 83 | const int Width = getWidth<DigitsT>(); |
||
| 84 | if (Width == 64 || Digits <= std::numeric_limits<DigitsT>::max()) |
||
| 85 | return std::make_pair(Digits, Scale); |
||
| 86 | |||
| 87 | // Shift right and round. |
||
| 88 | int Shift = 64 - Width - countLeadingZeros(Digits); |
||
| 89 | return getRounded<DigitsT>(Digits >> Shift, Scale + Shift, |
||
| 90 | Digits & (UINT64_C(1) << (Shift - 1))); |
||
| 91 | } |
||
| 92 | |||
| 93 | /// Convenience helper for adjusting to 32 bits. |
||
| 94 | inline std::pair<uint32_t, int16_t> getAdjusted32(uint64_t Digits, |
||
| 95 | int16_t Scale = 0) { |
||
| 96 | return getAdjusted<uint32_t>(Digits, Scale); |
||
| 97 | } |
||
| 98 | |||
| 99 | /// Convenience helper for adjusting to 64 bits. |
||
| 100 | inline std::pair<uint64_t, int16_t> getAdjusted64(uint64_t Digits, |
||
| 101 | int16_t Scale = 0) { |
||
| 102 | return getAdjusted<uint64_t>(Digits, Scale); |
||
| 103 | } |
||
| 104 | |||
| 105 | /// Multiply two 64-bit integers to create a 64-bit scaled number. |
||
| 106 | /// |
||
| 107 | /// Implemented with four 64-bit integer multiplies. |
||
| 108 | std::pair<uint64_t, int16_t> multiply64(uint64_t LHS, uint64_t RHS); |
||
| 109 | |||
| 110 | /// Multiply two 32-bit integers to create a 32-bit scaled number. |
||
| 111 | /// |
||
| 112 | /// Implemented with one 64-bit integer multiply. |
||
| 113 | template <class DigitsT> |
||
| 114 | inline std::pair<DigitsT, int16_t> getProduct(DigitsT LHS, DigitsT RHS) { |
||
| 115 | static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); |
||
| 116 | |||
| 117 | if (getWidth<DigitsT>() <= 32 || (LHS <= UINT32_MAX && RHS <= UINT32_MAX)) |
||
| 118 | return getAdjusted<DigitsT>(uint64_t(LHS) * RHS); |
||
| 119 | |||
| 120 | return multiply64(LHS, RHS); |
||
| 121 | } |
||
| 122 | |||
| 123 | /// Convenience helper for 32-bit product. |
||
| 124 | inline std::pair<uint32_t, int16_t> getProduct32(uint32_t LHS, uint32_t RHS) { |
||
| 125 | return getProduct(LHS, RHS); |
||
| 126 | } |
||
| 127 | |||
| 128 | /// Convenience helper for 64-bit product. |
||
| 129 | inline std::pair<uint64_t, int16_t> getProduct64(uint64_t LHS, uint64_t RHS) { |
||
| 130 | return getProduct(LHS, RHS); |
||
| 131 | } |
||
| 132 | |||
| 133 | /// Divide two 64-bit integers to create a 64-bit scaled number. |
||
| 134 | /// |
||
| 135 | /// Implemented with long division. |
||
| 136 | /// |
||
| 137 | /// \pre \c Dividend and \c Divisor are non-zero. |
||
| 138 | std::pair<uint64_t, int16_t> divide64(uint64_t Dividend, uint64_t Divisor); |
||
| 139 | |||
| 140 | /// Divide two 32-bit integers to create a 32-bit scaled number. |
||
| 141 | /// |
||
| 142 | /// Implemented with one 64-bit integer divide/remainder pair. |
||
| 143 | /// |
||
| 144 | /// \pre \c Dividend and \c Divisor are non-zero. |
||
| 145 | std::pair<uint32_t, int16_t> divide32(uint32_t Dividend, uint32_t Divisor); |
||
| 146 | |||
| 147 | /// Divide two 32-bit numbers to create a 32-bit scaled number. |
||
| 148 | /// |
||
| 149 | /// Implemented with one 64-bit integer divide/remainder pair. |
||
| 150 | /// |
||
| 151 | /// Returns \c (DigitsT_MAX, MaxScale) for divide-by-zero (0 for 0/0). |
||
| 152 | template <class DigitsT> |
||
| 153 | std::pair<DigitsT, int16_t> getQuotient(DigitsT Dividend, DigitsT Divisor) { |
||
| 154 | static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); |
||
| 155 | static_assert(sizeof(DigitsT) == 4 || sizeof(DigitsT) == 8, |
||
| 156 | "expected 32-bit or 64-bit digits"); |
||
| 157 | |||
| 158 | // Check for zero. |
||
| 159 | if (!Dividend) |
||
| 160 | return std::make_pair(0, 0); |
||
| 161 | if (!Divisor) |
||
| 162 | return std::make_pair(std::numeric_limits<DigitsT>::max(), MaxScale); |
||
| 163 | |||
| 164 | if (getWidth<DigitsT>() == 64) |
||
| 165 | return divide64(Dividend, Divisor); |
||
| 166 | return divide32(Dividend, Divisor); |
||
| 167 | } |
||
| 168 | |||
| 169 | /// Convenience helper for 32-bit quotient. |
||
| 170 | inline std::pair<uint32_t, int16_t> getQuotient32(uint32_t Dividend, |
||
| 171 | uint32_t Divisor) { |
||
| 172 | return getQuotient(Dividend, Divisor); |
||
| 173 | } |
||
| 174 | |||
| 175 | /// Convenience helper for 64-bit quotient. |
||
| 176 | inline std::pair<uint64_t, int16_t> getQuotient64(uint64_t Dividend, |
||
| 177 | uint64_t Divisor) { |
||
| 178 | return getQuotient(Dividend, Divisor); |
||
| 179 | } |
||
| 180 | |||
| 181 | /// Implementation of getLg() and friends. |
||
| 182 | /// |
||
| 183 | /// Returns the rounded lg of \c Digits*2^Scale and an int specifying whether |
||
| 184 | /// this was rounded up (1), down (-1), or exact (0). |
||
| 185 | /// |
||
| 186 | /// Returns \c INT32_MIN when \c Digits is zero. |
||
| 187 | template <class DigitsT> |
||
| 188 | inline std::pair<int32_t, int> getLgImpl(DigitsT Digits, int16_t Scale) { |
||
| 189 | static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); |
||
| 190 | |||
| 191 | if (!Digits) |
||
| 192 | return std::make_pair(INT32_MIN, 0); |
||
| 193 | |||
| 194 | // Get the floor of the lg of Digits. |
||
| 195 | int32_t LocalFloor = sizeof(Digits) * 8 - countLeadingZeros(Digits) - 1; |
||
| 196 | |||
| 197 | // Get the actual floor. |
||
| 198 | int32_t Floor = Scale + LocalFloor; |
||
| 199 | if (Digits == UINT64_C(1) << LocalFloor) |
||
| 200 | return std::make_pair(Floor, 0); |
||
| 201 | |||
| 202 | // Round based on the next digit. |
||
| 203 | assert(LocalFloor >= 1); |
||
| 204 | bool Round = Digits & UINT64_C(1) << (LocalFloor - 1); |
||
| 205 | return std::make_pair(Floor + Round, Round ? 1 : -1); |
||
| 206 | } |
||
| 207 | |||
| 208 | /// Get the lg (rounded) of a scaled number. |
||
| 209 | /// |
||
| 210 | /// Get the lg of \c Digits*2^Scale. |
||
| 211 | /// |
||
| 212 | /// Returns \c INT32_MIN when \c Digits is zero. |
||
| 213 | template <class DigitsT> int32_t getLg(DigitsT Digits, int16_t Scale) { |
||
| 214 | return getLgImpl(Digits, Scale).first; |
||
| 215 | } |
||
| 216 | |||
| 217 | /// Get the lg floor of a scaled number. |
||
| 218 | /// |
||
| 219 | /// Get the floor of the lg of \c Digits*2^Scale. |
||
| 220 | /// |
||
| 221 | /// Returns \c INT32_MIN when \c Digits is zero. |
||
| 222 | template <class DigitsT> int32_t getLgFloor(DigitsT Digits, int16_t Scale) { |
||
| 223 | auto Lg = getLgImpl(Digits, Scale); |
||
| 224 | return Lg.first - (Lg.second > 0); |
||
| 225 | } |
||
| 226 | |||
| 227 | /// Get the lg ceiling of a scaled number. |
||
| 228 | /// |
||
| 229 | /// Get the ceiling of the lg of \c Digits*2^Scale. |
||
| 230 | /// |
||
| 231 | /// Returns \c INT32_MIN when \c Digits is zero. |
||
| 232 | template <class DigitsT> int32_t getLgCeiling(DigitsT Digits, int16_t Scale) { |
||
| 233 | auto Lg = getLgImpl(Digits, Scale); |
||
| 234 | return Lg.first + (Lg.second < 0); |
||
| 235 | } |
||
| 236 | |||
| 237 | /// Implementation for comparing scaled numbers. |
||
| 238 | /// |
||
| 239 | /// Compare two 64-bit numbers with different scales. Given that the scale of |
||
| 240 | /// \c L is higher than that of \c R by \c ScaleDiff, compare them. Return -1, |
||
| 241 | /// 1, and 0 for less than, greater than, and equal, respectively. |
||
| 242 | /// |
||
| 243 | /// \pre 0 <= ScaleDiff < 64. |
||
| 244 | int compareImpl(uint64_t L, uint64_t R, int ScaleDiff); |
||
| 245 | |||
| 246 | /// Compare two scaled numbers. |
||
| 247 | /// |
||
| 248 | /// Compare two scaled numbers. Returns 0 for equal, -1 for less than, and 1 |
||
| 249 | /// for greater than. |
||
| 250 | template <class DigitsT> |
||
| 251 | int compare(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale) { |
||
| 252 | static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); |
||
| 253 | |||
| 254 | // Check for zero. |
||
| 255 | if (!LDigits) |
||
| 256 | return RDigits ? -1 : 0; |
||
| 257 | if (!RDigits) |
||
| 258 | return 1; |
||
| 259 | |||
| 260 | // Check for the scale. Use getLgFloor to be sure that the scale difference |
||
| 261 | // is always lower than 64. |
||
| 262 | int32_t lgL = getLgFloor(LDigits, LScale), lgR = getLgFloor(RDigits, RScale); |
||
| 263 | if (lgL != lgR) |
||
| 264 | return lgL < lgR ? -1 : 1; |
||
| 265 | |||
| 266 | // Compare digits. |
||
| 267 | if (LScale < RScale) |
||
| 268 | return compareImpl(LDigits, RDigits, RScale - LScale); |
||
| 269 | |||
| 270 | return -compareImpl(RDigits, LDigits, LScale - RScale); |
||
| 271 | } |
||
| 272 | |||
| 273 | /// Match scales of two numbers. |
||
| 274 | /// |
||
| 275 | /// Given two scaled numbers, match up their scales. Change the digits and |
||
| 276 | /// scales in place. Shift the digits as necessary to form equivalent numbers, |
||
| 277 | /// losing precision only when necessary. |
||
| 278 | /// |
||
| 279 | /// If the output value of \c LDigits (\c RDigits) is \c 0, the output value of |
||
| 280 | /// \c LScale (\c RScale) is unspecified. |
||
| 281 | /// |
||
| 282 | /// As a convenience, returns the matching scale. If the output value of one |
||
| 283 | /// number is zero, returns the scale of the other. If both are zero, which |
||
| 284 | /// scale is returned is unspecified. |
||
| 285 | template <class DigitsT> |
||
| 286 | int16_t matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits, |
||
| 287 | int16_t &RScale) { |
||
| 288 | static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); |
||
| 289 | |||
| 290 | if (LScale < RScale) |
||
| 291 | // Swap arguments. |
||
| 292 | return matchScales(RDigits, RScale, LDigits, LScale); |
||
| 293 | if (!LDigits) |
||
| 294 | return RScale; |
||
| 295 | if (!RDigits || LScale == RScale) |
||
| 296 | return LScale; |
||
| 297 | |||
| 298 | // Now LScale > RScale. Get the difference. |
||
| 299 | int32_t ScaleDiff = int32_t(LScale) - RScale; |
||
| 300 | if (ScaleDiff >= 2 * getWidth<DigitsT>()) { |
||
| 301 | // Don't bother shifting. RDigits will get zero-ed out anyway. |
||
| 302 | RDigits = 0; |
||
| 303 | return LScale; |
||
| 304 | } |
||
| 305 | |||
| 306 | // Shift LDigits left as much as possible, then shift RDigits right. |
||
| 307 | int32_t ShiftL = std::min<int32_t>(countLeadingZeros(LDigits), ScaleDiff); |
||
| 308 | assert(ShiftL < getWidth<DigitsT>() && "can't shift more than width"); |
||
| 309 | |||
| 310 | int32_t ShiftR = ScaleDiff - ShiftL; |
||
| 311 | if (ShiftR >= getWidth<DigitsT>()) { |
||
| 312 | // Don't bother shifting. RDigits will get zero-ed out anyway. |
||
| 313 | RDigits = 0; |
||
| 314 | return LScale; |
||
| 315 | } |
||
| 316 | |||
| 317 | LDigits <<= ShiftL; |
||
| 318 | RDigits >>= ShiftR; |
||
| 319 | |||
| 320 | LScale -= ShiftL; |
||
| 321 | RScale += ShiftR; |
||
| 322 | assert(LScale == RScale && "scales should match"); |
||
| 323 | return LScale; |
||
| 324 | } |
||
| 325 | |||
| 326 | /// Get the sum of two scaled numbers. |
||
| 327 | /// |
||
| 328 | /// Get the sum of two scaled numbers with as much precision as possible. |
||
| 329 | /// |
||
| 330 | /// \pre Adding 1 to \c LScale (or \c RScale) will not overflow INT16_MAX. |
||
| 331 | template <class DigitsT> |
||
| 332 | std::pair<DigitsT, int16_t> getSum(DigitsT LDigits, int16_t LScale, |
||
| 333 | DigitsT RDigits, int16_t RScale) { |
||
| 334 | static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); |
||
| 335 | |||
| 336 | // Check inputs up front. This is only relevant if addition overflows, but |
||
| 337 | // testing here should catch more bugs. |
||
| 338 | assert(LScale < INT16_MAX && "scale too large"); |
||
| 339 | assert(RScale < INT16_MAX && "scale too large"); |
||
| 340 | |||
| 341 | // Normalize digits to match scales. |
||
| 342 | int16_t Scale = matchScales(LDigits, LScale, RDigits, RScale); |
||
| 343 | |||
| 344 | // Compute sum. |
||
| 345 | DigitsT Sum = LDigits + RDigits; |
||
| 346 | if (Sum >= RDigits) |
||
| 347 | return std::make_pair(Sum, Scale); |
||
| 348 | |||
| 349 | // Adjust sum after arithmetic overflow. |
||
| 350 | DigitsT HighBit = DigitsT(1) << (getWidth<DigitsT>() - 1); |
||
| 351 | return std::make_pair(HighBit | Sum >> 1, Scale + 1); |
||
| 352 | } |
||
| 353 | |||
| 354 | /// Convenience helper for 32-bit sum. |
||
| 355 | inline std::pair<uint32_t, int16_t> getSum32(uint32_t LDigits, int16_t LScale, |
||
| 356 | uint32_t RDigits, int16_t RScale) { |
||
| 357 | return getSum(LDigits, LScale, RDigits, RScale); |
||
| 358 | } |
||
| 359 | |||
| 360 | /// Convenience helper for 64-bit sum. |
||
| 361 | inline std::pair<uint64_t, int16_t> getSum64(uint64_t LDigits, int16_t LScale, |
||
| 362 | uint64_t RDigits, int16_t RScale) { |
||
| 363 | return getSum(LDigits, LScale, RDigits, RScale); |
||
| 364 | } |
||
| 365 | |||
| 366 | /// Get the difference of two scaled numbers. |
||
| 367 | /// |
||
| 368 | /// Get LHS minus RHS with as much precision as possible. |
||
| 369 | /// |
||
| 370 | /// Returns \c (0, 0) if the RHS is larger than the LHS. |
||
| 371 | template <class DigitsT> |
||
| 372 | std::pair<DigitsT, int16_t> getDifference(DigitsT LDigits, int16_t LScale, |
||
| 373 | DigitsT RDigits, int16_t RScale) { |
||
| 374 | static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); |
||
| 375 | |||
| 376 | // Normalize digits to match scales. |
||
| 377 | const DigitsT SavedRDigits = RDigits; |
||
| 378 | const int16_t SavedRScale = RScale; |
||
| 379 | matchScales(LDigits, LScale, RDigits, RScale); |
||
| 380 | |||
| 381 | // Compute difference. |
||
| 382 | if (LDigits <= RDigits) |
||
| 383 | return std::make_pair(0, 0); |
||
| 384 | if (RDigits || !SavedRDigits) |
||
| 385 | return std::make_pair(LDigits - RDigits, LScale); |
||
| 386 | |||
| 387 | // Check if RDigits just barely lost its last bit. E.g., for 32-bit: |
||
| 388 | // |
||
| 389 | // 1*2^32 - 1*2^0 == 0xffffffff != 1*2^32 |
||
| 390 | const auto RLgFloor = getLgFloor(SavedRDigits, SavedRScale); |
||
| 391 | if (!compare(LDigits, LScale, DigitsT(1), RLgFloor + getWidth<DigitsT>())) |
||
| 392 | return std::make_pair(std::numeric_limits<DigitsT>::max(), RLgFloor); |
||
| 393 | |||
| 394 | return std::make_pair(LDigits, LScale); |
||
| 395 | } |
||
| 396 | |||
| 397 | /// Convenience helper for 32-bit difference. |
||
| 398 | inline std::pair<uint32_t, int16_t> getDifference32(uint32_t LDigits, |
||
| 399 | int16_t LScale, |
||
| 400 | uint32_t RDigits, |
||
| 401 | int16_t RScale) { |
||
| 402 | return getDifference(LDigits, LScale, RDigits, RScale); |
||
| 403 | } |
||
| 404 | |||
| 405 | /// Convenience helper for 64-bit difference. |
||
| 406 | inline std::pair<uint64_t, int16_t> getDifference64(uint64_t LDigits, |
||
| 407 | int16_t LScale, |
||
| 408 | uint64_t RDigits, |
||
| 409 | int16_t RScale) { |
||
| 410 | return getDifference(LDigits, LScale, RDigits, RScale); |
||
| 411 | } |
||
| 412 | |||
| 413 | } // end namespace ScaledNumbers |
||
| 414 | } // end namespace llvm |
||
| 415 | |||
| 416 | namespace llvm { |
||
| 417 | |||
| 418 | class raw_ostream; |
||
| 419 | class ScaledNumberBase { |
||
| 420 | public: |
||
| 421 | static constexpr int DefaultPrecision = 10; |
||
| 422 | |||
| 423 | static void dump(uint64_t D, int16_t E, int Width); |
||
| 424 | static raw_ostream &print(raw_ostream &OS, uint64_t D, int16_t E, int Width, |
||
| 425 | unsigned Precision); |
||
| 426 | static std::string toString(uint64_t D, int16_t E, int Width, |
||
| 427 | unsigned Precision); |
||
| 428 | static int countLeadingZeros32(uint32_t N) { return countLeadingZeros(N); } |
||
| 429 | static int countLeadingZeros64(uint64_t N) { return countLeadingZeros(N); } |
||
| 430 | static uint64_t getHalf(uint64_t N) { return (N >> 1) + (N & 1); } |
||
| 431 | |||
| 432 | static std::pair<uint64_t, bool> splitSigned(int64_t N) { |
||
| 433 | if (N >= 0) |
||
| 434 | return std::make_pair(N, false); |
||
| 435 | uint64_t Unsigned = N == INT64_MIN ? UINT64_C(1) << 63 : uint64_t(-N); |
||
| 436 | return std::make_pair(Unsigned, true); |
||
| 437 | } |
||
| 438 | static int64_t joinSigned(uint64_t U, bool IsNeg) { |
||
| 439 | if (U > uint64_t(INT64_MAX)) |
||
| 440 | return IsNeg ? INT64_MIN : INT64_MAX; |
||
| 441 | return IsNeg ? -int64_t(U) : int64_t(U); |
||
| 442 | } |
||
| 443 | }; |
||
| 444 | |||
| 445 | /// Simple representation of a scaled number. |
||
| 446 | /// |
||
| 447 | /// ScaledNumber is a number represented by digits and a scale. It uses simple |
||
| 448 | /// saturation arithmetic and every operation is well-defined for every value. |
||
| 449 | /// It's somewhat similar in behaviour to a soft-float, but is *not* a |
||
| 450 | /// replacement for one. If you're doing numerics, look at \a APFloat instead. |
||
| 451 | /// Nevertheless, we've found these semantics useful for modelling certain cost |
||
| 452 | /// metrics. |
||
| 453 | /// |
||
| 454 | /// The number is split into a signed scale and unsigned digits. The number |
||
| 455 | /// represented is \c getDigits()*2^getScale(). In this way, the digits are |
||
| 456 | /// much like the mantissa in the x87 long double, but there is no canonical |
||
| 457 | /// form so the same number can be represented by many bit representations. |
||
| 458 | /// |
||
| 459 | /// ScaledNumber is templated on the underlying integer type for digits, which |
||
| 460 | /// is expected to be unsigned. |
||
| 461 | /// |
||
| 462 | /// Unlike APFloat, ScaledNumber does not model architecture floating point |
||
| 463 | /// behaviour -- while this might make it a little faster and easier to reason |
||
| 464 | /// about, it certainly makes it more dangerous for general numerics. |
||
| 465 | /// |
||
| 466 | /// ScaledNumber is totally ordered. However, there is no canonical form, so |
||
| 467 | /// there are multiple representations of most scalars. E.g.: |
||
| 468 | /// |
||
| 469 | /// ScaledNumber(8u, 0) == ScaledNumber(4u, 1) |
||
| 470 | /// ScaledNumber(4u, 1) == ScaledNumber(2u, 2) |
||
| 471 | /// ScaledNumber(2u, 2) == ScaledNumber(1u, 3) |
||
| 472 | /// |
||
| 473 | /// ScaledNumber implements most arithmetic operations. Precision is kept |
||
| 474 | /// where possible. Uses simple saturation arithmetic, so that operations |
||
| 475 | /// saturate to 0.0 or getLargest() rather than under or overflowing. It has |
||
| 476 | /// some extra arithmetic for unit inversion. 0.0/0.0 is defined to be 0.0. |
||
| 477 | /// Any other division by 0.0 is defined to be getLargest(). |
||
| 478 | /// |
||
| 479 | /// As a convenience for modifying the exponent, left and right shifting are |
||
| 480 | /// both implemented, and both interpret negative shifts as positive shifts in |
||
| 481 | /// the opposite direction. |
||
| 482 | /// |
||
| 483 | /// Scales are limited to the range accepted by x87 long double. This makes |
||
| 484 | /// it trivial to add functionality to convert to APFloat (this is already |
||
| 485 | /// relied on for the implementation of printing). |
||
| 486 | /// |
||
| 487 | /// Possible (and conflicting) future directions: |
||
| 488 | /// |
||
| 489 | /// 1. Turn this into a wrapper around \a APFloat. |
||
| 490 | /// 2. Share the algorithm implementations with \a APFloat. |
||
| 491 | /// 3. Allow \a ScaledNumber to represent a signed number. |
||
| 492 | template <class DigitsT> class ScaledNumber : ScaledNumberBase { |
||
| 493 | public: |
||
| 494 | static_assert(!std::numeric_limits<DigitsT>::is_signed, |
||
| 495 | "only unsigned floats supported"); |
||
| 496 | |||
| 497 | typedef DigitsT DigitsType; |
||
| 498 | |||
| 499 | private: |
||
| 500 | typedef std::numeric_limits<DigitsType> DigitsLimits; |
||
| 501 | |||
| 502 | static constexpr int Width = sizeof(DigitsType) * 8; |
||
| 503 | static_assert(Width <= 64, "invalid integer width for digits"); |
||
| 504 | |||
| 505 | private: |
||
| 506 | DigitsType Digits = 0; |
||
| 507 | int16_t Scale = 0; |
||
| 508 | |||
| 509 | public: |
||
| 510 | ScaledNumber() = default; |
||
| 511 | |||
| 512 | constexpr ScaledNumber(DigitsType Digits, int16_t Scale) |
||
| 513 | : Digits(Digits), Scale(Scale) {} |
||
| 514 | |||
| 515 | private: |
||
| 516 | ScaledNumber(const std::pair<DigitsT, int16_t> &X) |
||
| 517 | : Digits(X.first), Scale(X.second) {} |
||
| 518 | |||
| 519 | public: |
||
| 520 | static ScaledNumber getZero() { return ScaledNumber(0, 0); } |
||
| 521 | static ScaledNumber getOne() { return ScaledNumber(1, 0); } |
||
| 522 | static ScaledNumber getLargest() { |
||
| 523 | return ScaledNumber(DigitsLimits::max(), ScaledNumbers::MaxScale); |
||
| 524 | } |
||
| 525 | static ScaledNumber get(uint64_t N) { return adjustToWidth(N, 0); } |
||
| 526 | static ScaledNumber getInverse(uint64_t N) { |
||
| 527 | return get(N).invert(); |
||
| 528 | } |
||
| 529 | static ScaledNumber getFraction(DigitsType N, DigitsType D) { |
||
| 530 | return getQuotient(N, D); |
||
| 531 | } |
||
| 532 | |||
| 533 | int16_t getScale() const { return Scale; } |
||
| 534 | DigitsType getDigits() const { return Digits; } |
||
| 535 | |||
| 536 | /// Convert to the given integer type. |
||
| 537 | /// |
||
| 538 | /// Convert to \c IntT using simple saturating arithmetic, truncating if |
||
| 539 | /// necessary. |
||
| 540 | template <class IntT> IntT toInt() const; |
||
| 541 | |||
| 542 | bool isZero() const { return !Digits; } |
||
| 543 | bool isLargest() const { return *this == getLargest(); } |
||
| 544 | bool isOne() const { |
||
| 545 | if (Scale > 0 || Scale <= -Width) |
||
| 546 | return false; |
||
| 547 | return Digits == DigitsType(1) << -Scale; |
||
| 548 | } |
||
| 549 | |||
| 550 | /// The log base 2, rounded. |
||
| 551 | /// |
||
| 552 | /// Get the lg of the scalar. lg 0 is defined to be INT32_MIN. |
||
| 553 | int32_t lg() const { return ScaledNumbers::getLg(Digits, Scale); } |
||
| 554 | |||
| 555 | /// The log base 2, rounded towards INT32_MIN. |
||
| 556 | /// |
||
| 557 | /// Get the lg floor. lg 0 is defined to be INT32_MIN. |
||
| 558 | int32_t lgFloor() const { return ScaledNumbers::getLgFloor(Digits, Scale); } |
||
| 559 | |||
| 560 | /// The log base 2, rounded towards INT32_MAX. |
||
| 561 | /// |
||
| 562 | /// Get the lg ceiling. lg 0 is defined to be INT32_MIN. |
||
| 563 | int32_t lgCeiling() const { |
||
| 564 | return ScaledNumbers::getLgCeiling(Digits, Scale); |
||
| 565 | } |
||
| 566 | |||
| 567 | bool operator==(const ScaledNumber &X) const { return compare(X) == 0; } |
||
| 568 | bool operator<(const ScaledNumber &X) const { return compare(X) < 0; } |
||
| 569 | bool operator!=(const ScaledNumber &X) const { return compare(X) != 0; } |
||
| 570 | bool operator>(const ScaledNumber &X) const { return compare(X) > 0; } |
||
| 571 | bool operator<=(const ScaledNumber &X) const { return compare(X) <= 0; } |
||
| 572 | bool operator>=(const ScaledNumber &X) const { return compare(X) >= 0; } |
||
| 573 | |||
| 574 | bool operator!() const { return isZero(); } |
||
| 575 | |||
| 576 | /// Convert to a decimal representation in a string. |
||
| 577 | /// |
||
| 578 | /// Convert to a string. Uses scientific notation for very large/small |
||
| 579 | /// numbers. Scientific notation is used roughly for numbers outside of the |
||
| 580 | /// range 2^-64 through 2^64. |
||
| 581 | /// |
||
| 582 | /// \c Precision indicates the number of decimal digits of precision to use; |
||
| 583 | /// 0 requests the maximum available. |
||
| 584 | /// |
||
| 585 | /// As a special case to make debugging easier, if the number is small enough |
||
| 586 | /// to convert without scientific notation and has more than \c Precision |
||
| 587 | /// digits before the decimal place, it's printed accurately to the first |
||
| 588 | /// digit past zero. E.g., assuming 10 digits of precision: |
||
| 589 | /// |
||
| 590 | /// 98765432198.7654... => 98765432198.8 |
||
| 591 | /// 8765432198.7654... => 8765432198.8 |
||
| 592 | /// 765432198.7654... => 765432198.8 |
||
| 593 | /// 65432198.7654... => 65432198.77 |
||
| 594 | /// 5432198.7654... => 5432198.765 |
||
| 595 | std::string toString(unsigned Precision = DefaultPrecision) { |
||
| 596 | return ScaledNumberBase::toString(Digits, Scale, Width, Precision); |
||
| 597 | } |
||
| 598 | |||
| 599 | /// Print a decimal representation. |
||
| 600 | /// |
||
| 601 | /// Print a string. See toString for documentation. |
||
| 602 | raw_ostream &print(raw_ostream &OS, |
||
| 603 | unsigned Precision = DefaultPrecision) const { |
||
| 604 | return ScaledNumberBase::print(OS, Digits, Scale, Width, Precision); |
||
| 605 | } |
||
| 606 | void dump() const { return ScaledNumberBase::dump(Digits, Scale, Width); } |
||
| 607 | |||
| 608 | ScaledNumber &operator+=(const ScaledNumber &X) { |
||
| 609 | std::tie(Digits, Scale) = |
||
| 610 | ScaledNumbers::getSum(Digits, Scale, X.Digits, X.Scale); |
||
| 611 | // Check for exponent past MaxScale. |
||
| 612 | if (Scale > ScaledNumbers::MaxScale) |
||
| 613 | *this = getLargest(); |
||
| 614 | return *this; |
||
| 615 | } |
||
| 616 | ScaledNumber &operator-=(const ScaledNumber &X) { |
||
| 617 | std::tie(Digits, Scale) = |
||
| 618 | ScaledNumbers::getDifference(Digits, Scale, X.Digits, X.Scale); |
||
| 619 | return *this; |
||
| 620 | } |
||
| 621 | ScaledNumber &operator*=(const ScaledNumber &X); |
||
| 622 | ScaledNumber &operator/=(const ScaledNumber &X); |
||
| 623 | ScaledNumber &operator<<=(int16_t Shift) { |
||
| 624 | shiftLeft(Shift); |
||
| 625 | return *this; |
||
| 626 | } |
||
| 627 | ScaledNumber &operator>>=(int16_t Shift) { |
||
| 628 | shiftRight(Shift); |
||
| 629 | return *this; |
||
| 630 | } |
||
| 631 | |||
| 632 | private: |
||
| 633 | void shiftLeft(int32_t Shift); |
||
| 634 | void shiftRight(int32_t Shift); |
||
| 635 | |||
| 636 | /// Adjust two floats to have matching exponents. |
||
| 637 | /// |
||
| 638 | /// Adjust \c this and \c X to have matching exponents. Returns the new \c X |
||
| 639 | /// by value. Does nothing if \a isZero() for either. |
||
| 640 | /// |
||
| 641 | /// The value that compares smaller will lose precision, and possibly become |
||
| 642 | /// \a isZero(). |
||
| 643 | ScaledNumber matchScales(ScaledNumber X) { |
||
| 644 | ScaledNumbers::matchScales(Digits, Scale, X.Digits, X.Scale); |
||
| 645 | return X; |
||
| 646 | } |
||
| 647 | |||
| 648 | public: |
||
| 649 | /// Scale a large number accurately. |
||
| 650 | /// |
||
| 651 | /// Scale N (multiply it by this). Uses full precision multiplication, even |
||
| 652 | /// if Width is smaller than 64, so information is not lost. |
||
| 653 | uint64_t scale(uint64_t N) const; |
||
| 654 | uint64_t scaleByInverse(uint64_t N) const { |
||
| 655 | // TODO: implement directly, rather than relying on inverse. Inverse is |
||
| 656 | // expensive. |
||
| 657 | return inverse().scale(N); |
||
| 658 | } |
||
| 659 | int64_t scale(int64_t N) const { |
||
| 660 | std::pair<uint64_t, bool> Unsigned = splitSigned(N); |
||
| 661 | return joinSigned(scale(Unsigned.first), Unsigned.second); |
||
| 662 | } |
||
| 663 | int64_t scaleByInverse(int64_t N) const { |
||
| 664 | std::pair<uint64_t, bool> Unsigned = splitSigned(N); |
||
| 665 | return joinSigned(scaleByInverse(Unsigned.first), Unsigned.second); |
||
| 666 | } |
||
| 667 | |||
| 668 | int compare(const ScaledNumber &X) const { |
||
| 669 | return ScaledNumbers::compare(Digits, Scale, X.Digits, X.Scale); |
||
| 670 | } |
||
| 671 | int compareTo(uint64_t N) const { |
||
| 672 | return ScaledNumbers::compare<uint64_t>(Digits, Scale, N, 0); |
||
| 673 | } |
||
| 674 | int compareTo(int64_t N) const { return N < 0 ? 1 : compareTo(uint64_t(N)); } |
||
| 675 | |||
| 676 | ScaledNumber &invert() { return *this = ScaledNumber::get(1) / *this; } |
||
| 677 | ScaledNumber inverse() const { return ScaledNumber(*this).invert(); } |
||
| 678 | |||
| 679 | private: |
||
| 680 | static ScaledNumber getProduct(DigitsType LHS, DigitsType RHS) { |
||
| 681 | return ScaledNumbers::getProduct(LHS, RHS); |
||
| 682 | } |
||
| 683 | static ScaledNumber getQuotient(DigitsType Dividend, DigitsType Divisor) { |
||
| 684 | return ScaledNumbers::getQuotient(Dividend, Divisor); |
||
| 685 | } |
||
| 686 | |||
| 687 | static int countLeadingZerosWidth(DigitsType Digits) { |
||
| 688 | if (Width == 64) |
||
| 689 | return countLeadingZeros64(Digits); |
||
| 690 | if (Width == 32) |
||
| 691 | return countLeadingZeros32(Digits); |
||
| 692 | return countLeadingZeros32(Digits) + Width - 32; |
||
| 693 | } |
||
| 694 | |||
| 695 | /// Adjust a number to width, rounding up if necessary. |
||
| 696 | /// |
||
| 697 | /// Should only be called for \c Shift close to zero. |
||
| 698 | /// |
||
| 699 | /// \pre Shift >= MinScale && Shift + 64 <= MaxScale. |
||
| 700 | static ScaledNumber adjustToWidth(uint64_t N, int32_t Shift) { |
||
| 701 | assert(Shift >= ScaledNumbers::MinScale && "Shift should be close to 0"); |
||
| 702 | assert(Shift <= ScaledNumbers::MaxScale - 64 && |
||
| 703 | "Shift should be close to 0"); |
||
| 704 | auto Adjusted = ScaledNumbers::getAdjusted<DigitsT>(N, Shift); |
||
| 705 | return Adjusted; |
||
| 706 | } |
||
| 707 | |||
| 708 | static ScaledNumber getRounded(ScaledNumber P, bool Round) { |
||
| 709 | // Saturate. |
||
| 710 | if (P.isLargest()) |
||
| 711 | return P; |
||
| 712 | |||
| 713 | return ScaledNumbers::getRounded(P.Digits, P.Scale, Round); |
||
| 714 | } |
||
| 715 | }; |
||
| 716 | |||
| 717 | #define SCALED_NUMBER_BOP(op, base) \ |
||
| 718 | template <class DigitsT> \ |
||
| 719 | ScaledNumber<DigitsT> operator op(const ScaledNumber<DigitsT> &L, \ |
||
| 720 | const ScaledNumber<DigitsT> &R) { \ |
||
| 721 | return ScaledNumber<DigitsT>(L) base R; \ |
||
| 722 | } |
||
| 723 | SCALED_NUMBER_BOP(+, += ) |
||
| 724 | SCALED_NUMBER_BOP(-, -= ) |
||
| 725 | SCALED_NUMBER_BOP(*, *= ) |
||
| 726 | SCALED_NUMBER_BOP(/, /= ) |
||
| 727 | #undef SCALED_NUMBER_BOP |
||
| 728 | |||
| 729 | template <class DigitsT> |
||
| 730 | ScaledNumber<DigitsT> operator<<(const ScaledNumber<DigitsT> &L, |
||
| 731 | int16_t Shift) { |
||
| 732 | return ScaledNumber<DigitsT>(L) <<= Shift; |
||
| 733 | } |
||
| 734 | |||
| 735 | template <class DigitsT> |
||
| 736 | ScaledNumber<DigitsT> operator>>(const ScaledNumber<DigitsT> &L, |
||
| 737 | int16_t Shift) { |
||
| 738 | return ScaledNumber<DigitsT>(L) >>= Shift; |
||
| 739 | } |
||
| 740 | |||
| 741 | template <class DigitsT> |
||
| 742 | raw_ostream &operator<<(raw_ostream &OS, const ScaledNumber<DigitsT> &X) { |
||
| 743 | return X.print(OS, 10); |
||
| 744 | } |
||
| 745 | |||
| 746 | #define SCALED_NUMBER_COMPARE_TO_TYPE(op, T1, T2) \ |
||
| 747 | template <class DigitsT> \ |
||
| 748 | bool operator op(const ScaledNumber<DigitsT> &L, T1 R) { \ |
||
| 749 | return L.compareTo(T2(R)) op 0; \ |
||
| 750 | } \ |
||
| 751 | template <class DigitsT> \ |
||
| 752 | bool operator op(T1 L, const ScaledNumber<DigitsT> &R) { \ |
||
| 753 | return 0 op R.compareTo(T2(L)); \ |
||
| 754 | } |
||
| 755 | #define SCALED_NUMBER_COMPARE_TO(op) \ |
||
| 756 | SCALED_NUMBER_COMPARE_TO_TYPE(op, uint64_t, uint64_t) \ |
||
| 757 | SCALED_NUMBER_COMPARE_TO_TYPE(op, uint32_t, uint64_t) \ |
||
| 758 | SCALED_NUMBER_COMPARE_TO_TYPE(op, int64_t, int64_t) \ |
||
| 759 | SCALED_NUMBER_COMPARE_TO_TYPE(op, int32_t, int64_t) |
||
| 760 | SCALED_NUMBER_COMPARE_TO(< ) |
||
| 761 | SCALED_NUMBER_COMPARE_TO(> ) |
||
| 762 | SCALED_NUMBER_COMPARE_TO(== ) |
||
| 763 | SCALED_NUMBER_COMPARE_TO(!= ) |
||
| 764 | SCALED_NUMBER_COMPARE_TO(<= ) |
||
| 765 | SCALED_NUMBER_COMPARE_TO(>= ) |
||
| 766 | #undef SCALED_NUMBER_COMPARE_TO |
||
| 767 | #undef SCALED_NUMBER_COMPARE_TO_TYPE |
||
| 768 | |||
| 769 | template <class DigitsT> |
||
| 770 | uint64_t ScaledNumber<DigitsT>::scale(uint64_t N) const { |
||
| 771 | if (Width == 64 || N <= DigitsLimits::max()) |
||
| 772 | return (get(N) * *this).template toInt<uint64_t>(); |
||
| 773 | |||
| 774 | // Defer to the 64-bit version. |
||
| 775 | return ScaledNumber<uint64_t>(Digits, Scale).scale(N); |
||
| 776 | } |
||
| 777 | |||
| 778 | template <class DigitsT> |
||
| 779 | template <class IntT> |
||
| 780 | IntT ScaledNumber<DigitsT>::toInt() const { |
||
| 781 | typedef std::numeric_limits<IntT> Limits; |
||
| 782 | if (*this < 1) |
||
| 783 | return 0; |
||
| 784 | if (*this >= Limits::max()) |
||
| 785 | return Limits::max(); |
||
| 786 | |||
| 787 | IntT N = Digits; |
||
| 788 | if (Scale > 0) { |
||
| 789 | assert(size_t(Scale) < sizeof(IntT) * 8); |
||
| 790 | return N << Scale; |
||
| 791 | } |
||
| 792 | if (Scale < 0) { |
||
| 793 | assert(size_t(-Scale) < sizeof(IntT) * 8); |
||
| 794 | return N >> -Scale; |
||
| 795 | } |
||
| 796 | return N; |
||
| 797 | } |
||
| 798 | |||
| 799 | template <class DigitsT> |
||
| 800 | ScaledNumber<DigitsT> &ScaledNumber<DigitsT>:: |
||
| 801 | operator*=(const ScaledNumber &X) { |
||
| 802 | if (isZero()) |
||
| 803 | return *this; |
||
| 804 | if (X.isZero()) |
||
| 805 | return *this = X; |
||
| 806 | |||
| 807 | // Save the exponents. |
||
| 808 | int32_t Scales = int32_t(Scale) + int32_t(X.Scale); |
||
| 809 | |||
| 810 | // Get the raw product. |
||
| 811 | *this = getProduct(Digits, X.Digits); |
||
| 812 | |||
| 813 | // Combine with exponents. |
||
| 814 | return *this <<= Scales; |
||
| 815 | } |
||
| 816 | template <class DigitsT> |
||
| 817 | ScaledNumber<DigitsT> &ScaledNumber<DigitsT>:: |
||
| 818 | operator/=(const ScaledNumber &X) { |
||
| 819 | if (isZero()) |
||
| 820 | return *this; |
||
| 821 | if (X.isZero()) |
||
| 822 | return *this = getLargest(); |
||
| 823 | |||
| 824 | // Save the exponents. |
||
| 825 | int32_t Scales = int32_t(Scale) - int32_t(X.Scale); |
||
| 826 | |||
| 827 | // Get the raw quotient. |
||
| 828 | *this = getQuotient(Digits, X.Digits); |
||
| 829 | |||
| 830 | // Combine with exponents. |
||
| 831 | return *this <<= Scales; |
||
| 832 | } |
||
| 833 | template <class DigitsT> void ScaledNumber<DigitsT>::shiftLeft(int32_t Shift) { |
||
| 834 | if (!Shift || isZero()) |
||
| 835 | return; |
||
| 836 | assert(Shift != INT32_MIN); |
||
| 837 | if (Shift < 0) { |
||
| 838 | shiftRight(-Shift); |
||
| 839 | return; |
||
| 840 | } |
||
| 841 | |||
| 842 | // Shift as much as we can in the exponent. |
||
| 843 | int32_t ScaleShift = std::min(Shift, ScaledNumbers::MaxScale - Scale); |
||
| 844 | Scale += ScaleShift; |
||
| 845 | if (ScaleShift == Shift) |
||
| 846 | return; |
||
| 847 | |||
| 848 | // Check this late, since it's rare. |
||
| 849 | if (isLargest()) |
||
| 850 | return; |
||
| 851 | |||
| 852 | // Shift the digits themselves. |
||
| 853 | Shift -= ScaleShift; |
||
| 854 | if (Shift > countLeadingZerosWidth(Digits)) { |
||
| 855 | // Saturate. |
||
| 856 | *this = getLargest(); |
||
| 857 | return; |
||
| 858 | } |
||
| 859 | |||
| 860 | Digits <<= Shift; |
||
| 861 | } |
||
| 862 | |||
| 863 | template <class DigitsT> void ScaledNumber<DigitsT>::shiftRight(int32_t Shift) { |
||
| 864 | if (!Shift || isZero()) |
||
| 865 | return; |
||
| 866 | assert(Shift != INT32_MIN); |
||
| 867 | if (Shift < 0) { |
||
| 868 | shiftLeft(-Shift); |
||
| 869 | return; |
||
| 870 | } |
||
| 871 | |||
| 872 | // Shift as much as we can in the exponent. |
||
| 873 | int32_t ScaleShift = std::min(Shift, Scale - ScaledNumbers::MinScale); |
||
| 874 | Scale -= ScaleShift; |
||
| 875 | if (ScaleShift == Shift) |
||
| 876 | return; |
||
| 877 | |||
| 878 | // Shift the digits themselves. |
||
| 879 | Shift -= ScaleShift; |
||
| 880 | if (Shift >= Width) { |
||
| 881 | // Saturate. |
||
| 882 | *this = getZero(); |
||
| 883 | return; |
||
| 884 | } |
||
| 885 | |||
| 886 | Digits >>= Shift; |
||
| 887 | } |
||
| 888 | |||
| 889 | |||
| 890 | } // end namespace llvm |
||
| 891 | |||
| 892 | #endif // LLVM_SUPPORT_SCALEDNUMBER_H |