endian: add float byteswap specialisation
This commit is contained in:
parent
aff4786409
commit
d8bb00c9c3
@ -495,6 +495,7 @@ if (TESTS)
|
||||
crypto/tea
|
||||
crypto/xtea
|
||||
crypto/xxtea
|
||||
endian
|
||||
exe
|
||||
extent
|
||||
fixed
|
||||
|
33
endian.hpp
33
endian.hpp
@ -33,7 +33,7 @@ namespace util {
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
constexpr T
|
||||
bswap (T);
|
||||
bswap (T) noexcept;
|
||||
|
||||
// CXX: Update using "if constexpr" when available. It doesn't seem to be
|
||||
// worth the dicking about to use enable_if_t to differentiate the
|
||||
@ -42,7 +42,7 @@ namespace util {
|
||||
template <> \
|
||||
constexpr \
|
||||
int##S##_t \
|
||||
bswap (int##S##_t v) { \
|
||||
bswap (int##S##_t v) noexcept { \
|
||||
const union { \
|
||||
int##S##_t s; \
|
||||
uint##S##_t u; \
|
||||
@ -55,12 +55,31 @@ namespace util {
|
||||
SIGNED_BSWAP(32)
|
||||
SIGNED_BSWAP(64)
|
||||
|
||||
template <> constexpr int8_t bswap ( int8_t v) { return v; }
|
||||
template <> constexpr uint8_t bswap (uint8_t v) { return v; }
|
||||
template <> constexpr int8_t bswap ( int8_t v) noexcept { return v; }
|
||||
template <> constexpr uint8_t bswap (uint8_t v) noexcept { return v; }
|
||||
|
||||
template <> constexpr uint16_t bswap (uint16_t v) { return __builtin_bswap16 (v); }
|
||||
template <> constexpr uint32_t bswap (uint32_t v) { return __builtin_bswap32 (v); }
|
||||
template <> constexpr uint64_t bswap (uint64_t v) { return __builtin_bswap64 (v); }
|
||||
template <> constexpr uint16_t bswap (uint16_t v) noexcept { return __builtin_bswap16 (v); }
|
||||
template <> constexpr uint32_t bswap (uint32_t v) noexcept { return __builtin_bswap32 (v); }
|
||||
template <> constexpr uint64_t bswap (uint64_t v) noexcept { return __builtin_bswap64 (v); }
|
||||
|
||||
|
||||
// use a type-punning union to punt the byte swapping operation to the
|
||||
// unsigned integer code.
|
||||
//
|
||||
// this is debatably safe under production compilers like gcc + clang
|
||||
// despite what the standard may say about unions.
|
||||
template <>
|
||||
constexpr float
|
||||
bswap (float v) noexcept
|
||||
{
|
||||
union {
|
||||
float f;
|
||||
uint32_t u;
|
||||
} temp { .f = v };
|
||||
|
||||
temp.u = bswap (temp.u);
|
||||
return temp.f;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
31
test/endian.cpp
Normal file
31
test/endian.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "tap.hpp"
|
||||
|
||||
#include "endian.hpp"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
util::TAP::logger tap;
|
||||
|
||||
{
|
||||
uint32_t a = 0x12345678, b = 0x78563412;
|
||||
tap.expect_eq (a, util::bswap (b), "u32 byteswap");
|
||||
}
|
||||
|
||||
{
|
||||
// try to byte swap the pattern for 1.0f
|
||||
//
|
||||
// it may not be the most robust test, but it'll catch the most
|
||||
// egregious errors for the time being.
|
||||
union {
|
||||
uint32_t u;
|
||||
float f;
|
||||
} data { .u = 0x0000803f /* 0x3f800000 == 1.f */ };
|
||||
|
||||
tap.expect_eq (util::bswap (data.f), 1.f, "f32 byteswap");
|
||||
};
|
||||
|
||||
return tap.status ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user