diff options
author | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-06-20 02:31:03 +0000 |
---|---|---|
committer | Duncan P. N. Exon Smith <dexonsmith@apple.com> | 2014-06-20 02:31:03 +0000 |
commit | 5cf39383da201784a40eb47cfd289cbe98972145 (patch) | |
tree | fefb7039496734a77f67b5cc0f11e828a98a964a /include/llvm/Support | |
parent | 8483dacfd804c71adc73764cee7f1304d1c8977c (diff) | |
download | llvm-5cf39383da201784a40eb47cfd289cbe98972145.tar.gz llvm-5cf39383da201784a40eb47cfd289cbe98972145.tar.bz2 llvm-5cf39383da201784a40eb47cfd289cbe98972145.tar.xz |
Support: Write ScaledNumbers::getAdjusted()
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211336 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/Support')
-rw-r--r-- | include/llvm/Support/ScaledNumber.h | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h index afdc7dc188..54b5386c5a 100644 --- a/include/llvm/Support/ScaledNumber.h +++ b/include/llvm/Support/ScaledNumber.h @@ -22,6 +22,8 @@ #ifndef LLVM_SUPPORT_SCALEDNUMBER_H #define LLVM_SUPPORT_SCALEDNUMBER_H +#include "llvm/Support/MathExtras.h" + #include <cstdint> #include <limits> #include <utility> @@ -50,6 +52,39 @@ inline std::pair<DigitsT, int16_t> getRounded(DigitsT Digits, int16_t Scale, return std::make_pair(DigitsT(1) << (getWidth<DigitsT>() - 1), Scale + 1); return std::make_pair(Digits, Scale); } + +/// \brief Adjust a 64-bit scaled number down to the appropriate width. +/// +/// Adjust a soft float with 64-bits of digits down, keeping as much +/// information as possible, and rounding up on half. +/// +/// \pre Adding 1 to \c Scale will not overflow INT16_MAX. +template <class DigitsT> +inline std::pair<DigitsT, int16_t> getAdjusted(uint64_t Digits, + int16_t Scale = 0) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + const int Width = getWidth<DigitsT>(); + if (Width == 64 || Digits <= std::numeric_limits<DigitsT>::max()) + return std::make_pair(Digits, Scale); + + // Shift right and round. + int Shift = 64 - Width - countLeadingZeros(Digits); + return getRounded<DigitsT>(Digits >> Shift, Scale + Shift, + Digits & (UINT64_C(1) << (Shift - 1))); +} + +/// \brief Convenience helper for adjusting to 32 bits. +inline std::pair<uint32_t, int16_t> getAdjusted32(uint64_t Digits, + int16_t Scale = 0) { + return getAdjusted<uint32_t>(Digits, Scale); +} + +/// \brief Convenience helper for adjusting to 64 bits. +inline std::pair<uint64_t, int16_t> getAdjusted64(uint64_t Digits, + int16_t Scale = 0) { + return getAdjusted<uint64_t>(Digits, Scale); +} } } |