/* * Copyright (C) 2018-2023 Intel Corporation * * SPDX-License-Identifier: MIT * */ #pragma once #include "shared/source/helpers/vec.h" #include #include #include #include namespace Math { constexpr uint32_t nextPowerOfTwo(uint32_t value) { --value; value |= value >> 1; value |= value >> 2; value |= value >> 4; value |= value >> 8; value |= value >> 16; ++value; return value; } constexpr uint64_t nextPowerOfTwo(uint64_t value) { --value; value |= value >> 1; value |= value >> 2; value |= value >> 4; value |= value >> 8; value |= value >> 16; value |= value >> 32; ++value; return value; } constexpr uint32_t prevPowerOfTwo(uint32_t value) { value |= value >> 1; value |= value >> 2; value |= value >> 4; value |= value >> 8; value |= value >> 16; return (value - (value >> 1)); } constexpr uint64_t prevPowerOfTwo(uint64_t value) { value |= value >> 1; value |= value >> 2; value |= value >> 4; value |= value >> 8; value |= value >> 16; value |= value >> 32; return (value - (value >> 1)); } inline uint32_t getMinLsbSet(uint32_t value) { static const uint8_t multiplyDeBruijnBitPosition[32] = { 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9}; auto invert = -static_cast(value); value &= static_cast(invert); return multiplyDeBruijnBitPosition[static_cast(value * 0x077CB531U) >> 27]; } constexpr uint32_t log2(uint32_t value) { if (value == 0) { return 32; } uint32_t exponent = 0u; while (value >>= 1) { exponent++; } return exponent; } constexpr uint32_t log2(uint64_t value) { if (value == 0) { return 64; } uint32_t exponent = 0; while (value >>= 1) { exponent++; } return exponent; } union FloatConversion { uint32_t u; float f; }; // clang-format off static const FloatConversion PosInfinity = {0x7f800000}; static const FloatConversion NegInfinity = {0xff800000}; static const FloatConversion Nan = {0x7fc00000}; // clang-format on inline uint16_t float2Half(float f) { FloatConversion u; u.f = f; uint32_t fsign = (u.u >> 16) & 0x8000; float x = std::fabs(f); // Nan if (x != x) { u.u >>= (24 - 11); u.u &= 0x7fff; u.u |= 0x0200; // silence the NaN return u.u | fsign; } // overflow if (x >= std::ldexp(1.0f, 16)) { if (x == PosInfinity.f) return 0x7c00 | fsign; return 0x7bff | fsign; } // underflow if (x < std::ldexp(1.0f, -24)) return fsign; // The halfway case can return 0x0001 or 0. 0 is even. // half denormal if (x < std::ldexp(1.0f, -14)) { x *= std::ldexp(1.0f, 24); return (uint16_t)((int)x | fsign); } u.u &= 0xFFFFE000U; u.u -= 0x38000000U; return (u.u >> (24 - 11)) | fsign; } constexpr bool isDivisibleByPowerOfTwoDivisor(uint32_t number, uint32_t divisor) { return (number & (divisor - 1)) == 0; } constexpr size_t computeTotalElementsCount(const Vec3 &inputVector) { size_t minElementCount = 1; auto xDim = std::max(minElementCount, inputVector.x); auto yDim = std::max(minElementCount, inputVector.y); auto zDim = std::max(minElementCount, inputVector.z); return xDim * yDim * zDim; } template constexpr bool isPow2(T val) { return val != 0 && (val & (val - 1)) == 0; } template constexpr T ffs(T v) { if (v == 0) { return std::numeric_limits::max(); } for (T i = 0; i < sizeof(T) * 8; ++i) { if (0 != (v & (1ULL << i))) { return i; } } std::abort(); } constexpr size_t divideAndRoundUp(size_t dividend, size_t divisor) { return (dividend + divisor - 1) / divisor; } } // namespace Math