1
0
forked from boostorg/core

Add bit_ceil

This commit is contained in:
Peter Dimov
2020-12-29 00:29:44 +02:00
parent 3e41929dfb
commit 26728848b4
3 changed files with 127 additions and 3 deletions

View File

@ -197,15 +197,73 @@ 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 );
}
namespace detail
{
BOOST_CXX14_CONSTEXPR inline boost::uint32_t bit_ceil_impl( boost::uint32_t x ) BOOST_NOEXCEPT
{
if( x == 0 )
{
return 0;
}
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
++x;
return x;
}
BOOST_CXX14_CONSTEXPR inline boost::uint64_t bit_ceil_impl( boost::uint64_t x ) BOOST_NOEXCEPT
{
if( x == 0 )
{
return 0;
}
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
x |= x >> 32;
++x;
return x;
}
} // namespace detail
template<class T>
BOOST_CXX14_CONSTEXPR T bit_ceil( T x ) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT( sizeof(T) <= sizeof(boost::uint64_t) );
if( sizeof(T) <= sizeof(boost::uint32_t) )
{
return static_cast<T>( boost::core::detail::bit_ceil_impl( static_cast<boost::uint32_t>( x ) ) );
}
else
{
return static_cast<T>( boost::core::detail::bit_ceil_impl( static_cast<boost::uint64_t>( x ) ) );
}
}
// endian
#if !defined(BOOST_NO_CXX11_SCOPED_ENUMS)

View File

@ -229,6 +229,7 @@ run bit_countl_test.cpp ;
run bit_width_test.cpp ;
run has_single_bit_test.cpp ;
run bit_floor_test.cpp ;
run bit_ceil_test.cpp ;
use-project /boost/core/swap : ./swap ;
build-project ./swap ;

65
test/bit_ceil_test.cpp Normal file
View File

@ -0,0 +1,65 @@
// Test for boost/core/bit.hpp (bit_ceil)
//
// 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>
template<class T> void test_bit_ceil( T x )
{
if( !boost::core::has_single_bit( x ) )
{
x >>= 1;
}
T y = boost::core::bit_ceil( x );
if( x == 0 )
{
BOOST_TEST_EQ( y, 0 );
}
else
{
BOOST_TEST( boost::core::has_single_bit( y ) );
BOOST_TEST_GE( +y, +x );
BOOST_TEST_LT( y >> 1, +x );
}
}
int main()
{
{
test_bit_ceil( static_cast<unsigned char>( 0 ) );
test_bit_ceil( static_cast<unsigned short>( 0 ) );
test_bit_ceil( static_cast<unsigned int>( 0 ) );
test_bit_ceil( static_cast<unsigned long>( 0 ) );
test_bit_ceil( static_cast<unsigned long long>( 0 ) );
}
{
test_bit_ceil( static_cast<boost::uint8_t>( 0x80 ) );
test_bit_ceil( static_cast<boost::uint16_t>( 0x8000 ) );
test_bit_ceil( static_cast<boost::uint32_t>( 0x80000000 ) );
test_bit_ceil( static_cast<boost::uint64_t>( 0x8000000000000000 ) );
}
boost::detail::splitmix64 rng;
for( int i = 0; i < 1000; ++i )
{
boost::uint64_t x = rng();
test_bit_ceil( static_cast<unsigned char>( x ) );
test_bit_ceil( static_cast<unsigned short>( x ) );
test_bit_ceil( static_cast<unsigned int>( x ) );
test_bit_ceil( static_cast<unsigned long>( x ) );
test_bit_ceil( static_cast<unsigned long long>( x ) );
}
return boost::report_errors();
}