mirror of
https://github.com/boostorg/core.git
synced 2025-07-29 20:37:22 +02:00
Add boost/core/bit.hpp (bit_cast, rotl, rotr)
This commit is contained in:
134
include/boost/core/bit.hpp
Normal file
134
include/boost/core/bit.hpp
Normal file
@ -0,0 +1,134 @@
|
||||
#ifndef BOOST_CORE_BIT_HPP_INCLUDED
|
||||
#define BOOST_CORE_BIT_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// boost/core/bit.hpp
|
||||
//
|
||||
// A portable version of the C++20 standard header <bit>
|
||||
//
|
||||
// Copyright 2020 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <limits>
|
||||
#include <cstring>
|
||||
|
||||
#define BOOST_CORE_BIT_CONSTEXPR
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
|
||||
// bit_cast
|
||||
template<class To, class From>
|
||||
To bit_cast( From const & from) BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_STATIC_ASSERT( sizeof(To) == sizeof(From) );
|
||||
|
||||
To to;
|
||||
std::memcpy( &to, &from, sizeof(To) );
|
||||
return to;
|
||||
}
|
||||
|
||||
// counting
|
||||
template<class T>
|
||||
BOOST_CORE_BIT_CONSTEXPR int countl_zero( T x ) BOOST_NOEXCEPT;
|
||||
|
||||
template<class T>
|
||||
BOOST_CORE_BIT_CONSTEXPR int countl_one( T x ) BOOST_NOEXCEPT
|
||||
{
|
||||
return boost::core::countl_zero( ~x );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOST_CORE_BIT_CONSTEXPR int countr_zero( T x ) BOOST_NOEXCEPT;
|
||||
|
||||
template<class T>
|
||||
BOOST_CORE_BIT_CONSTEXPR int countr_one( T x ) BOOST_NOEXCEPT
|
||||
{
|
||||
return boost::core::countr_zero( ~x );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOST_CORE_BIT_CONSTEXPR int popcount( T x ) BOOST_NOEXCEPT;
|
||||
|
||||
// rotating
|
||||
template<class T>
|
||||
BOOST_CXX14_CONSTEXPR T rotl( T x, int s ) BOOST_NOEXCEPT
|
||||
{
|
||||
unsigned const mask = std::numeric_limits<T>::digits - 1;
|
||||
return x << (s & mask) | x >> ((-s) & mask);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOST_CXX14_CONSTEXPR T rotr( T x, int s ) BOOST_NOEXCEPT
|
||||
{
|
||||
unsigned const mask = std::numeric_limits<T>::digits - 1;
|
||||
return x >> (s & mask) | x << ((-s) & mask);
|
||||
}
|
||||
|
||||
// integral powers of 2
|
||||
template<class T>
|
||||
BOOST_CONSTEXPR bool has_single_bit( T x ) BOOST_NOEXCEPT
|
||||
{
|
||||
return x != 0 && ( x & ( x - 1 ) ) == 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOST_CONSTEXPR T bit_width( T x ) BOOST_NOEXCEPT
|
||||
{
|
||||
return std::numeric_limits<T>::digits - boost::core::countl_zero( x );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
BOOST_CONSTEXPR T bit_ceil( T x ) BOOST_NOEXCEPT;
|
||||
|
||||
template<class T>
|
||||
BOOST_CONSTEXPR T bit_floor( T x ) BOOST_NOEXCEPT
|
||||
{
|
||||
return x == 0? 0: T(1) << ( boost::core::bit_width( x ) - 1 );
|
||||
}
|
||||
|
||||
// endian
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_SCOPED_ENUMS)
|
||||
|
||||
enum class endian
|
||||
{
|
||||
little,
|
||||
big,
|
||||
// native = /* see description */
|
||||
};
|
||||
|
||||
typedef endian endian_type;
|
||||
|
||||
#else
|
||||
|
||||
namespace endian
|
||||
{
|
||||
|
||||
enum type
|
||||
{
|
||||
little,
|
||||
big,
|
||||
// native = /* see description */
|
||||
};
|
||||
|
||||
} // namespace endian
|
||||
|
||||
typedef endian::type endian_type;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace core
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_CORE_BIT_HPP_INCLUDED
|
54
include/boost/core/detail/splitmix64.hpp
Normal file
54
include/boost/core/detail/splitmix64.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef BOOST_CORE_DETAIL_SPLITMIX64_HPP_INCLUDED
|
||||
#define BOOST_CORE_DETAIL_SPLITMIX64_HPP_INCLUDED
|
||||
|
||||
// Copyright 2020 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
// An implementation of splitmix64 for testing purposes,
|
||||
// derived from Sebastiano Vigna's public domain implementation
|
||||
// http://xorshift.di.unimi.it/splitmix64.c
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class splitmix64
|
||||
{
|
||||
private:
|
||||
|
||||
boost::uint64_t x_;
|
||||
|
||||
public:
|
||||
|
||||
splitmix64(): x_( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
explicit splitmix64( boost::uint64_t seed ): x_( seed )
|
||||
{
|
||||
}
|
||||
|
||||
boost::uint64_t operator()()
|
||||
{
|
||||
x_ += 0x9e3779b97f4a7c15;
|
||||
|
||||
boost::uint64_t z = x_;
|
||||
|
||||
z ^= z >> 30;
|
||||
z *= 0xbf58476d1ce4e5b9;
|
||||
z ^= z >> 27;
|
||||
z *= 0x94d049bb133111eb;
|
||||
z ^= z >> 31;
|
||||
|
||||
return z;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_CORE_DETAIL_SPLITMIX64_HPP_INCLUDED
|
@ -222,5 +222,8 @@ run no_exceptions_support_test.cpp : : : <exception-handling>off : no_exceptions
|
||||
|
||||
run cmath_test.cpp ;
|
||||
|
||||
run bit_cast_test.cpp ;
|
||||
run bit_rotate_test.cpp ;
|
||||
|
||||
use-project /boost/core/swap : ./swap ;
|
||||
build-project ./swap ;
|
||||
|
29
test/bit_cast_test.cpp
Normal file
29
test/bit_cast_test.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
// Test for boost/core/bit.hpp
|
||||
//
|
||||
// Copyright 2020 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/core/bit.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <cstring>
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
float x = 0.89f;
|
||||
boost::uint32_t y = boost::core::bit_cast<boost::uint32_t>( x );
|
||||
|
||||
BOOST_TEST( std::memcmp( &x, &y, sizeof(x) ) == 0 );
|
||||
}
|
||||
|
||||
{
|
||||
double x = 0.89;
|
||||
boost::uint64_t y = boost::core::bit_cast<boost::uint64_t>( x );
|
||||
|
||||
BOOST_TEST( std::memcmp( &x, &y, sizeof(x) ) == 0 );
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
168
test/bit_rotate_test.cpp
Normal file
168
test/bit_rotate_test.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
// Test for boost/core/bit.hpp
|
||||
//
|
||||
// Copyright 2020 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/core/bit.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/detail/splitmix64.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <limits>
|
||||
|
||||
int const M = 256;
|
||||
|
||||
template<class T> void test_rotate( T x )
|
||||
{
|
||||
for( int i = 0; i < M; ++i )
|
||||
{
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, i ), +boost::core::rotr( x, -i ) );
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, -i ), +boost::core::rotr( x, i ) );
|
||||
|
||||
unsigned const width = std::numeric_limits<T>::digits;
|
||||
unsigned r = i & ( width - 1 );
|
||||
|
||||
if( r == 0 )
|
||||
{
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, i ), +x );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, i ), +x );
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, i ), +static_cast<T>( (x << r) | (x >> (width - r)) ) );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, i ), +static_cast<T>( (x >> r) | (x << (width - r)) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
boost::uint8_t x = 0x11;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x22 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x88 );
|
||||
|
||||
x = 0x22;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x44 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x11 );
|
||||
|
||||
x = 0x44;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x88 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x22 );
|
||||
|
||||
x = 0x88;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x11 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x44 );
|
||||
}
|
||||
|
||||
{
|
||||
boost::uint16_t x = 0x1111;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x2222 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x8888 );
|
||||
|
||||
x = 0x2222;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x4444 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x1111 );
|
||||
|
||||
x = 0x4444;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x8888 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x2222 );
|
||||
|
||||
x = 0x8888;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x1111 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x4444 );
|
||||
}
|
||||
|
||||
{
|
||||
boost::uint32_t x = 0x11111111;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x22222222 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x88888888 );
|
||||
|
||||
x = 0x22222222;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x44444444 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x11111111 );
|
||||
|
||||
x = 0x44444444;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x88888888 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x22222222 );
|
||||
|
||||
x = 0x88888888;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x11111111 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x44444444 );
|
||||
}
|
||||
|
||||
{
|
||||
boost::uint64_t x = 0x1111111111111111;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x2222222222222222 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x8888888888888888 );
|
||||
|
||||
x = 0x2222222222222222;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x4444444444444444 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x1111111111111111 );
|
||||
|
||||
x = 0x4444444444444444;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x8888888888888888 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x2222222222222222 );
|
||||
|
||||
x = 0x8888888888888888;
|
||||
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, 1 ), 0x1111111111111111 );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, 1 ), 0x4444444444444444 );
|
||||
}
|
||||
|
||||
for( int i = -M; i <= M; ++i )
|
||||
{
|
||||
{
|
||||
unsigned char x = 0;
|
||||
BOOST_TEST_EQ( +boost::core::rotl( x, i ), +x );
|
||||
BOOST_TEST_EQ( +boost::core::rotr( x, i ), +x );
|
||||
}
|
||||
|
||||
{
|
||||
unsigned int x = 0;
|
||||
BOOST_TEST_EQ( boost::core::rotl( x, i ), x );
|
||||
BOOST_TEST_EQ( boost::core::rotr( x, i ), x );
|
||||
}
|
||||
|
||||
{
|
||||
unsigned long x = 0;
|
||||
BOOST_TEST_EQ( boost::core::rotl( x, i ), x );
|
||||
BOOST_TEST_EQ( boost::core::rotr( x, i ), x );
|
||||
}
|
||||
|
||||
{
|
||||
unsigned long long x = 0;
|
||||
BOOST_TEST_EQ( boost::core::rotl( x, i ), x );
|
||||
BOOST_TEST_EQ( boost::core::rotr( x, i ), x );
|
||||
}
|
||||
}
|
||||
|
||||
boost::detail::splitmix64 rng;
|
||||
|
||||
for( int i = 0; i < 1000; ++i )
|
||||
{
|
||||
boost::uint64_t x = rng();
|
||||
|
||||
test_rotate( static_cast<unsigned char>( x ) );
|
||||
test_rotate( static_cast<unsigned int>( x ) );
|
||||
test_rotate( static_cast<unsigned long>( x ) );
|
||||
test_rotate( static_cast<unsigned long long>( x ) );
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
Reference in New Issue
Block a user