| //===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file contains some functions that are useful for math stuff. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_SUPPORT_MATHEXTRAS_H |
| #define LLVM_SUPPORT_MATHEXTRAS_H |
| |
| #include "llvm/Compiler.h" |
| #include <cstdint> |
| #include <limits> |
| |
| namespace llvm { |
| /// \brief The behavior an operation has on an input of 0. |
| enum ZeroBehavior { |
| /// \brief The returned value is undefined. |
| ZB_Undefined, |
| /// \brief The returned value is numeric_limits<T>::max() |
| ZB_Max, |
| /// \brief The returned value is numeric_limits<T>::digits |
| ZB_Width |
| }; |
| |
| namespace detail { |
| template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter { |
| static std::size_t count(T Val, ZeroBehavior) { |
| if (!Val) |
| return std::numeric_limits<T>::digits; |
| |
| // Bisection method. |
| std::size_t ZeroBits = 0; |
| for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) { |
| T Tmp = Val >> Shift; |
| if (Tmp) |
| Val = Tmp; |
| else |
| ZeroBits |= Shift; |
| } |
| return ZeroBits; |
| } |
| }; |
| |
| #if __GNUC__ >= 4 || _MSC_VER |
| template <typename T> struct LeadingZerosCounter<T, 4> { |
| static std::size_t count(T Val, ZeroBehavior ZB) { |
| if (ZB != ZB_Undefined && Val == 0) |
| return 32; |
| |
| #if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0) |
| return __builtin_clz(Val); |
| #elif _MSC_VER |
| unsigned long Index; |
| _BitScanReverse(&Index, Val); |
| return Index ^ 31; |
| #endif |
| } |
| }; |
| |
| #if !defined(_MSC_VER) || defined(_M_X64) |
| template <typename T> struct LeadingZerosCounter<T, 8> { |
| static std::size_t count(T Val, ZeroBehavior ZB) { |
| if (ZB != ZB_Undefined && Val == 0) |
| return 64; |
| |
| #if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0) |
| return __builtin_clzll(Val); |
| #elif _MSC_VER |
| unsigned long Index; |
| _BitScanReverse64(&Index, Val); |
| return Index ^ 63; |
| #endif |
| } |
| }; |
| #endif |
| #endif |
| } // namespace detail |
| |
| /// \brief Count number of 0's from the most significant bit to the least |
| /// stopping at the first 1. |
| /// |
| /// Only unsigned integral types are allowed. |
| /// |
| /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are |
| /// valid arguments. |
| template <typename T> |
| std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { |
| static_assert(std::numeric_limits<T>::is_integer && |
| !std::numeric_limits<T>::is_signed, |
| "Only unsigned integral types are allowed."); |
| return detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB); |
| } |
| |
| /// Log2_32 - This function returns the floor log base 2 of the specified value, |
| /// -1 if the value is zero. (32 bit edition.) |
| /// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2 |
| inline unsigned Log2_32(uint32_t Value) { |
| return 31 - countLeadingZeros(Value); |
| } |
| |
| /// Log2_64 - This function returns the floor log base 2 of the specified value, |
| /// -1 if the value is zero. (64 bit edition.) |
| inline unsigned Log2_64(uint64_t Value) { |
| return 63 - countLeadingZeros(Value); |
| } |
| |
| /// Log2_32_Ceil - This function returns the ceil log base 2 of the specified |
| /// value, 32 if the value is zero. (32 bit edition). |
| /// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3 |
| inline unsigned Log2_32_Ceil(uint32_t Value) { |
| return 32 - countLeadingZeros(Value - 1); |
| } |
| |
| /// Log2_64_Ceil - This function returns the ceil log base 2 of the specified |
| /// value, 64 if the value is zero. (64 bit edition.) |
| inline unsigned Log2_64_Ceil(uint64_t Value) { |
| return 64 - countLeadingZeros(Value - 1); |
| } |
| |
| /// BitsToDouble - This function takes a 64-bit integer and returns the bit |
| /// equivalent double. |
| inline double BitsToDouble(uint64_t Bits) { |
| union { |
| uint64_t L; |
| double D; |
| } T; |
| T.L = Bits; |
| return T.D; |
| } |
| |
| /// BitsToFloat - This function takes a 32-bit integer and returns the bit |
| /// equivalent float. |
| inline float BitsToFloat(uint32_t Bits) { |
| union { |
| uint32_t I; |
| float F; |
| } T; |
| T.I = Bits; |
| return T.F; |
| } |
| |
| /// DoubleToBits - This function takes a double and returns the bit |
| /// equivalent 64-bit integer. Note that copying doubles around |
| /// changes the bits of NaNs on some hosts, notably x86, so this |
| /// routine cannot be used if these bits are needed. |
| inline uint64_t DoubleToBits(double Double) { |
| union { |
| uint64_t L; |
| double D; |
| } T; |
| T.D = Double; |
| return T.L; |
| } |
| |
| /// FloatToBits - This function takes a float and returns the bit |
| /// equivalent 32-bit integer. Note that copying floats around |
| /// changes the bits of NaNs on some hosts, notably x86, so this |
| /// routine cannot be used if these bits are needed. |
| inline uint32_t FloatToBits(float Float) { |
| union { |
| uint32_t I; |
| float F; |
| } T; |
| T.F = Float; |
| return T.I; |
| } |
| |
| /// NextPowerOf2 - Returns the next power of two (in 64-bits) |
| /// that is strictly greater than A. Returns zero on overflow. |
| inline uint64_t NextPowerOf2(uint64_t A) { |
| A |= (A >> 1); |
| A |= (A >> 2); |
| A |= (A >> 4); |
| A |= (A >> 8); |
| A |= (A >> 16); |
| A |= (A >> 32); |
| return A + 1; |
| } |
| |
| } // namespace llvm |
| |
| #endif |