chromium/third_party/angle/src/common/mathutil.h

//
// Copyright 2002 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// mathutil.h: Math and bit manipulation functions.

#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 angle

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)
{}

// Specialize clampCast for bool->int conversion to avoid MSVS 2015 performance warning when the max
// value is casted to the source type.
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)
{}

// https://stackoverflow.com/a/37581284
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)
{}

// Converts to and from float and 16.16 fixed point format.
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
{};

// Combine a floating-point value representing a mantissa (x) and an integer exponent (exp) into a
// floating-point value. As in GLSL ldexp() built-in.
inline float Ldexp(float x, int exp)
{}

// First, both normalized floating-point values are converted into 16-bit integer values.
// Then, the results are packed into the returned 32-bit unsigned integer.
// The first float value will be written to the least significant bits of the output;
// the last float value will be written to the most significant bits.
// The conversion of each value to fixed point is done as follows :
// packSnorm2x16 : round(clamp(c, -1, +1) * 32767.0)
inline uint32_t packSnorm2x16(float f1, float f2)
{}

// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
// each component is converted to a normalized floating-point value to generate the returned two
// float values. The first float value will be extracted from the least significant bits of the
// input; the last float value will be extracted from the most-significant bits. The conversion for
// unpacked fixed-point value to floating point is done as follows: unpackSnorm2x16 : clamp(f /
// 32767.0, -1, +1)
inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
{}

// First, both normalized floating-point values are converted into 16-bit integer values.
// Then, the results are packed into the returned 32-bit unsigned integer.
// The first float value will be written to the least significant bits of the output;
// the last float value will be written to the most significant bits.
// The conversion of each value to fixed point is done as follows:
// packUnorm2x16 : round(clamp(c, 0, +1) * 65535.0)
inline uint32_t packUnorm2x16(float f1, float f2)
{}

// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
// each component is converted to a normalized floating-point value to generate the returned two
// float values. The first float value will be extracted from the least significant bits of the
// input; the last float value will be extracted from the most-significant bits. The conversion for
// unpacked fixed-point value to floating point is done as follows: unpackUnorm2x16 : f / 65535.0
inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2)
{}

// Helper functions intended to be used only here.
namespace priv
{

inline uint8_t ToPackedUnorm8(float f)
{}

inline int8_t ToPackedSnorm8(float f)
{}

}  // namespace priv

// Packs 4 normalized unsigned floating-point values to a single 32-bit unsigned integer. Works
// similarly to packUnorm2x16. The floats are clamped to the range 0.0 to 1.0, and written to the
// unsigned integer starting from the least significant bits.
inline uint32_t PackUnorm4x8(float f1, float f2, float f3, float f4)
{}

// Unpacks 4 normalized unsigned floating-point values from a single 32-bit unsigned integer into f.
// Works similarly to unpackUnorm2x16. The floats are unpacked starting from the least significant
// bits.
inline void UnpackUnorm4x8(uint32_t u, float *f)
{}

// Packs 4 normalized signed floating-point values to a single 32-bit unsigned integer. The floats
// are clamped to the range -1.0 to 1.0, and written to the unsigned integer starting from the least
// significant bits.
inline uint32_t PackSnorm4x8(float f1, float f2, float f3, float f4)
{}

// Unpacks 4 normalized signed floating-point values from a single 32-bit unsigned integer into f.
// Works similarly to unpackSnorm2x16. The floats are unpacked starting from the least significant
// bits, and clamped to the range -1.0 to 1.0.
inline void UnpackSnorm4x8(uint32_t u, float *f)
{}

// Returns an unsigned integer obtained by converting the two floating-point values to the 16-bit
// floating-point representation found in the OpenGL ES Specification, and then packing these
// two 16-bit integers into a 32-bit unsigned integer.
// f1: The 16 least-significant bits of the result;
// f2: The 16 most-significant bits.
inline uint32_t packHalf2x16(float f1, float f2)
{}

// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of
// 16-bit values, interpreting those values as 16-bit floating-point numbers according to the OpenGL
// ES Specification, and converting them to 32-bit floating-point values. The first float value is
// obtained from the 16 least-significant bits of u; the second component is obtained from the 16
// most-significant bits of u.
inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
{}

inline float sRGBToLinear(uint8_t srgbValue)
{}

inline uint8_t linearToSRGB(float value)
{}

// Reverse the order of the bits.
inline uint32_t BitfieldReverse(uint32_t value)
{}

// Count the 1 bits.
#if defined(_MSC_VER) && !defined(__clang__)
#    if defined(_M_IX86) || defined(_M_X64)
namespace priv
{
// Check POPCNT instruction support and cache the result.
// https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64#remarks
static const bool kHasPopcnt = [] {
    int info[4];
    __cpuid(&info[0], 1);
    return static_cast<bool>(info[2] & 0x800000);
}();
}  // namespace priv

// Polyfills for x86/x64 CPUs without POPCNT.
// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
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   // x86
        return static_cast<int>(__popcnt(static_cast<uint32_t>(bits >> 32)) +
                                __popcnt(static_cast<uint32_t>(bits)));
#        endif  // defined(_M_X64)
    }
    return BitCountPolyfill(bits);
}

#    elif defined(_M_ARM) || defined(_M_ARM64)

// MSVC's _CountOneBits* intrinsics are not defined for ARM64, moreover they do not use dedicated
// NEON instructions.

inline int BitCount(uint32_t bits)
{
    // cast bits to 8x8 datatype and use VCNT on it
    const uint8x8_t vsum = vcnt_u8(vcreate_u8(static_cast<uint64_t>(bits)));

    // pairwise sums: 8x8 -> 16x4 -> 32x2
    return static_cast<int>(vget_lane_u32(vpaddl_u16(vpaddl_u8(vsum)), 0));
}

inline int BitCount(uint64_t bits)
{
    // cast bits to 8x8 datatype and use VCNT on it
    const uint8x8_t vsum = vcnt_u8(vcreate_u8(bits));

    // pairwise sums: 8x8 -> 16x4 -> 32x2 -> 64x1
    return static_cast<int>(vget_lane_u64(vpaddl_u32(vpaddl_u16(vpaddl_u8(vsum))), 0));
}
#    endif  // defined(_M_IX86) || defined(_M_X64)
#endif      // defined(_MSC_VER) && !defined(__clang__)

#if defined(ANGLE_PLATFORM_POSIX) || defined(__clang__) || defined(__GNUC__)
inline int BitCount(uint32_t bits)
{}

inline int BitCount(uint64_t bits)
{}
#endif  // defined(ANGLE_PLATFORM_POSIX) || defined(__clang__) || defined(__GNUC__)

inline int BitCount(uint8_t bits)
{}

inline int BitCount(uint16_t bits)
{}

#if defined(ANGLE_PLATFORM_WINDOWS)
// Return the index of the least significant bit set. Indexing is such that bit 0 is the least
// significant bit. Implemented for different bit widths on different platforms.
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  // defined(ANGLE_IS_64_BIT_CPU)
    ASSERT(ret != 0u);
    return firstBitIndex;
}

// Return the index of the most significant bit set. Indexing is such that bit 0 is the least
// significant bit.
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  // defined(ANGLE_IS_64_BIT_CPU)
    ASSERT(ret != 0u);
    return lastBitIndex;
}
#endif  // defined(ANGLE_PLATFORM_WINDOWS)

#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  // defined(ANGLE_PLATFORM_POSIX)

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)
{}

// Returns -1 on 0, otherwise the index of the least significant 1 bit as in GLSL.
template <typename T>
int FindLSB(T bits)
{}

// Returns -1 on 0, otherwise the index of the most significant 1 bit as in GLSL.
template <typename T>
int FindMSB(T bits)
{}

// Returns whether the argument is Not a Number.
// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
// non-zero.
inline bool isNaN(float f)
{}

// Returns whether the argument is infinity.
// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
// zero.
inline bool isInf(float f)
{}

namespace priv
{
template <unsigned int N, unsigned int R>
struct iSquareRoot
{};

iSquareRoot<N, N>;

}  // namespace priv

template <unsigned int N>
constexpr unsigned int iSquareRoot()
{}

// Sum, difference and multiplication operations for signed ints that wrap on 32-bit overflow.
//
// Unsigned types are defined to do arithmetic modulo 2^n in C++. For signed types, overflow
// behavior is undefined.

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 gl

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  // namespace rx

constexpr unsigned int Log2(unsigned int bytes)
{}
}  // namespace rx

#endif  // COMMON_MATHUTIL_H_