mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-20 00:51:42 +00:00
This is a breaking change to dependencies that use the static ntcore library. Unless the wpiutil library is also linked, linker errors will result. This does not affect the shared ntcore library.
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
|