1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-20 19:54:19 +01:00

[util] Add helpers to encode or decode fixed-point numbers

This commit is contained in:
Philip Rebohle 2024-09-27 10:55:24 +02:00 committed by Philip Rebohle
parent b4e69dce76
commit 5f9f43e658

View File

@ -529,4 +529,61 @@ namespace dxvk::bit {
uint32_t m_mask;
};
/**
* \brief Encodes float as fixed point
*
* Rounds away from zero. If this is not suitable for
* certain use cases, implement round to nearest even.
* \tparam T Integer type, may be signed
* \tparam I Integer bits
* \tparam F Fractional bits
* \param n Float to encode
* \returns Encoded fixed-point value
*/
template<typename T, int32_t I, int32_t F>
T encodeFixed(float n) {
if (n != n)
return 0u;
n *= float(1u << F);
if constexpr (std::is_signed_v<T>) {
n = std::max(n, -float(1u << (I + F - 1u)));
n = std::min(n, float(1u << (I + F - 1u)) - 1.0f);
n += n < 0.0f ? -0.5f : 0.5f;
} else {
n = std::max(n, 0.0f);
n = std::min(n, float(1u << (I + F)) - 1.0f);
n += 0.5f;
}
T result = T(n);
if constexpr (std::is_signed_v<T>)
result &= ((T(1u) << (I + F)) - 1u);
return result;
}
/**
* \brief Decodes fixed-point integer to float
*
* \tparam T Integer type, may be signed
* \tparam I Integer bits
* \tparam F Fractional bits
* \param n Number to decode
* \returns Decoded number
*/
template<typename T, int32_t I, int32_t F>
float decodeFixed(T n) {
// Sign-extend as necessary
if constexpr (std::is_signed_v<T>)
n -= (n & (T(1u) << (I + F - 1u))) << 1u;
return float(n) / float(1u << F);
}
}