Skip to content

Commit

Permalink
[util] Add helpers to encode or decode fixed-point numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
doitsujin committed Sep 27, 2024
1 parent 78f5136 commit a4ecb30
Showing 1 changed file with 57 additions and 0 deletions.
57 changes: 57 additions & 0 deletions src/util/util_bit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

}

0 comments on commit a4ecb30

Please sign in to comment.