190 lines
5.3 KiB
C++
190 lines
5.3 KiB
C++
//===-- 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
|