diff --git a/include/bx/fpumath.h b/include/bx/fpumath.h index 2c93cc8..4c04eb6 100644 --- a/include/bx/fpumath.h +++ b/include/bx/fpumath.h @@ -46,6 +46,18 @@ namespace bx /// float toDeg(float _rad); + /// + uint32_t floatToBits(float _a); + + /// + float bitsToFloat(uint32_t _a); + + /// + uint64_t doubleToBits(double _a); + + /// + double bitsToDouble(uint64_t _a); + /// bool isNan(float _f); diff --git a/include/bx/fpumath.inl b/include/bx/fpumath.inl index ff8dc1a..8a81fc2 100644 --- a/include/bx/fpumath.inl +++ b/include/bx/fpumath.inl @@ -25,46 +25,64 @@ namespace bx return _rad * 180.0f / pi; } + inline uint32_t floatToBits(float _a) + { + union { float f; uint32_t ui; } u = { _a }; + return u.ui; + } + + inline float bitsToFloat(uint32_t _a) + { + union { uint32_t ui; float f; } u = { _a }; + return u.f; + } + + inline uint64_t doubleToBits(double _a) + { + union { double f; uint64_t ui; } u = { _a }; + return u.ui; + } + + inline double bitsToDouble(uint64_t _a) + { + union { uint64_t ui; double f; } u = { _a }; + return u.f; + } + inline bool isNan(float _f) { - union { float f; uint32_t ui; } u = { _f }; - u.ui &= INT32_MAX; - return u.ui > UINT32_C(0x7f800000); + const uint32_t tmp = floatToBits(_f) & INT32_MAX; + return tmp > UINT32_C(0x7f800000); } inline bool isNan(double _f) { - union { double f; uint64_t ui; } u = { _f }; - u.ui &= INT64_MAX; - return u.ui > UINT64_C(0x7ff0000000000000); + const uint64_t tmp = doubleToBits(_f) & INT64_MAX; + return tmp > UINT64_C(0x7ff0000000000000); } inline bool isFinite(float _f) { - union { float f; uint32_t ui; } u = { _f }; - u.ui &= INT32_MAX; - return u.ui < UINT32_C(0x7f800000); + const uint32_t tmp = floatToBits(_f) & INT32_MAX; + return tmp < UINT32_C(0x7f800000); } inline bool isFinite(double _f) { - union { double f; uint64_t ui; } u = { _f }; - u.ui &= INT64_MAX; - return u.ui < UINT64_C(0x7ff0000000000000); + const uint64_t tmp = doubleToBits(_f) & INT64_MAX; + return tmp < UINT64_C(0x7ff0000000000000); } inline bool isInfinite(float _f) { - union { float f; uint32_t ui; } u = { _f }; - u.ui &= INT32_MAX; - return u.ui == UINT32_C(0x7f800000); + const uint32_t tmp = floatToBits(_f) & INT32_MAX; + return tmp == UINT32_C(0x7f800000); } inline bool isInfinite(double _f) { - union { double f; uint64_t ui; } u = { _f }; - u.ui &= INT64_MAX; - return u.ui == UINT64_C(0x7ff0000000000000); + const uint64_t tmp = doubleToBits(_f) & INT64_MAX; + return tmp == UINT64_C(0x7ff0000000000000); } inline float ffloor(float _f) diff --git a/tests/fpumath_test.cpp b/tests/fpumath_test.cpp index c982f86..ae84387 100644 --- a/tests/fpumath_test.cpp +++ b/tests/fpumath_test.cpp @@ -20,6 +20,12 @@ TEST_CASE("isFinite, isInfinite, isNan", "") } #endif // !BX_COMPILER_MSVC || BX_COMPILER_MSVC >= 1800 +TEST_CASE("ToBits", "") +{ + REQUIRE(UINT32_C(0x12345678) == bx::floatToBits( bx::bitsToFloat( UINT32_C(0x12345678) ) ) ); + REQUIRE(UINT64_C(0x123456789abcdef0) == bx::doubleToBits(bx::bitsToDouble(UINT32_C(0x123456789abcdef0) ) ) ); +} + void mtxCheck(const float* _a, const float* _b) { if (!bx::fequal(_a, _b, 16, 0.01f) )