From ca3bc1bd80fdff511e83d563a4ee94d6cd885473 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 25 Aug 2023 11:28:05 -0700 Subject: Use a bit_cast instead of a union for type-punning --- common/alnumeric.h | 47 ++++++++++++++++------------------------------- 1 file changed, 16 insertions(+), 31 deletions(-) (limited to 'common/alnumeric.h') diff --git a/common/alnumeric.h b/common/alnumeric.h index 8220d3e5..620a9bcb 100644 --- a/common/alnumeric.h +++ b/common/alnumeric.h @@ -12,6 +12,7 @@ #include #endif +#include "albit.h" #include "altraits.h" #include "opthelpers.h" @@ -159,21 +160,16 @@ inline int float2int(float f) noexcept #elif (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 0) \ || ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) \ && !defined(__SSE_MATH__)) - int sign, shift, mant; - union { - float f; - int i; - } conv; + const int conv_i{al::bit_cast(f)}; - conv.f = f; - sign = (conv.i>>31) | 1; - shift = ((conv.i>>23)&0xff) - (127+23); + const int sign{(conv_i>>31) | 1}; + const int shift{((conv_i>>23)&0xff) - (127+23)}; /* Over/underflow */ if(shift >= 31 || shift < -23) UNLIKELY return 0; - mant = (conv.i&0x7fffff) | 0x800000; + const int mant{(conv_i&0x7fffff) | 0x800000}; if(shift < 0) LIKELY return (mant >> -shift) * sign; return (mant << shift) * sign; @@ -195,25 +191,19 @@ inline int double2int(double d) noexcept #elif (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP < 2) \ || ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) \ && !defined(__SSE2_MATH__)) - int sign, shift; - int64_t mant; - union { - double d; - int64_t i64; - } conv; + const int64_t conv_i64{al::bit_cast(d)}; - conv.d = d; - sign = (conv.i64 >> 63) | 1; - shift = ((conv.i64 >> 52) & 0x7ff) - (1023 + 52); + const int sign{static_cast(conv_i64 >> 63) | 1}; + const int shift{(static_cast(conv_i64 >> 52) & 0x7ff) - (1023 + 52)}; /* Over/underflow */ if(shift >= 63 || shift < -52) UNLIKELY return 0; - mant = (conv.i64 & 0xfffffffffffff_i64) | 0x10000000000000_i64; + const int64_t mant{(conv_i64 & 0xfffffffffffff_i64) | 0x10000000000000_i64}; if(shift < 0) LIKELY - return (int)(mant >> -shift) * sign; - return (int)(mant << shift) * sign; + return static_cast(mant >> -shift) * sign; + return static_cast(mant << shift) * sign; #else @@ -246,19 +236,14 @@ inline float fast_roundf(float f) noexcept /* Integral limit, where sub-integral precision is not available for * floats. */ - static const float ilim[2]{ + static constexpr float ilim[2]{ 8388608.0f /* 0x1.0p+23 */, -8388608.0f /* -0x1.0p+23 */ }; - unsigned int sign, expo; - union { - float f; - unsigned int i; - } conv; - - conv.f = f; - sign = (conv.i>>31)&0x01; - expo = (conv.i>>23)&0xff; + const unsigned int conv_i{al::bit_cast(f)}; + + const unsigned int sign{(conv_i>>31)&0x01}; + const unsigned int expo{(conv_i>>23)&0xff}; if(expo >= 150/*+23*/) UNLIKELY { -- cgit v1.2.3