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:
99
include/boost/hash2/detail/byteswap.hpp
Normal file
99
include/boost/hash2/detail/byteswap.hpp
Normal 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
|
||||
@@ -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
18
test/detail_byteswap.cpp
Normal 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();
|
||||
}
|
||||
26
test/detail_byteswap_cx.cpp
Normal file
26
test/detail_byteswap_cx.cpp
Normal 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();
|
||||
}
|
||||
Reference in New Issue
Block a user