@ -27,28 +27,109 @@ constexpr uint32_t ceil_div(uint32_t x, uint32_t y)
}
}
template < typename Integer >
template < typename Integer >
Integer mask_ trailing_one s( size_t N )
Integer mask_ msb_zero s( size_t N )
{
{
static_assert ( std : : is_unsigned < Integer > : : value , " T must be unsigned integer " ) ;
static_assert ( std : : is_unsigned < Integer > : : value , " T must be unsigned integer " ) ;
return N = = 0 ? 0 : ( static_cast < Integer > ( - 1 ) >> ( sizeof ( Integer ) * 8U - N ) ) ;
return ( N = = 0 ) ? static_cast < Integer > ( - 1 ) : ( N = = sizeof ( Integer ) * 8U ) ? 0 : ( static_cast < Integer > ( -1 ) > > ( N ) ) ;
}
}
template < typename Integer >
template < typename Integer >
Integer mask_l eading _ones( size_t N )
Integer mask_l sb _ones( size_t N )
{
{
return ~ mask_trailing_one s< Integer > ( 8U * sizeof ( Integer ) - N ) ;
return mask_msb_zero s< Integer > ( sizeof ( Integer ) * 8U - N ) ;
}
}
template < typename Integer >
template < typename Integer >
Integer mask_ trailing_zero s( size_t N )
Integer mask_ msb_one s( size_t N )
{
{
return mask_leading_one s< Integer > ( 8U * sizeof ( Integer ) - N ) ;
return ~ mask_msb_zero s< Integer > ( N ) ;
}
}
template < typename Integer >
template < typename Integer >
Integer mask_l eading _zeros( size_t N )
Integer mask_l sb _zeros( size_t N )
{
{
return mask_trailing_ones < Integer > ( 8U * sizeof ( Integer ) - N ) ;
return ~ mask_lsb_ones < Integer > ( N ) ;
}
namespace detail {
template < typename Integer , size_t SizeOf >
struct zerobit_counter {
static Integer msb_count ( Integer value )
{
if ( value = = 0 ) {
return std : : numeric_limits < Integer > : : digits ;
}
Integer ret = 0 ;
for ( Integer shift = std : : numeric_limits < Integer > : : digits > > 1 ; shift ! = 0 ; shift > > = 1 ) {
Integer tmp = value > > shift ;
if ( tmp ! = 0 ) {
value = tmp ;
} else {
ret | = shift ;
}
}
return ret ;
}
static Integer lsb_count ( Integer value )
{
if ( value = = 0 ) {
return std : : numeric_limits < Integer > : : digits ;
}
Integer ret = 0 ;
for ( Integer shift = std : : numeric_limits < Integer > : : digits > > 1 , mask = std : : numeric_limits < Integer > : : max ( ) > > shift ;
shift ! = 0 ;
shift > > = 1 , mask > > = shift ) {
if ( ( value & mask ) = = 0 ) {
value > > = shift ;
ret | = shift ;
}
}
return ret ;
}
} ;
/// Specializations for unsigned
template < typename Integer >
struct zerobit_counter < Integer , sizeof ( unsigned ) > {
static Integer msb_count ( Integer value )
{
return ( value ) ? __builtin_clz ( value ) : std : : numeric_limits < Integer > : : digits ;
}
static Integer lsb_count ( Integer value )
{
return ( value ) ? __builtin_ctz ( value ) : std : : numeric_limits < Integer > : : digits ;
}
} ;
/// Specializations for unsigned long
template < typename Integer >
struct zerobit_counter < Integer , sizeof ( unsigned long ) > {
static Integer msb_count ( Integer value )
{
return ( value ) ? __builtin_clzl ( value ) : std : : numeric_limits < Integer > : : digits ;
}
static Integer lsb_count ( Integer value )
{
return ( value ) ? __builtin_ctzl ( value ) : std : : numeric_limits < Integer > : : digits ;
}
} ;
} // namespace detail
/// uses lsb as zero position
template < typename Integer >
Integer find_first_msb_one ( Integer value )
{
return ( value ) ? ( sizeof ( Integer ) * 8U - 1 - detail : : zerobit_counter < Integer , sizeof ( Integer ) > : : msb_count ( value ) )
: std : : numeric_limits < Integer > : : digits ;
}
/// uses lsb as zero position
template < typename Integer >
Integer find_first_lsb_one ( Integer value )
{
return detail : : zerobit_counter < Integer , sizeof ( Integer ) > : : lsb_count ( value ) ;
}
}
template < size_t N , bool reversed = false >
template < size_t N , bool reversed = false >
@ -139,35 +220,17 @@ public:
return * this ;
return * this ;
}
}
int find_ fir st( size_t startpos , size_t endpos , bool value = true ) const noexcept
int find_ lowe st( size_t startpos , size_t endpos , bool value = true ) const noexcept
{
{
assert_range_bounds_ ( startpos , endpos ) ;
assert_range_bounds_ ( startpos , endpos ) ;
if ( startpos = = endpos ) {
if ( startpos = = endpos ) {
return - 1 ;
return - 1 ;
}
}
size_t startword = startpos / bits_per_word ;
if ( not reversed ) {
size_t lastword = ( endpos - 1 ) / bits_per_word ;
return find_first_ ( startpos , endpos , value ) ;
for ( size_t i = startword ; i < = lastword ; + + i ) {
word_t w = buffer [ i ] ;
if ( not value ) {
w = ~ w ;
}
if ( i = = startword ) {
size_t offset = startpos % bits_per_word ;
w & = mask_trailing_zeros < word_t > ( offset ) ;
}
if ( i = = lastword ) {
size_t offset = ( endpos - 1 ) % bits_per_word ;
w & = mask_trailing_ones < word_t > ( offset + 1 ) ;
}
if ( w ! = 0 ) {
return static_cast < int > ( i * bits_per_word + ( bits_per_word - __builtin_clzl ( w ) - 1 ) ) ;
}
}
}
return - 1 ;
return find_first_reversed_ ( startpos , endpos , value ) ;
}
}
bool all ( ) const noexcept
bool all ( ) const noexcept
@ -328,33 +391,35 @@ private:
}
}
}
}
bool test_ ( size_t pos ) const noexcept
size_t get_bitidx_ ( size_t bitpos ) const noexcept { return reversed ? size ( ) - 1 - bitpos : bitpos ; }
bool test_ ( size_t bitpos ) const noexcept
{
{
pos = reversed ? size ( ) - 1 - pos : pos ;
bitpos = get_bitidx_ ( bitpos ) ;
return ( ( get_word_ ( pos) & maskbit ( pos) ) ! = static_cast < word_t > ( 0 ) ) ;
return ( ( get_word_ ( bit pos) & maskbit ( bit pos) ) ! = static_cast < word_t > ( 0 ) ) ;
}
}
void set_ ( size_t pos) noexcept
void set_ ( size_t bit pos) noexcept
{
{
pos = reversed ? size ( ) - 1 - pos : pos ;
bitpos = get_bitidx_ ( bitpos ) ;
get_word_ ( pos) | = maskbit ( pos) ;
get_word_ ( bit pos) | = maskbit ( bit pos) ;
}
}
void reset_ ( size_t pos) noexcept
void reset_ ( size_t bit pos) noexcept
{
{
pos = reversed ? size ( ) - 1 - pos : pos ;
bitpos = get_bitidx_ ( bitpos ) ;
get_word_ ( pos) & = ~ ( maskbit ( pos) ) ;
get_word_ ( bit pos) & = ~ ( maskbit ( bit pos) ) ;
}
}
size_t nof_words_ ( ) const noexcept { return size ( ) > 0 ? ( size ( ) - 1 ) / bits_per_word + 1 : 0 ; }
size_t nof_words_ ( ) const noexcept { return size ( ) > 0 ? ( size ( ) - 1 ) / bits_per_word + 1 : 0 ; }
word_t & get_word_ ( size_t pos) noexcept { return buffer [ pos / bits_per_word ] ; }
word_t & get_word_ ( size_t bitidx) noexcept { return buffer [ bitidx / bits_per_word ] ; }
const word_t & get_word_ ( size_t pos) const { return buffer [ pos / bits_per_word ] ; }
const word_t & get_word_ ( size_t bitidx) const { return buffer [ bitidx / bits_per_word ] ; }
size_t word_idx_ ( size_t pos ) const { return pos / bits_per_word ; }
size_t word_idx_ ( size_t pos ) const { return pos / bits_per_word ; }
void assert_within_bounds_ ( size_t pos , bool strict ) const
void assert_within_bounds_ ( size_t pos , bool strict ) const noexcept
{
{
srsran_assert ( pos < size ( ) or ( not strict and pos = = size ( ) ) ,
srsran_assert ( pos < size ( ) or ( not strict and pos = = size ( ) ) ,
" ERROR: index=%zd is out-of-bounds for bitset of size=%zd " ,
" ERROR: index=%zd is out-of-bounds for bitset of size=%zd " ,
@ -362,7 +427,7 @@ private:
size ( ) ) ;
size ( ) ) ;
}
}
void assert_range_bounds_ ( size_t startpos , size_t endpos ) const
void assert_range_bounds_ ( size_t startpos , size_t endpos ) const noexcept
{
{
srsran_assert ( startpos < = endpos and endpos < = size ( ) ,
srsran_assert ( startpos < = endpos and endpos < = size ( ) ,
" ERROR: range [%zd, %zd) out-of-bounds for bitsize of size=%zd " ,
" ERROR: range [%zd, %zd) out-of-bounds for bitsize of size=%zd " ,
@ -371,9 +436,89 @@ private:
size ( ) ) ;
size ( ) ) ;
}
}
static word_t maskbit ( size_t pos ) { return ( static_cast < word_t > ( 1 ) ) < < ( pos % bits_per_word ) ; }
static word_t maskbit ( size_t pos ) noexcept { return ( static_cast < word_t > ( 1 ) ) < < ( pos % bits_per_word ) ; }
static size_t max_nof_words_ ( ) noexcept { return ( N - 1 ) / bits_per_word + 1 ; }
int find_last_ ( size_t startpos , size_t endpos , bool value ) const noexcept
{
size_t startword = startpos / bits_per_word ;
size_t lastword = ( endpos - 1 ) / bits_per_word ;
for ( size_t i = lastword ; i ! = startpos - 1 ; - - i ) {
word_t w = buffer [ i ] ;
if ( not value ) {
w = ~ w ;
}
if ( i = = startword ) {
size_t offset = startpos % bits_per_word ;
w & = ( reversed ) ? mask_msb_zeros < word_t > ( offset ) : mask_lsb_zeros < word_t > ( offset ) ;
}
if ( i = = lastword ) {
size_t offset = ( endpos - 1 ) % bits_per_word ;
w & = ( reversed ) ? mask_msb_ones < word_t > ( offset + 1 ) : mask_lsb_ones < word_t > ( offset + 1 ) ;
}
if ( w ! = 0 ) {
return static_cast < int > ( i * bits_per_word + find_first_msb_one ( w ) ) ;
}
}
return - 1 ;
}
int find_first_ ( size_t startpos , size_t endpos , bool value ) const noexcept
{
size_t startword = startpos / bits_per_word ;
size_t lastword = ( endpos - 1 ) / bits_per_word ;
static size_t max_nof_words_ ( ) { return ( N - 1 ) / bits_per_word + 1 ; }
for ( size_t i = startword ; i < = lastword ; + + i ) {
word_t w = buffer [ i ] ;
if ( not value ) {
w = ~ w ;
}
if ( i = = startword ) {
size_t offset = startpos % bits_per_word ;
w & = mask_lsb_zeros < word_t > ( offset ) ;
}
if ( i = = lastword ) {
size_t offset = ( endpos - 1 ) % bits_per_word ;
w & = mask_lsb_ones < word_t > ( offset + 1 ) ;
}
if ( w ! = 0 ) {
return static_cast < int > ( i * bits_per_word + find_first_lsb_one ( w ) ) ;
}
}
return - 1 ;
}
int find_first_reversed_ ( size_t startpos , size_t endpos , bool value ) const noexcept
{
size_t startbitpos = get_bitidx_ ( startpos ) , lastbitpos = get_bitidx_ ( endpos - 1 ) ;
size_t startword = startbitpos / bits_per_word ;
size_t lastword = lastbitpos / bits_per_word ;
for ( size_t i = startword ; i ! = lastword - 1 ; - - i ) {
word_t w = buffer [ i ] ;
if ( not value ) {
w = ~ w ;
}
if ( i = = startword ) {
size_t offset = startbitpos % bits_per_word ;
w & = mask_lsb_ones < word_t > ( offset + 1 ) ;
}
if ( i = = lastword ) {
size_t offset = lastbitpos % bits_per_word ;
w & = mask_lsb_zeros < word_t > ( offset ) ;
}
if ( w ! = 0 ) {
word_t pos = find_first_msb_one ( w ) ;
return static_cast < int > ( size ( ) - 1 - ( pos + i * bits_per_word ) ) ;
}
}
return - 1 ;
}
} ;
} ;
template < size_t N , bool reversed >
template < size_t N , bool reversed >