#ifndef COMMON_MATHUTIL_H_
#define COMMON_MATHUTIL_H_
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <limits>
#include <anglebase/numerics/safe_math.h>
#include "common/debug.h"
#include "common/platform.h"
namespace angle
{
CheckedNumeric;
IsValueInRangeForNumericType;
}
namespace gl
{
const unsigned int Float32One = …;
const unsigned short Float16One = …;
template <typename T>
inline constexpr bool isPow2(T x)
{ … }
template <typename T>
inline int log2(T x)
{ … }
inline unsigned int ceilPow2(unsigned int x)
{ … }
template <typename DestT, typename SrcT>
inline DestT clampCast(SrcT value)
{ … }
template <>
inline unsigned int clampCast(bool value)
{ … }
template <>
inline int clampCast(bool value)
{ … }
template <typename T, typename MIN, typename MAX>
inline T clamp(T x, MIN min, MAX max)
{ … }
template <typename T>
T clampForBitCount(T value, size_t bitCount)
{ … }
inline float clamp01(float x)
{ … }
template <const int n>
inline unsigned int unorm(float x)
{ … }
template <typename destType, typename sourceType>
destType bitCast(const sourceType &source)
{ … }
template <typename DestT, typename SrcT>
DestT unsafe_int_to_pointer_cast(SrcT src)
{ … }
template <typename DestT, typename SrcT>
DestT unsafe_pointer_to_int_cast(SrcT src)
{ … }
template <typename T>
static constexpr double normalize(T value)
{ … }
inline unsigned short float32ToFloat16(float fp32)
{ … }
float float16ToFloat32(unsigned short h);
unsigned int convertRGBFloatsTo999E5(float red, float green, float blue);
void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue);
inline unsigned short float32ToFloat11(float fp32)
{ … }
inline unsigned short float32ToFloat10(float fp32)
{ … }
inline float float11ToFloat32(unsigned short fp11)
{ … }
inline float float10ToFloat32(unsigned short fp10)
{ … }
inline float ConvertFixedToFloat(int32_t fixedInput)
{ … }
inline uint32_t ConvertFloatToFixed(float floatInput)
{ … }
template <typename T>
inline float normalizedToFloat(T input)
{ … }
template <unsigned int inputBitCount, typename T>
inline float normalizedToFloat(T input)
{ … }
template <typename T, typename R>
inline R roundToNearest(T input)
{ … }
template <typename T>
inline T floatToNormalized(float input)
{ … }
template <unsigned int outputBitCount, typename T>
inline T floatToNormalized(float input)
{ … }
template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
inline T getShiftedData(T input)
{ … }
template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
inline T shiftData(T input)
{ … }
inline unsigned int CountLeadingZeros(uint32_t x)
{ … }
inline unsigned char average(unsigned char a, unsigned char b)
{ … }
inline signed char average(signed char a, signed char b)
{ … }
inline unsigned short average(unsigned short a, unsigned short b)
{ … }
inline signed short average(signed short a, signed short b)
{ … }
inline unsigned int average(unsigned int a, unsigned int b)
{ … }
inline int average(int a, int b)
{ … }
inline float average(float a, float b)
{ … }
inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
{ … }
inline unsigned int averageFloat11(unsigned int a, unsigned int b)
{ … }
inline unsigned int averageFloat10(unsigned int a, unsigned int b)
{ … }
template <typename T>
class Range
{ … };
RangeI;
RangeUI;
static_assert …;
struct IndexRange
{ … };
inline float Ldexp(float x, int exp)
{ … }
inline uint32_t packSnorm2x16(float f1, float f2)
{ … }
inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
{ … }
inline uint32_t packUnorm2x16(float f1, float f2)
{ … }
inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2)
{ … }
namespace priv
{
inline uint8_t ToPackedUnorm8(float f)
{ … }
inline int8_t ToPackedSnorm8(float f)
{ … }
}
inline uint32_t PackUnorm4x8(float f1, float f2, float f3, float f4)
{ … }
inline void UnpackUnorm4x8(uint32_t u, float *f)
{ … }
inline uint32_t PackSnorm4x8(float f1, float f2, float f3, float f4)
{ … }
inline void UnpackSnorm4x8(uint32_t u, float *f)
{ … }
inline uint32_t packHalf2x16(float f1, float f2)
{ … }
inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
{ … }
inline float sRGBToLinear(uint8_t srgbValue)
{ … }
inline uint8_t linearToSRGB(float value)
{ … }
inline uint32_t BitfieldReverse(uint32_t value)
{ … }
#if defined(_MSC_VER) && !defined(__clang__)
# if defined(_M_IX86) || defined(_M_X64)
namespace priv
{
static const bool kHasPopcnt = [] {
int info[4];
__cpuid(&info[0], 1);
return static_cast<bool>(info[2] & 0x800000);
}();
}
inline int BitCountPolyfill(uint32_t bits)
{
bits = bits - ((bits >> 1) & 0x55555555);
bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
bits = ((bits + (bits >> 4) & 0x0F0F0F0F) * 0x01010101) >> 24;
return static_cast<int>(bits);
}
inline int BitCountPolyfill(uint64_t bits)
{
bits = bits - ((bits >> 1) & 0x5555555555555555ull);
bits = (bits & 0x3333333333333333ull) + ((bits >> 2) & 0x3333333333333333ull);
bits = ((bits + (bits >> 4) & 0x0F0F0F0F0F0F0F0Full) * 0x0101010101010101ull) >> 56;
return static_cast<int>(bits);
}
inline int BitCount(uint32_t bits)
{
if (priv::kHasPopcnt)
{
return static_cast<int>(__popcnt(bits));
}
return BitCountPolyfill(bits);
}
inline int BitCount(uint64_t bits)
{
if (priv::kHasPopcnt)
{
# if defined(_M_X64)
return static_cast<int>(__popcnt64(bits));
# else
return static_cast<int>(__popcnt(static_cast<uint32_t>(bits >> 32)) +
__popcnt(static_cast<uint32_t>(bits)));
# endif
}
return BitCountPolyfill(bits);
}
# elif defined(_M_ARM) || defined(_M_ARM64)
inline int BitCount(uint32_t bits)
{
const uint8x8_t vsum = vcnt_u8(vcreate_u8(static_cast<uint64_t>(bits)));
return static_cast<int>(vget_lane_u32(vpaddl_u16(vpaddl_u8(vsum)), 0));
}
inline int BitCount(uint64_t bits)
{
const uint8x8_t vsum = vcnt_u8(vcreate_u8(bits));
return static_cast<int>(vget_lane_u64(vpaddl_u32(vpaddl_u16(vpaddl_u8(vsum))), 0));
}
# endif
#endif
#if defined(ANGLE_PLATFORM_POSIX) || defined(__clang__) || defined(__GNUC__)
inline int BitCount(uint32_t bits)
{ … }
inline int BitCount(uint64_t bits)
{ … }
#endif
inline int BitCount(uint8_t bits)
{ … }
inline int BitCount(uint16_t bits)
{ … }
#if defined(ANGLE_PLATFORM_WINDOWS)
inline unsigned long ScanForward(uint32_t bits)
{
ASSERT(bits != 0u);
unsigned long firstBitIndex = 0ul;
unsigned char ret = _BitScanForward(&firstBitIndex, bits);
ASSERT(ret != 0u);
return firstBitIndex;
}
inline unsigned long ScanForward(uint64_t bits)
{
ASSERT(bits != 0u);
unsigned long firstBitIndex = 0ul;
# if defined(ANGLE_IS_64_BIT_CPU)
unsigned char ret = _BitScanForward64(&firstBitIndex, bits);
# else
unsigned char ret;
if (static_cast<uint32_t>(bits) == 0)
{
ret = _BitScanForward(&firstBitIndex, static_cast<uint32_t>(bits >> 32));
firstBitIndex += 32ul;
}
else
{
ret = _BitScanForward(&firstBitIndex, static_cast<uint32_t>(bits));
}
# endif
ASSERT(ret != 0u);
return firstBitIndex;
}
inline unsigned long ScanReverse(uint32_t bits)
{
ASSERT(bits != 0u);
unsigned long lastBitIndex = 0ul;
unsigned char ret = _BitScanReverse(&lastBitIndex, bits);
ASSERT(ret != 0u);
return lastBitIndex;
}
inline unsigned long ScanReverse(uint64_t bits)
{
ASSERT(bits != 0u);
unsigned long lastBitIndex = 0ul;
# if defined(ANGLE_IS_64_BIT_CPU)
unsigned char ret = _BitScanReverse64(&lastBitIndex, bits);
# else
unsigned char ret;
if (static_cast<uint32_t>(bits >> 32) == 0)
{
ret = _BitScanReverse(&lastBitIndex, static_cast<uint32_t>(bits));
}
else
{
ret = _BitScanReverse(&lastBitIndex, static_cast<uint32_t>(bits >> 32));
lastBitIndex += 32ul;
}
# endif
ASSERT(ret != 0u);
return lastBitIndex;
}
#endif
#if defined(ANGLE_PLATFORM_POSIX)
inline unsigned long ScanForward(uint32_t bits)
{ … }
inline unsigned long ScanForward(uint64_t bits)
{ … }
inline unsigned long ScanReverse(uint32_t bits)
{ … }
inline unsigned long ScanReverse(uint64_t bits)
{ … }
#endif
inline unsigned long ScanForward(uint8_t bits)
{ … }
inline unsigned long ScanForward(uint16_t bits)
{ … }
inline unsigned long ScanReverse(uint8_t bits)
{ … }
inline unsigned long ScanReverse(uint16_t bits)
{ … }
template <typename T>
int FindLSB(T bits)
{ … }
template <typename T>
int FindMSB(T bits)
{ … }
inline bool isNaN(float f)
{ … }
inline bool isInf(float f)
{ … }
namespace priv
{
template <unsigned int N, unsigned int R>
struct iSquareRoot
{ … };
iSquareRoot<N, N>;
}
template <unsigned int N>
constexpr unsigned int iSquareRoot()
{ … }
template <typename T>
inline T WrappingSum(T lhs, T rhs)
{ … }
template <typename T>
inline T WrappingDiff(T lhs, T rhs)
{ … }
inline int32_t WrappingMul(int32_t lhs, int32_t rhs)
{ … }
inline float scaleScreenDimensionToNdc(float dimensionScreen, float viewportDimension)
{ … }
inline float scaleScreenCoordinateToNdc(float coordinateScreen, float viewportDimension)
{ … }
}
namespace rx
{
template <typename T>
T roundUp(const T value, const T alignment)
{ … }
template <typename T>
constexpr T roundUpPow2(const T value, const T alignment)
{ … }
template <typename T>
constexpr T roundDownPow2(const T value, const T alignment)
{ … }
template <typename T>
angle::CheckedNumeric<T> CheckedRoundUp(const T value, const T alignment)
{ … }
inline constexpr unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
{ … }
#if defined(__has_builtin)
#define ANGLE_HAS_BUILTIN(x) …
#else
#define ANGLE_HAS_BUILTIN …
#endif
#if defined(_MSC_VER)
#define ANGLE_ROTL …
#define ANGLE_ROTL64 …
#define ANGLE_ROTR16 …
#elif defined(__clang__) && ANGLE_HAS_BUILTIN(__builtin_rotateleft32) && \
ANGLE_HAS_BUILTIN(__builtin_rotateleft64) && ANGLE_HAS_BUILTIN(__builtin_rotateright16)
#define ANGLE_ROTL(x, y) …
#define ANGLE_ROTL64(x, y) …
#define ANGLE_ROTR16(x, y) …
#else
inline uint32_t RotL(uint32_t x, int8_t r)
{
return (x << r) | (x >> (32 - r));
}
inline uint64_t RotL64(uint64_t x, int8_t r)
{
return (x << r) | (x >> (64 - r));
}
inline uint16_t RotR16(uint16_t x, int8_t r)
{
return (x >> r) | (x << (16 - r));
}
#define ANGLE_ROTL …
#define ANGLE_ROTL64 …
#define ANGLE_ROTR16 …
#endif
constexpr unsigned int Log2(unsigned int bytes)
{ … }
}
#endif