21#ifndef LLVM_SUPPORT_SCALEDNUMBER_H
22#define LLVM_SUPPORT_SCALEDNUMBER_H
34namespace ScaledNumbers {
43template <
class DigitsT>
inline int getWidth() {
return sizeof(DigitsT) * 8; }
52template <
class DigitsT>
53inline std::pair<DigitsT, int16_t>
getRounded(DigitsT Digits, int16_t Scale,
55 static_assert(!std::numeric_limits<DigitsT>::is_signed,
"expected unsigned");
60 return std::make_pair(DigitsT(1) << (getWidth<DigitsT>() - 1), Scale + 1);
61 return std::make_pair(Digits, Scale);
79template <
class DigitsT>
82 static_assert(!std::numeric_limits<DigitsT>::is_signed,
"expected unsigned");
84 const int Width = getWidth<DigitsT>();
85 if (Width == 64 || Digits <= std::numeric_limits<DigitsT>::max())
86 return std::make_pair(Digits, Scale);
90 return getRounded<DigitsT>(Digits >> Shift, Scale + Shift,
91 Digits & (UINT64_C(1) << (Shift - 1)));
97 return getAdjusted<uint32_t>(Digits, Scale);
103 return getAdjusted<uint64_t>(Digits, Scale);
114template <
class DigitsT>
116 static_assert(!std::numeric_limits<DigitsT>::is_signed,
"expected unsigned");
118 if (getWidth<DigitsT>() <= 32 || (
LHS <= UINT32_MAX &&
RHS <= UINT32_MAX))
155template <
class DigitsT>
156std::pair<DigitsT, int16_t>
getQuotient(DigitsT Dividend, DigitsT Divisor) {
157 static_assert(!std::numeric_limits<DigitsT>::is_signed,
"expected unsigned");
158 static_assert(
sizeof(DigitsT) == 4 ||
sizeof(DigitsT) == 8,
159 "expected 32-bit or 64-bit digits");
163 return std::make_pair(0, 0);
165 return std::make_pair(std::numeric_limits<DigitsT>::max(),
MaxScale);
167 if (getWidth<DigitsT>() == 64)
190template <
class DigitsT>
191inline std::pair<int32_t, int>
getLgImpl(DigitsT Digits, int16_t Scale) {
192 static_assert(!std::numeric_limits<DigitsT>::is_signed,
"expected unsigned");
195 return std::make_pair(INT32_MIN, 0);
198 static_assert(
sizeof(Digits) <=
sizeof(
uint64_t));
202 int32_t Floor = Scale + LocalFloor;
203 if (Digits == UINT64_C(1) << LocalFloor)
204 return std::make_pair(Floor, 0);
208 bool Round = Digits & UINT64_C(1) << (LocalFloor - 1);
209 return std::make_pair(Floor + Round, Round ? 1 : -1);
217template <
class DigitsT> int32_t
getLg(DigitsT Digits, int16_t Scale) {
226template <
class DigitsT> int32_t
getLgFloor(DigitsT Digits, int16_t Scale) {
228 return Lg.first - (Lg.second > 0);
236template <
class DigitsT> int32_t
getLgCeiling(DigitsT Digits, int16_t Scale) {
238 return Lg.first + (Lg.second < 0);
254template <
class DigitsT>
255int compare(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale) {
256 static_assert(!std::numeric_limits<DigitsT>::is_signed,
"expected unsigned");
260 return RDigits ? -1 : 0;
268 return lgL < lgR ? -1 : 1;
272 return compareImpl(LDigits, RDigits, RScale - LScale);
274 return -
compareImpl(RDigits, LDigits, LScale - RScale);
289template <
class DigitsT>
290int16_t
matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits,
292 static_assert(!std::numeric_limits<DigitsT>::is_signed,
"expected unsigned");
296 return matchScales(RDigits, RScale, LDigits, LScale);
299 if (!RDigits || LScale == RScale)
303 int32_t ScaleDiff = int32_t(LScale) - RScale;
304 if (ScaleDiff >= 2 * getWidth<DigitsT>()) {
312 assert(ShiftL < getWidth<DigitsT>() &&
"can't shift more than width");
314 int32_t ShiftR = ScaleDiff - ShiftL;
315 if (ShiftR >= getWidth<DigitsT>()) {
326 assert(LScale == RScale &&
"scales should match");
335template <
class DigitsT>
336std::pair<DigitsT, int16_t>
getSum(DigitsT LDigits, int16_t LScale,
337 DigitsT RDigits, int16_t RScale) {
338 static_assert(!std::numeric_limits<DigitsT>::is_signed,
"expected unsigned");
342 assert(LScale < INT16_MAX &&
"scale too large");
343 assert(RScale < INT16_MAX &&
"scale too large");
346 int16_t Scale =
matchScales(LDigits, LScale, RDigits, RScale);
349 DigitsT Sum = LDigits + RDigits;
351 return std::make_pair(Sum, Scale);
354 DigitsT HighBit = DigitsT(1) << (getWidth<DigitsT>() - 1);
355 return std::make_pair(HighBit | Sum >> 1, Scale + 1);
361 return getSum(LDigits, LScale, RDigits, RScale);
367 return getSum(LDigits, LScale, RDigits, RScale);
375template <
class DigitsT>
377 DigitsT RDigits, int16_t RScale) {
378 static_assert(!std::numeric_limits<DigitsT>::is_signed,
"expected unsigned");
381 const DigitsT SavedRDigits = RDigits;
382 const int16_t SavedRScale = RScale;
386 if (LDigits <= RDigits)
387 return std::make_pair(0, 0);
388 if (RDigits || !SavedRDigits)
389 return std::make_pair(LDigits - RDigits, LScale);
394 const auto RLgFloor =
getLgFloor(SavedRDigits, SavedRScale);
395 if (!
compare(LDigits, LScale, DigitsT(1), RLgFloor + getWidth<DigitsT>()))
396 return std::make_pair(std::numeric_limits<DigitsT>::max(), RLgFloor);
398 return std::make_pair(LDigits, LScale);
429 int Width,
unsigned Precision);
438 return std::make_pair(
N,
false);
440 return std::make_pair(
Unsigned,
true);
445 return IsNeg ? -int64_t(U) : int64_t(U);
498 static_assert(!std::numeric_limits<DigitsT>::is_signed,
499 "only unsigned floats supported");
504 typedef std::numeric_limits<DigitsType> DigitsLimits;
506 static constexpr int Width =
sizeof(
DigitsType) * 8;
507 static_assert(Width <= 64,
"invalid integer width for digits");
517 : Digits(Digits), Scale(Scale) {}
521 : Digits(
X.first), Scale(
X.second) {}
534 return getQuotient(
N,
D);
544 template <
class IntT> IntT
toInt()
const;
549 if (Scale > 0 || Scale <= -Width)
613 std::tie(Digits, Scale) =
621 std::tie(Digits, Scale) =
637 void shiftLeft(int32_t Shift);
638 void shiftRight(int32_t Shift);
676 return ScaledNumbers::compare<uint64_t>(Digits, Scale,
N, 0);
691 static int countLeadingZerosWidth(
DigitsType Digits) {
707 "Shift should be close to 0");
708 auto Adjusted = ScaledNumbers::getAdjusted<DigitsT>(
N, Shift);
721#define SCALED_NUMBER_BOP(op, base) \
722 template <class DigitsT> \
723 ScaledNumber<DigitsT> operator op(const ScaledNumber<DigitsT> &L, \
724 const ScaledNumber<DigitsT> &R) { \
725 return ScaledNumber<DigitsT>(L) base R; \
731#undef SCALED_NUMBER_BOP
733template <
class DigitsT>
734ScaledNumber<DigitsT>
operator<<(
const ScaledNumber<DigitsT> &L,
736 return ScaledNumber<DigitsT>(L) <<= Shift;
739template <
class DigitsT>
745template <
class DigitsT>
747 return X.print(
OS, 10);
750#define SCALED_NUMBER_COMPARE_TO_TYPE(op, T1, T2) \
751 template <class DigitsT> \
752 bool operator op(const ScaledNumber<DigitsT> &L, T1 R) { \
753 return L.compareTo(T2(R)) op 0; \
755 template <class DigitsT> \
756 bool operator op(T1 L, const ScaledNumber<DigitsT> &R) { \
757 return 0 op R.compareTo(T2(L)); \
759#define SCALED_NUMBER_COMPARE_TO(op) \
760 SCALED_NUMBER_COMPARE_TO_TYPE(op, uint64_t, uint64_t) \
761 SCALED_NUMBER_COMPARE_TO_TYPE(op, uint32_t, uint64_t) \
762 SCALED_NUMBER_COMPARE_TO_TYPE(op, int64_t, int64_t) \
763 SCALED_NUMBER_COMPARE_TO_TYPE(op, int32_t, int64_t)
770#undef SCALED_NUMBER_COMPARE_TO
771#undef SCALED_NUMBER_COMPARE_TO_TYPE
773template <
class DigitsT>
775 if (Width == 64 ||
N <= DigitsLimits::max())
776 return (
get(
N) * *
this).template toInt<uint64_t>();
782template <
class DigitsT>
785 typedef std::numeric_limits<IntT> Limits;
788 if (*
this >= Limits::max())
789 return Limits::max();
793 assert(
size_t(Scale) <
sizeof(IntT) * 8);
797 assert(
size_t(-Scale) <
sizeof(IntT) * 8);
803template <
class DigitsT>
812 int32_t Scales = int32_t(Scale) + int32_t(
X.Scale);
815 *
this = getProduct(Digits,
X.Digits);
818 return *
this <<= Scales;
820template <
class DigitsT>
826 return *
this = getLargest();
829 int32_t Scales = int32_t(Scale) - int32_t(
X.Scale);
832 *
this = getQuotient(Digits,
X.Digits);
835 return *
this <<= Scales;
840 assert(Shift != INT32_MIN);
849 if (ScaleShift == Shift)
858 if (Shift > countLeadingZerosWidth(Digits)) {
860 *
this = getLargest();
867template <
class DigitsT>
void ScaledNumber<DigitsT>::shiftRight(int32_t Shift) {
870 assert(Shift != INT32_MIN);
879 if (ScaleShift == Shift)
884 if (Shift >= Width) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
#define SCALED_NUMBER_BOP(op, base)
#define SCALED_NUMBER_COMPARE_TO(op)
static int countLeadingZeros64(uint64_t N)
static int countLeadingZeros32(uint32_t N)
static constexpr int DefaultPrecision
static int64_t joinSigned(uint64_t U, bool IsNeg)
static LLVM_ABI raw_ostream & print(raw_ostream &OS, uint64_t D, int16_t E, int Width, unsigned Precision)
static LLVM_ABI std::string toString(uint64_t D, int16_t E, int Width, unsigned Precision)
static LLVM_ABI void dump(uint64_t D, int16_t E, int Width)
static uint64_t getHalf(uint64_t N)
static std::pair< uint64_t, bool > splitSigned(int64_t N)
Simple representation of a scaled number.
bool operator!=(const ScaledNumber &X) const
raw_ostream & print(raw_ostream &OS, unsigned Precision=DefaultPrecision) const
Print a decimal representation.
ScaledNumber & operator*=(const ScaledNumber &X)
static ScaledNumber getLargest()
ScaledNumber & operator/=(const ScaledNumber &X)
ScaledNumber & operator<<=(int16_t Shift)
int32_t lgFloor() const
The log base 2, rounded towards INT32_MIN.
ScaledNumber inverse() const
bool operator<=(const ScaledNumber &X) const
ScaledNumber & operator+=(const ScaledNumber &X)
bool operator==(const ScaledNumber &X) const
int compare(const ScaledNumber &X) const
std::string toString(unsigned Precision=DefaultPrecision)
Convert to a decimal representation in a string.
static ScaledNumber get(uint64_t N)
static ScaledNumber getZero()
DigitsType getDigits() const
static ScaledNumber getOne()
uint64_t scale(uint64_t N) const
Scale a large number accurately.
bool operator>(const ScaledNumber &X) const
ScaledNumber & operator>>=(int16_t Shift)
static ScaledNumber getFraction(DigitsType N, DigitsType D)
int64_t scaleByInverse(int64_t N) const
constexpr ScaledNumber(DigitsType Digits, int16_t Scale)
int32_t lgCeiling() const
The log base 2, rounded towards INT32_MAX.
uint64_t scaleByInverse(uint64_t N) const
bool operator<(const ScaledNumber &X) const
bool operator>=(const ScaledNumber &X) const
int32_t lg() const
The log base 2, rounded.
int compareTo(uint64_t N) const
static ScaledNumber getInverse(uint64_t N)
IntT toInt() const
Convert to the given integer type.
ScaledNumber & operator-=(const ScaledNumber &X)
int64_t scale(int64_t N) const
int compareTo(int64_t N) const
This class implements an extremely fast bulk output stream that can only output to a stream.
int compare(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale)
Compare two scaled numbers.
LLVM_ABI std::pair< uint64_t, int16_t > divide64(uint64_t Dividend, uint64_t Divisor)
Divide two 64-bit integers to create a 64-bit scaled number.
int32_t getLgFloor(DigitsT Digits, int16_t Scale)
Get the lg floor of a scaled number.
LLVM_ABI std::pair< uint64_t, int16_t > multiply64(uint64_t LHS, uint64_t RHS)
Multiply two 64-bit integers to create a 64-bit scaled number.
std::pair< DigitsT, int16_t > getSum(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale)
Get the sum of two scaled numbers.
std::pair< uint32_t, int16_t > getAdjusted32(uint64_t Digits, int16_t Scale=0)
Convenience helper for adjusting to 32 bits.
const int32_t MinScale
Maximum scale; same as APFloat for easy debug printing.
std::pair< DigitsT, int16_t > getAdjusted(uint64_t Digits, int16_t Scale=0)
Adjust a 64-bit scaled number down to the appropriate width.
std::pair< uint64_t, int16_t > getAdjusted64(uint64_t Digits, int16_t Scale=0)
Convenience helper for adjusting to 64 bits.
std::pair< uint32_t, int16_t > getQuotient32(uint32_t Dividend, uint32_t Divisor)
Convenience helper for 32-bit quotient.
std::pair< int32_t, int > getLgImpl(DigitsT Digits, int16_t Scale)
Implementation of getLg() and friends.
std::pair< uint32_t, int16_t > getSum32(uint32_t LDigits, int16_t LScale, uint32_t RDigits, int16_t RScale)
Convenience helper for 32-bit sum.
std::pair< DigitsT, int16_t > getProduct(DigitsT LHS, DigitsT RHS)
Multiply two 32-bit integers to create a 32-bit scaled number.
std::pair< DigitsT, int16_t > getRounded(DigitsT Digits, int16_t Scale, bool ShouldRound)
Conditionally round up a scaled number.
std::pair< uint32_t, int16_t > getDifference32(uint32_t LDigits, int16_t LScale, uint32_t RDigits, int16_t RScale)
Convenience helper for 32-bit difference.
std::pair< uint64_t, int16_t > getQuotient64(uint64_t Dividend, uint64_t Divisor)
Convenience helper for 64-bit quotient.
std::pair< uint32_t, int16_t > getRounded32(uint32_t Digits, int16_t Scale, bool ShouldRound)
Convenience helper for 32-bit rounding.
int16_t matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits, int16_t &RScale)
Match scales of two numbers.
LLVM_ABI std::pair< uint32_t, int16_t > divide32(uint32_t Dividend, uint32_t Divisor)
Divide two 32-bit integers to create a 32-bit scaled number.
const int32_t MaxScale
Maximum scale; same as APFloat for easy debug printing.
std::pair< uint32_t, int16_t > getProduct32(uint32_t LHS, uint32_t RHS)
Convenience helper for 32-bit product.
int32_t getLg(DigitsT Digits, int16_t Scale)
Get the lg (rounded) of a scaled number.
std::pair< uint64_t, int16_t > getSum64(uint64_t LDigits, int16_t LScale, uint64_t RDigits, int16_t RScale)
Convenience helper for 64-bit sum.
std::pair< DigitsT, int16_t > getDifference(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale)
Get the difference of two scaled numbers.
std::pair< DigitsT, int16_t > getQuotient(DigitsT Dividend, DigitsT Divisor)
Divide two 32-bit numbers to create a 32-bit scaled number.
LLVM_ABI int compareImpl(uint64_t L, uint64_t R, int ScaleDiff)
Implementation for comparing scaled numbers.
int getWidth()
Get the width of a number.
std::pair< uint64_t, int16_t > getDifference64(uint64_t LDigits, int16_t LScale, uint64_t RDigits, int16_t RScale)
Convenience helper for 64-bit difference.
int32_t getLgCeiling(DigitsT Digits, int16_t Scale)
Get the lg ceiling of a scaled number.
std::pair< uint64_t, int16_t > getRounded64(uint64_t Digits, int16_t Scale, bool ShouldRound)
Convenience helper for 64-bit rounding.
std::pair< uint64_t, int16_t > getProduct64(uint64_t LHS, uint64_t RHS)
Convenience helper for 64-bit product.
This is an optimization pass for GlobalISel generic memory operations.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
static lostFraction shiftRight(APFloatBase::integerPart *dst, unsigned int parts, unsigned int bits)
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ScaledNumber< DigitsT > operator>>(const ScaledNumber< DigitsT > &L, int16_t Shift)