libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00028 // A (growing) collection of bit manipulation utils 00029 00030 #ifndef MOOST_UTILS_NEXT_POWER_OF_TWO_HPP__ 00031 #define MOOST_UTILS_NEXT_POWER_OF_TWO_HPP__ 00032 00033 #include <stdexcept> 00034 #include <boost/type_traits.hpp> 00035 #include <boost/static_assert.hpp> 00036 #include <boost/cstdint.hpp> 00037 00038 namespace moost { namespace utils { 00039 00040 template<typename unsigned_intT> 00041 unsigned_intT next_power_of_two(unsigned_intT num) 00042 { 00043 // Only allow unsigned types (sign types get all messy!) 00044 BOOST_STATIC_ASSERT(boost::is_unsigned<unsigned_intT>::value); 00045 00046 // Only allow types that are 8, 16, 32 or 64 bits 00047 BOOST_STATIC_ASSERT( 00048 sizeof(unsigned_intT) == 8 || 00049 sizeof(unsigned_intT) == 4 || 00050 sizeof(unsigned_intT) == 2 || 00051 sizeof(unsigned_intT) == 1 00052 ); 00053 00054 // Make sure int_max_t is big enough to cope 00055 BOOST_STATIC_ASSERT(sizeof(boost::intmax_t) == 8); 00056 00057 // Convert to intmax so we can bitshift without warning for 00058 // types that have less bits that we are going to manupulate 00059 boost::intmax_t intmax = num; 00060 00061 --intmax; 00062 00063 switch(sizeof(unsigned_intT)) 00064 { 00065 case 8: // 64 bit 00066 intmax |= intmax >> 32; 00067 case 4: // 32 bit 00068 intmax |= intmax >> 16; 00069 case 2: // 16 bit 00070 intmax |= intmax >> 8; 00071 case 1: // 08 bit 00072 intmax |= intmax >> 4; 00073 intmax |= intmax >> 2; 00074 intmax |= intmax >> 1; 00075 break; 00076 } 00077 00078 return static_cast<unsigned_intT>(++intmax); 00079 } 00080 00081 template<typename unsigned_intT> 00082 bool is_power_of_two(unsigned_intT num) 00083 { 00084 // Only allow unsigned types 00085 BOOST_STATIC_ASSERT(boost::is_unsigned<unsigned_intT>::value); 00086 00087 return (0 == num) || (0 == ((num - 1) & num)); 00088 } 00089 00090 template<typename unsigned_intT> 00091 signed char msb_set(unsigned_intT num) 00092 { 00093 // Only allow unsigned types 00094 BOOST_STATIC_ASSERT(boost::is_unsigned<unsigned_intT>::value); 00095 00096 signed char cnt = -1; // No bits set 00097 while(num) { ++cnt; num >>= 1; } 00098 00099 return cnt; // LSB is 0 and MSB is N-1 where N is the number of bits 00100 } 00101 00102 }} 00103 00104 #endif // MOOST_UTILS_NEXT_POWER_OF_TWO_HPP__