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:
parent
b4e69dce76
commit
5f9f43e658
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user