Skip to content

Commit

Permalink
Replace type-punning unions by std::bit_cast clone
Browse files Browse the repository at this point in the history
The type-punning unions are not allowed by the C++ standard. bit_cast is
more succinct anyway.
  • Loading branch information
slipher committed May 27, 2024
1 parent bfa7b90 commit 2ae2181
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 39 deletions.
12 changes: 3 additions & 9 deletions src/common/Endian.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,9 @@ inline uint64_t USwap64(uint64_t x)

inline float SwapFloat(float x)
{
union
{
float f;
int i;
unsigned int ui;
} fi;
fi.f = x;
fi.i = Swap32(fi.i);
return fi.f;
int32_t bits = Util::bit_cast<int32_t>(x);
bits = Swap32(bits);
return Util::bit_cast<float>(bits);
}

#ifdef Q3_LITTLE_ENDIAN
Expand Down
11 changes: 11 additions & 0 deletions src/common/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ char *PRINTF_LIKE(1) va( const char *format, ... );

namespace Util {

// C++20 std::bit_cast
template<typename ToT, typename FromT>
ToT bit_cast(FromT from)
{
static_assert(sizeof(ToT) == sizeof(FromT), "bit_cast: sizes must be equal");

ToT to;
memcpy(&to, &from, sizeof(to));
return to;
}

// Binary search function which returns an iterator to the result or end if not found
template<typename Iter, typename T>
Iter binary_find(Iter begin, Iter end, const T& value)
Expand Down
25 changes: 1 addition & 24 deletions src/engine/qcommon/q_shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,6 @@ void ignore_result(T) {}
using uint = unsigned int;
enum class qtrinary {qno, qyes, qmaybe};

union floatint_t
{
float f;
int i;
uint ui;
};

//=============================================================

#include "common/Platform.h"
Expand Down Expand Up @@ -351,22 +344,6 @@ extern const quat_t quatIdentity;

#define Q_ftol(x) ((long)(x))

inline unsigned int Q_floatBitsToUint( float number )
{
floatint_t t;

t.f = number;
return t.ui;
}

inline float Q_uintBitsToFloat( unsigned int number )
{
floatint_t t;

t.ui = number;
return t.f;
}

// Overall relative error bound (ignoring unknown powerpc case): 5 * 10^-6
// https://en.wikipedia.org/wiki/Fast_inverse_square_root#/media/File:2nd-iter.png
inline float Q_rsqrt( float number )
Expand All @@ -379,7 +356,7 @@ extern const quat_t quatIdentity;
// SSE rsqrt relative error bound: 3.7 * 10^-4
_mm_store_ss( &y, _mm_rsqrt_ss( _mm_load_ss( &number ) ) );
#else
y = Q_uintBitsToFloat( 0x5f3759df - (Q_floatBitsToUint( number ) >> 1) );
y = Util::bit_cast<float>( 0x5f3759df - ( Util::bit_cast<uint32_t>( number ) >> 1 ) );
y *= ( 1.5f - ( x * y * y ) ); // initial iteration
// relative error bound after the initial iteration: 1.8 * 10^-3
#endif
Expand Down
10 changes: 4 additions & 6 deletions src/engine/renderer/tr_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,10 @@ static inline void snorm16ToFloat( const i16vec4_t in, vec4_t out )

static inline f16_t floatToHalf( float in ) {
static float scale = powf(2.0f, 15 - 127);
floatint_t fi;

fi.f = in * scale;
uint32_t ui = Util::bit_cast<uint32_t>( in * scale );

return { uint16_t(((fi.ui & 0x80000000) >> 16) | ((fi.ui & 0x0fffe000) >> 13)) };
return { uint16_t(((ui & 0x80000000) >> 16) | ((ui & 0x0fffe000) >> 13)) };
}
static inline void floatToHalf( const vec4_t in, f16vec4_t out )
{
Expand All @@ -140,10 +139,9 @@ static inline void floatToHalf( const vec4_t in, f16vec4_t out )
}
static inline float halfToFloat( f16_t in ) {
static float scale = powf(2.0f, 127 - 15);
floatint_t fi;

fi.ui = (((unsigned int)in.bits & 0x8000) << 16) | (((unsigned int)in.bits & 0x7fff) << 13);
return fi.f * scale;
uint32_t ui = (((unsigned int)in.bits & 0x8000) << 16) | (((unsigned int)in.bits & 0x7fff) << 13);
return Util::bit_cast<float>(ui) * scale;
}
static inline void halfToFloat( const f16vec4_t in, vec4_t out )
{
Expand Down

0 comments on commit 2ae2181

Please sign in to comment.