File indexing completed on 2026-05-10 08:44:34
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #ifndef LLVM_SUPPORT_SCALEDNUMBER_H
0022 #define LLVM_SUPPORT_SCALEDNUMBER_H
0023
0024 #include "llvm/Support/MathExtras.h"
0025 #include <algorithm>
0026 #include <cstdint>
0027 #include <limits>
0028 #include <string>
0029 #include <tuple>
0030 #include <utility>
0031
0032 namespace llvm {
0033 namespace ScaledNumbers {
0034
0035
0036 const int32_t MaxScale = 16383;
0037
0038
0039 const int32_t MinScale = -16382;
0040
0041
0042 template <class DigitsT> inline int getWidth() { return sizeof(DigitsT) * 8; }
0043
0044
0045
0046
0047
0048
0049
0050
0051 template <class DigitsT>
0052 inline std::pair<DigitsT, int16_t> getRounded(DigitsT Digits, int16_t Scale,
0053 bool ShouldRound) {
0054 static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned");
0055
0056 if (ShouldRound)
0057 if (!++Digits)
0058
0059 return std::make_pair(DigitsT(1) << (getWidth<DigitsT>() - 1), Scale + 1);
0060 return std::make_pair(Digits, Scale);
0061 }
0062
0063
0064 inline std::pair<uint32_t, int16_t> getRounded32(uint32_t Digits, int16_t Scale,
0065 bool ShouldRound) {
0066 return getRounded(Digits, Scale, ShouldRound);
0067 }
0068
0069
0070 inline std::pair<uint64_t, int16_t> getRounded64(uint64_t Digits, int16_t Scale,
0071 bool ShouldRound) {
0072 return getRounded(Digits, Scale, ShouldRound);
0073 }
0074
0075
0076
0077
0078 template <class DigitsT>
0079 inline std::pair<DigitsT, int16_t> getAdjusted(uint64_t Digits,
0080 int16_t Scale = 0) {
0081 static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned");
0082
0083 const int Width = getWidth<DigitsT>();
0084 if (Width == 64 || Digits <= std::numeric_limits<DigitsT>::max())
0085 return std::make_pair(Digits, Scale);
0086
0087
0088 int Shift = llvm::bit_width(Digits) - Width;
0089 return getRounded<DigitsT>(Digits >> Shift, Scale + Shift,
0090 Digits & (UINT64_C(1) << (Shift - 1)));
0091 }
0092
0093
0094 inline std::pair<uint32_t, int16_t> getAdjusted32(uint64_t Digits,
0095 int16_t Scale = 0) {
0096 return getAdjusted<uint32_t>(Digits, Scale);
0097 }
0098
0099
0100 inline std::pair<uint64_t, int16_t> getAdjusted64(uint64_t Digits,
0101 int16_t Scale = 0) {
0102 return getAdjusted<uint64_t>(Digits, Scale);
0103 }
0104
0105
0106
0107
0108 std::pair<uint64_t, int16_t> multiply64(uint64_t LHS, uint64_t RHS);
0109
0110
0111
0112
0113 template <class DigitsT>
0114 inline std::pair<DigitsT, int16_t> getProduct(DigitsT LHS, DigitsT RHS) {
0115 static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned");
0116
0117 if (getWidth<DigitsT>() <= 32 || (LHS <= UINT32_MAX && RHS <= UINT32_MAX))
0118 return getAdjusted<DigitsT>(uint64_t(LHS) * RHS);
0119
0120 return multiply64(LHS, RHS);
0121 }
0122
0123
0124 inline std::pair<uint32_t, int16_t> getProduct32(uint32_t LHS, uint32_t RHS) {
0125 return getProduct(LHS, RHS);
0126 }
0127
0128
0129 inline std::pair<uint64_t, int16_t> getProduct64(uint64_t LHS, uint64_t RHS) {
0130 return getProduct(LHS, RHS);
0131 }
0132
0133
0134
0135
0136
0137
0138 std::pair<uint64_t, int16_t> divide64(uint64_t Dividend, uint64_t Divisor);
0139
0140
0141
0142
0143
0144
0145 std::pair<uint32_t, int16_t> divide32(uint32_t Dividend, uint32_t Divisor);
0146
0147
0148
0149
0150
0151
0152 template <class DigitsT>
0153 std::pair<DigitsT, int16_t> getQuotient(DigitsT Dividend, DigitsT Divisor) {
0154 static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned");
0155 static_assert(sizeof(DigitsT) == 4 || sizeof(DigitsT) == 8,
0156 "expected 32-bit or 64-bit digits");
0157
0158
0159 if (!Dividend)
0160 return std::make_pair(0, 0);
0161 if (!Divisor)
0162 return std::make_pair(std::numeric_limits<DigitsT>::max(), MaxScale);
0163
0164 if (getWidth<DigitsT>() == 64)
0165 return divide64(Dividend, Divisor);
0166 return divide32(Dividend, Divisor);
0167 }
0168
0169
0170 inline std::pair<uint32_t, int16_t> getQuotient32(uint32_t Dividend,
0171 uint32_t Divisor) {
0172 return getQuotient(Dividend, Divisor);
0173 }
0174
0175
0176 inline std::pair<uint64_t, int16_t> getQuotient64(uint64_t Dividend,
0177 uint64_t Divisor) {
0178 return getQuotient(Dividend, Divisor);
0179 }
0180
0181
0182
0183
0184
0185
0186
0187 template <class DigitsT>
0188 inline std::pair<int32_t, int> getLgImpl(DigitsT Digits, int16_t Scale) {
0189 static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned");
0190
0191 if (!Digits)
0192 return std::make_pair(INT32_MIN, 0);
0193
0194
0195 static_assert(sizeof(Digits) <= sizeof(uint64_t));
0196 int32_t LocalFloor = llvm::Log2_64(Digits);
0197
0198
0199 int32_t Floor = Scale + LocalFloor;
0200 if (Digits == UINT64_C(1) << LocalFloor)
0201 return std::make_pair(Floor, 0);
0202
0203
0204 assert(LocalFloor >= 1);
0205 bool Round = Digits & UINT64_C(1) << (LocalFloor - 1);
0206 return std::make_pair(Floor + Round, Round ? 1 : -1);
0207 }
0208
0209
0210
0211
0212
0213
0214 template <class DigitsT> int32_t getLg(DigitsT Digits, int16_t Scale) {
0215 return getLgImpl(Digits, Scale).first;
0216 }
0217
0218
0219
0220
0221
0222
0223 template <class DigitsT> int32_t getLgFloor(DigitsT Digits, int16_t Scale) {
0224 auto Lg = getLgImpl(Digits, Scale);
0225 return Lg.first - (Lg.second > 0);
0226 }
0227
0228
0229
0230
0231
0232
0233 template <class DigitsT> int32_t getLgCeiling(DigitsT Digits, int16_t Scale) {
0234 auto Lg = getLgImpl(Digits, Scale);
0235 return Lg.first + (Lg.second < 0);
0236 }
0237
0238
0239
0240
0241
0242
0243
0244
0245 int compareImpl(uint64_t L, uint64_t R, int ScaleDiff);
0246
0247
0248
0249
0250
0251 template <class DigitsT>
0252 int compare(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale) {
0253 static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned");
0254
0255
0256 if (!LDigits)
0257 return RDigits ? -1 : 0;
0258 if (!RDigits)
0259 return 1;
0260
0261
0262
0263 int32_t lgL = getLgFloor(LDigits, LScale), lgR = getLgFloor(RDigits, RScale);
0264 if (lgL != lgR)
0265 return lgL < lgR ? -1 : 1;
0266
0267
0268 if (LScale < RScale)
0269 return compareImpl(LDigits, RDigits, RScale - LScale);
0270
0271 return -compareImpl(RDigits, LDigits, LScale - RScale);
0272 }
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286 template <class DigitsT>
0287 int16_t matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits,
0288 int16_t &RScale) {
0289 static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned");
0290
0291 if (LScale < RScale)
0292
0293 return matchScales(RDigits, RScale, LDigits, LScale);
0294 if (!LDigits)
0295 return RScale;
0296 if (!RDigits || LScale == RScale)
0297 return LScale;
0298
0299
0300 int32_t ScaleDiff = int32_t(LScale) - RScale;
0301 if (ScaleDiff >= 2 * getWidth<DigitsT>()) {
0302
0303 RDigits = 0;
0304 return LScale;
0305 }
0306
0307
0308 int32_t ShiftL = std::min<int32_t>(llvm::countl_zero(LDigits), ScaleDiff);
0309 assert(ShiftL < getWidth<DigitsT>() && "can't shift more than width");
0310
0311 int32_t ShiftR = ScaleDiff - ShiftL;
0312 if (ShiftR >= getWidth<DigitsT>()) {
0313
0314 RDigits = 0;
0315 return LScale;
0316 }
0317
0318 LDigits <<= ShiftL;
0319 RDigits >>= ShiftR;
0320
0321 LScale -= ShiftL;
0322 RScale += ShiftR;
0323 assert(LScale == RScale && "scales should match");
0324 return LScale;
0325 }
0326
0327
0328
0329
0330
0331
0332 template <class DigitsT>
0333 std::pair<DigitsT, int16_t> getSum(DigitsT LDigits, int16_t LScale,
0334 DigitsT RDigits, int16_t RScale) {
0335 static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned");
0336
0337
0338
0339 assert(LScale < INT16_MAX && "scale too large");
0340 assert(RScale < INT16_MAX && "scale too large");
0341
0342
0343 int16_t Scale = matchScales(LDigits, LScale, RDigits, RScale);
0344
0345
0346 DigitsT Sum = LDigits + RDigits;
0347 if (Sum >= RDigits)
0348 return std::make_pair(Sum, Scale);
0349
0350
0351 DigitsT HighBit = DigitsT(1) << (getWidth<DigitsT>() - 1);
0352 return std::make_pair(HighBit | Sum >> 1, Scale + 1);
0353 }
0354
0355
0356 inline std::pair<uint32_t, int16_t> getSum32(uint32_t LDigits, int16_t LScale,
0357 uint32_t RDigits, int16_t RScale) {
0358 return getSum(LDigits, LScale, RDigits, RScale);
0359 }
0360
0361
0362 inline std::pair<uint64_t, int16_t> getSum64(uint64_t LDigits, int16_t LScale,
0363 uint64_t RDigits, int16_t RScale) {
0364 return getSum(LDigits, LScale, RDigits, RScale);
0365 }
0366
0367
0368
0369
0370
0371
0372 template <class DigitsT>
0373 std::pair<DigitsT, int16_t> getDifference(DigitsT LDigits, int16_t LScale,
0374 DigitsT RDigits, int16_t RScale) {
0375 static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned");
0376
0377
0378 const DigitsT SavedRDigits = RDigits;
0379 const int16_t SavedRScale = RScale;
0380 matchScales(LDigits, LScale, RDigits, RScale);
0381
0382
0383 if (LDigits <= RDigits)
0384 return std::make_pair(0, 0);
0385 if (RDigits || !SavedRDigits)
0386 return std::make_pair(LDigits - RDigits, LScale);
0387
0388
0389
0390
0391 const auto RLgFloor = getLgFloor(SavedRDigits, SavedRScale);
0392 if (!compare(LDigits, LScale, DigitsT(1), RLgFloor + getWidth<DigitsT>()))
0393 return std::make_pair(std::numeric_limits<DigitsT>::max(), RLgFloor);
0394
0395 return std::make_pair(LDigits, LScale);
0396 }
0397
0398
0399 inline std::pair<uint32_t, int16_t> getDifference32(uint32_t LDigits,
0400 int16_t LScale,
0401 uint32_t RDigits,
0402 int16_t RScale) {
0403 return getDifference(LDigits, LScale, RDigits, RScale);
0404 }
0405
0406
0407 inline std::pair<uint64_t, int16_t> getDifference64(uint64_t LDigits,
0408 int16_t LScale,
0409 uint64_t RDigits,
0410 int16_t RScale) {
0411 return getDifference(LDigits, LScale, RDigits, RScale);
0412 }
0413
0414 }
0415 }
0416
0417 namespace llvm {
0418
0419 class raw_ostream;
0420 class ScaledNumberBase {
0421 public:
0422 static constexpr int DefaultPrecision = 10;
0423
0424 static void dump(uint64_t D, int16_t E, int Width);
0425 static raw_ostream &print(raw_ostream &OS, uint64_t D, int16_t E, int Width,
0426 unsigned Precision);
0427 static std::string toString(uint64_t D, int16_t E, int Width,
0428 unsigned Precision);
0429 static int countLeadingZeros32(uint32_t N) { return llvm::countl_zero(N); }
0430 static int countLeadingZeros64(uint64_t N) { return llvm::countl_zero(N); }
0431 static uint64_t getHalf(uint64_t N) { return (N >> 1) + (N & 1); }
0432
0433 static std::pair<uint64_t, bool> splitSigned(int64_t N) {
0434 if (N >= 0)
0435 return std::make_pair(N, false);
0436 uint64_t Unsigned = N == INT64_MIN ? UINT64_C(1) << 63 : uint64_t(-N);
0437 return std::make_pair(Unsigned, true);
0438 }
0439 static int64_t joinSigned(uint64_t U, bool IsNeg) {
0440 if (U > uint64_t(INT64_MAX))
0441 return IsNeg ? INT64_MIN : INT64_MAX;
0442 return IsNeg ? -int64_t(U) : int64_t(U);
0443 }
0444 };
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493 template <class DigitsT> class ScaledNumber : ScaledNumberBase {
0494 public:
0495 static_assert(!std::numeric_limits<DigitsT>::is_signed,
0496 "only unsigned floats supported");
0497
0498 typedef DigitsT DigitsType;
0499
0500 private:
0501 typedef std::numeric_limits<DigitsType> DigitsLimits;
0502
0503 static constexpr int Width = sizeof(DigitsType) * 8;
0504 static_assert(Width <= 64, "invalid integer width for digits");
0505
0506 private:
0507 DigitsType Digits = 0;
0508 int16_t Scale = 0;
0509
0510 public:
0511 ScaledNumber() = default;
0512
0513 constexpr ScaledNumber(DigitsType Digits, int16_t Scale)
0514 : Digits(Digits), Scale(Scale) {}
0515
0516 private:
0517 ScaledNumber(const std::pair<DigitsT, int16_t> &X)
0518 : Digits(X.first), Scale(X.second) {}
0519
0520 public:
0521 static ScaledNumber getZero() { return ScaledNumber(0, 0); }
0522 static ScaledNumber getOne() { return ScaledNumber(1, 0); }
0523 static ScaledNumber getLargest() {
0524 return ScaledNumber(DigitsLimits::max(), ScaledNumbers::MaxScale);
0525 }
0526 static ScaledNumber get(uint64_t N) { return adjustToWidth(N, 0); }
0527 static ScaledNumber getInverse(uint64_t N) {
0528 return get(N).invert();
0529 }
0530 static ScaledNumber getFraction(DigitsType N, DigitsType D) {
0531 return getQuotient(N, D);
0532 }
0533
0534 int16_t getScale() const { return Scale; }
0535 DigitsType getDigits() const { return Digits; }
0536
0537
0538
0539
0540
0541 template <class IntT> IntT toInt() const;
0542
0543 bool isZero() const { return !Digits; }
0544 bool isLargest() const { return *this == getLargest(); }
0545 bool isOne() const {
0546 if (Scale > 0 || Scale <= -Width)
0547 return false;
0548 return Digits == DigitsType(1) << -Scale;
0549 }
0550
0551
0552
0553
0554 int32_t lg() const { return ScaledNumbers::getLg(Digits, Scale); }
0555
0556
0557
0558
0559 int32_t lgFloor() const { return ScaledNumbers::getLgFloor(Digits, Scale); }
0560
0561
0562
0563
0564 int32_t lgCeiling() const {
0565 return ScaledNumbers::getLgCeiling(Digits, Scale);
0566 }
0567
0568 bool operator==(const ScaledNumber &X) const { return compare(X) == 0; }
0569 bool operator<(const ScaledNumber &X) const { return compare(X) < 0; }
0570 bool operator!=(const ScaledNumber &X) const { return compare(X) != 0; }
0571 bool operator>(const ScaledNumber &X) const { return compare(X) > 0; }
0572 bool operator<=(const ScaledNumber &X) const { return compare(X) <= 0; }
0573 bool operator>=(const ScaledNumber &X) const { return compare(X) >= 0; }
0574
0575 bool operator!() const { return isZero(); }
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596 std::string toString(unsigned Precision = DefaultPrecision) {
0597 return ScaledNumberBase::toString(Digits, Scale, Width, Precision);
0598 }
0599
0600
0601
0602
0603 raw_ostream &print(raw_ostream &OS,
0604 unsigned Precision = DefaultPrecision) const {
0605 return ScaledNumberBase::print(OS, Digits, Scale, Width, Precision);
0606 }
0607 void dump() const { return ScaledNumberBase::dump(Digits, Scale, Width); }
0608
0609 ScaledNumber &operator+=(const ScaledNumber &X) {
0610 std::tie(Digits, Scale) =
0611 ScaledNumbers::getSum(Digits, Scale, X.Digits, X.Scale);
0612
0613 if (Scale > ScaledNumbers::MaxScale)
0614 *this = getLargest();
0615 return *this;
0616 }
0617 ScaledNumber &operator-=(const ScaledNumber &X) {
0618 std::tie(Digits, Scale) =
0619 ScaledNumbers::getDifference(Digits, Scale, X.Digits, X.Scale);
0620 return *this;
0621 }
0622 ScaledNumber &operator*=(const ScaledNumber &X);
0623 ScaledNumber &operator/=(const ScaledNumber &X);
0624 ScaledNumber &operator<<=(int16_t Shift) {
0625 shiftLeft(Shift);
0626 return *this;
0627 }
0628 ScaledNumber &operator>>=(int16_t Shift) {
0629 shiftRight(Shift);
0630 return *this;
0631 }
0632
0633 private:
0634 void shiftLeft(int32_t Shift);
0635 void shiftRight(int32_t Shift);
0636
0637
0638
0639
0640
0641
0642
0643
0644 ScaledNumber matchScales(ScaledNumber X) {
0645 ScaledNumbers::matchScales(Digits, Scale, X.Digits, X.Scale);
0646 return X;
0647 }
0648
0649 public:
0650
0651
0652
0653
0654 uint64_t scale(uint64_t N) const;
0655 uint64_t scaleByInverse(uint64_t N) const {
0656
0657
0658 return inverse().scale(N);
0659 }
0660 int64_t scale(int64_t N) const {
0661 std::pair<uint64_t, bool> Unsigned = splitSigned(N);
0662 return joinSigned(scale(Unsigned.first), Unsigned.second);
0663 }
0664 int64_t scaleByInverse(int64_t N) const {
0665 std::pair<uint64_t, bool> Unsigned = splitSigned(N);
0666 return joinSigned(scaleByInverse(Unsigned.first), Unsigned.second);
0667 }
0668
0669 int compare(const ScaledNumber &X) const {
0670 return ScaledNumbers::compare(Digits, Scale, X.Digits, X.Scale);
0671 }
0672 int compareTo(uint64_t N) const {
0673 return ScaledNumbers::compare<uint64_t>(Digits, Scale, N, 0);
0674 }
0675 int compareTo(int64_t N) const { return N < 0 ? 1 : compareTo(uint64_t(N)); }
0676
0677 ScaledNumber &invert() { return *this = ScaledNumber::get(1) / *this; }
0678 ScaledNumber inverse() const { return ScaledNumber(*this).invert(); }
0679
0680 private:
0681 static ScaledNumber getProduct(DigitsType LHS, DigitsType RHS) {
0682 return ScaledNumbers::getProduct(LHS, RHS);
0683 }
0684 static ScaledNumber getQuotient(DigitsType Dividend, DigitsType Divisor) {
0685 return ScaledNumbers::getQuotient(Dividend, Divisor);
0686 }
0687
0688 static int countLeadingZerosWidth(DigitsType Digits) {
0689 if (Width == 64)
0690 return countLeadingZeros64(Digits);
0691 if (Width == 32)
0692 return countLeadingZeros32(Digits);
0693 return countLeadingZeros32(Digits) + Width - 32;
0694 }
0695
0696
0697
0698
0699
0700
0701 static ScaledNumber adjustToWidth(uint64_t N, int32_t Shift) {
0702 assert(Shift >= ScaledNumbers::MinScale && "Shift should be close to 0");
0703 assert(Shift <= ScaledNumbers::MaxScale - 64 &&
0704 "Shift should be close to 0");
0705 auto Adjusted = ScaledNumbers::getAdjusted<DigitsT>(N, Shift);
0706 return Adjusted;
0707 }
0708
0709 static ScaledNumber getRounded(ScaledNumber P, bool Round) {
0710
0711 if (P.isLargest())
0712 return P;
0713
0714 return ScaledNumbers::getRounded(P.Digits, P.Scale, Round);
0715 }
0716 };
0717
0718 #define SCALED_NUMBER_BOP(op, base) \
0719 template <class DigitsT> \
0720 ScaledNumber<DigitsT> operator op(const ScaledNumber<DigitsT> &L, \
0721 const ScaledNumber<DigitsT> &R) { \
0722 return ScaledNumber<DigitsT>(L) base R; \
0723 }
0724 SCALED_NUMBER_BOP(+, += )
0725 SCALED_NUMBER_BOP(-, -= )
0726 SCALED_NUMBER_BOP(*, *= )
0727 SCALED_NUMBER_BOP(/, /= )
0728 #undef SCALED_NUMBER_BOP
0729
0730 template <class DigitsT>
0731 ScaledNumber<DigitsT> operator<<(const ScaledNumber<DigitsT> &L,
0732 int16_t Shift) {
0733 return ScaledNumber<DigitsT>(L) <<= Shift;
0734 }
0735
0736 template <class DigitsT>
0737 ScaledNumber<DigitsT> operator>>(const ScaledNumber<DigitsT> &L,
0738 int16_t Shift) {
0739 return ScaledNumber<DigitsT>(L) >>= Shift;
0740 }
0741
0742 template <class DigitsT>
0743 raw_ostream &operator<<(raw_ostream &OS, const ScaledNumber<DigitsT> &X) {
0744 return X.print(OS, 10);
0745 }
0746
0747 #define SCALED_NUMBER_COMPARE_TO_TYPE(op, T1, T2) \
0748 template <class DigitsT> \
0749 bool operator op(const ScaledNumber<DigitsT> &L, T1 R) { \
0750 return L.compareTo(T2(R)) op 0; \
0751 } \
0752 template <class DigitsT> \
0753 bool operator op(T1 L, const ScaledNumber<DigitsT> &R) { \
0754 return 0 op R.compareTo(T2(L)); \
0755 }
0756 #define SCALED_NUMBER_COMPARE_TO(op) \
0757 SCALED_NUMBER_COMPARE_TO_TYPE(op, uint64_t, uint64_t) \
0758 SCALED_NUMBER_COMPARE_TO_TYPE(op, uint32_t, uint64_t) \
0759 SCALED_NUMBER_COMPARE_TO_TYPE(op, int64_t, int64_t) \
0760 SCALED_NUMBER_COMPARE_TO_TYPE(op, int32_t, int64_t)
0761 SCALED_NUMBER_COMPARE_TO(< )
0762 SCALED_NUMBER_COMPARE_TO(> )
0763 SCALED_NUMBER_COMPARE_TO(== )
0764 SCALED_NUMBER_COMPARE_TO(!= )
0765 SCALED_NUMBER_COMPARE_TO(<= )
0766 SCALED_NUMBER_COMPARE_TO(>= )
0767 #undef SCALED_NUMBER_COMPARE_TO
0768 #undef SCALED_NUMBER_COMPARE_TO_TYPE
0769
0770 template <class DigitsT>
0771 uint64_t ScaledNumber<DigitsT>::scale(uint64_t N) const {
0772 if (Width == 64 || N <= DigitsLimits::max())
0773 return (get(N) * *this).template toInt<uint64_t>();
0774
0775
0776 return ScaledNumber<uint64_t>(Digits, Scale).scale(N);
0777 }
0778
0779 template <class DigitsT>
0780 template <class IntT>
0781 IntT ScaledNumber<DigitsT>::toInt() const {
0782 typedef std::numeric_limits<IntT> Limits;
0783 if (*this < 1)
0784 return 0;
0785 if (*this >= Limits::max())
0786 return Limits::max();
0787
0788 IntT N = Digits;
0789 if (Scale > 0) {
0790 assert(size_t(Scale) < sizeof(IntT) * 8);
0791 return N << Scale;
0792 }
0793 if (Scale < 0) {
0794 assert(size_t(-Scale) < sizeof(IntT) * 8);
0795 return N >> -Scale;
0796 }
0797 return N;
0798 }
0799
0800 template <class DigitsT>
0801 ScaledNumber<DigitsT> &ScaledNumber<DigitsT>::
0802 operator*=(const ScaledNumber &X) {
0803 if (isZero())
0804 return *this;
0805 if (X.isZero())
0806 return *this = X;
0807
0808
0809 int32_t Scales = int32_t(Scale) + int32_t(X.Scale);
0810
0811
0812 *this = getProduct(Digits, X.Digits);
0813
0814
0815 return *this <<= Scales;
0816 }
0817 template <class DigitsT>
0818 ScaledNumber<DigitsT> &ScaledNumber<DigitsT>::
0819 operator/=(const ScaledNumber &X) {
0820 if (isZero())
0821 return *this;
0822 if (X.isZero())
0823 return *this = getLargest();
0824
0825
0826 int32_t Scales = int32_t(Scale) - int32_t(X.Scale);
0827
0828
0829 *this = getQuotient(Digits, X.Digits);
0830
0831
0832 return *this <<= Scales;
0833 }
0834 template <class DigitsT> void ScaledNumber<DigitsT>::shiftLeft(int32_t Shift) {
0835 if (!Shift || isZero())
0836 return;
0837 assert(Shift != INT32_MIN);
0838 if (Shift < 0) {
0839 shiftRight(-Shift);
0840 return;
0841 }
0842
0843
0844 int32_t ScaleShift = std::min(Shift, ScaledNumbers::MaxScale - Scale);
0845 Scale += ScaleShift;
0846 if (ScaleShift == Shift)
0847 return;
0848
0849
0850 if (isLargest())
0851 return;
0852
0853
0854 Shift -= ScaleShift;
0855 if (Shift > countLeadingZerosWidth(Digits)) {
0856
0857 *this = getLargest();
0858 return;
0859 }
0860
0861 Digits <<= Shift;
0862 }
0863
0864 template <class DigitsT> void ScaledNumber<DigitsT>::shiftRight(int32_t Shift) {
0865 if (!Shift || isZero())
0866 return;
0867 assert(Shift != INT32_MIN);
0868 if (Shift < 0) {
0869 shiftLeft(-Shift);
0870 return;
0871 }
0872
0873
0874 int32_t ScaleShift = std::min(Shift, Scale - ScaledNumbers::MinScale);
0875 Scale -= ScaleShift;
0876 if (ScaleShift == Shift)
0877 return;
0878
0879
0880 Shift -= ScaleShift;
0881 if (Shift >= Width) {
0882
0883 *this = getZero();
0884 return;
0885 }
0886
0887 Digits >>= Shift;
0888 }
0889
0890
0891 }
0892
0893 #endif