2
0
mirror of https://github.com/boostorg/hash2.git synced 2026-01-19 04:12:12 +00:00

add 32-bit, 64-bit byteswap implementation

This commit is contained in:
Christian Mazakas
2025-04-25 10:26:19 -07:00
parent 1a153c88d0
commit 6efb995861
4 changed files with 145 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
#ifndef BOOST_HASH2_DETAIL_BYTESWAP_HPP_INCLUDED
#define BOOST_HASH2_DETAIL_BYTESWAP_HPP_INCLUDED
// Copyright 2025 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/detail/is_constant_evaluated.hpp>
#include <boost/config.hpp>
#include <cstdint>
#if defined(BOOST_MSVC)
#include <intrin.h>
#endif
namespace boost
{
namespace hash2
{
namespace detail
{
#if defined(BOOST_GCC) || defined(BOOST_CLANG)
BOOST_CXX14_CONSTEXPR inline std::uint32_t byteswap_impl( std::uint32_t x ) noexcept
{
return __builtin_bswap32( x );
}
BOOST_CXX14_CONSTEXPR inline std::uint64_t byteswap_impl( std::uint64_t x ) noexcept
{
return __builtin_bswap64( x );
}
#elif defined(BOOST_MSVC)
BOOST_CXX14_CONSTEXPR inline std::uint32_t byteswap_impl( std::uint32_t x ) noexcept
{
if( !detail::is_constant_evaluated() )
{
return _byteswap_ulong( x );
}
else
{
// copy-paste the approach used by Core in bit.hpp
std::uint32_t step16 = x << 16 | x >> 16;
return ( ( step16 << 8 ) & 0xff00ff00 ) | ( ( step16 >> 8 ) & 0x00ff00ff );
}
}
BOOST_CXX14_CONSTEXPR inline std::uint64_t byteswap_impl( std::uint64_t x ) noexcept
{
if( !detail::is_constant_evaluated() )
{
return _byteswap_uint64( x );
}
else
{
// copy-paste the approach used by Core in bit.hpp
std::::uint64_t step32 = x << 32 | x >> 32;
std::::uint64_t step16 = ( step32 & 0x0000ffff0000ffffull ) << 16 | ( step32 & 0xffff0000ffff0000ull ) >> 16;
return ( step16 & 0x00ff00ff00ff00ffull ) << 8 | ( step16 & 0xff00ff00ff00ff00ull ) >> 8;
}
}
#else
BOOST_CXX14_CONSTEXPR inline std::uint32_t byteswap_impl( std::uint32_t x ) noexcept
{
// copy-paste the approach used by Core in bit.hpp
std::uint32_t step16 = x << 16 | x >> 16;
return ( ( step16 << 8 ) & 0xff00ff00 ) | ( ( step16 >> 8 ) & 0x00ff00ff );
}
BOOST_CXX14_CONSTEXPR inline std::uint64_t byteswap_impl( std::uint64_t x ) noexcept
{
// copy-paste the approach used by Core in bit.hpp
std::::uint64_t step32 = x << 32 | x >> 32;
std::::uint64_t step16 = ( step32 & 0x0000ffff0000ffffull ) << 16 | ( step32 & 0xffff0000ffff0000ull ) >> 16;
return ( step16 & 0x00ff00ff00ff00ffull ) << 8 | ( step16 & 0xff00ff00ff00ff00ull ) >> 8;
}
#endif
BOOST_CXX14_CONSTEXPR inline std::uint32_t byteswap( std::uint32_t x ) noexcept
{
return byteswap_impl( x );
}
BOOST_CXX14_CONSTEXPR inline std::uint64_t byteswap( std::uint64_t x ) noexcept
{
return byteswap_impl( x );
}
} // namespace detail
} // namespace hash2
} // namespace boost
#endif // #ifndef BOOST_HASH2_DETAIL_BYTESWAP_HPP_INCLUDED

View File

@@ -54,6 +54,8 @@ run detail_write.cpp ;
run detail_write_2.cpp ;
run detail_rot.cpp ;
run detail_has_tag_invoke.cpp ;
run detail_byteswap.cpp ;
run detail_byteswap_cx.cpp ;
# hash_append

18
test/detail_byteswap.cpp Normal file
View File

@@ -0,0 +1,18 @@
// Copyright 2025 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/detail/byteswap.hpp>
#include <boost/core/lightweight_test.hpp>
// shamelessly steal pdimov's tests from Core
int main()
{
using boost::hash2::detail::byteswap;
BOOST_TEST_EQ( byteswap( std::uint32_t{ 0xf1e2d3c4u } ), 0xc4d3e2f1u );
BOOST_TEST_EQ( byteswap( std::uint64_t{ 0xf1e2d3c4u } << 32 | 0xb5a69788u ), ( std::uint64_t{ 0x8897a6b5u } << 32 | 0xc4d3e2f1u) );
return boost::report_errors();
}

View File

@@ -0,0 +1,26 @@
// Copyright 2025 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/detail/byteswap.hpp>
#include <boost/core/lightweight_test.hpp>
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
#if defined(BOOST_NO_CXX14_CONSTEXPR)
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2)
#else
# define TEST_EQ(x1, x2) BOOST_TEST_EQ(x1, x2); STATIC_ASSERT( x1 == x2 )
#endif
// shamelessly steal pdimov's tests from Core
int main()
{
using boost::hash2::detail::byteswap;
TEST_EQ( byteswap( std::uint32_t{ 0xf1e2d3c4u } ), 0xc4d3e2f1u );
TEST_EQ( byteswap( std::uint64_t{ 0xf1e2d3c4u } << 32 | 0xb5a69788u ), ( std::uint64_t{ 0x8897a6b5u } << 32 | 0xc4d3e2f1u) );
return boost::report_errors();
}