8 #ifndef INCL_evo_bits_h     9 #define INCL_evo_bits_h    17     #pragma warning(disable:4146)    30 #if defined(__GNUC__) && !defined(EVO_NOBUILTIN_BITS) && !defined(EVO_GCC_NOBUILTIN_POPCOUNT)    31     template<
class T,
int S=sizeof(T)> 
struct BitsPopCount {
    32         static int popcount(uint32 mask) {
    33             return (uint)__builtin_popcount(mask);
    36     template<
class T> 
struct BitsPopCount<T,4> {
    37         static int popcount(uint32 mask) {
    39             return (uint)__builtin_popcount(mask);
    41             return (uint)__builtin_popcountl(mask);
    45     template<
class T> 
struct BitsPopCount<T,8> {
    46         static int popcount(uint64 mask) {
    47             return (uint)__builtin_popcountll(mask);
    51     template<
class T,
int S=sizeof(T)> 
struct BitsPopCount {
    52         static int popcount(uint32 mask) {
    53             mask -= ((mask >> 1) & 0x55555555);
    54             mask = (mask & 0x33333333) + ((mask >> 2) & 0x33333333);
    55             return (
int)((((mask + (mask >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
    58     template<
class T> 
struct BitsPopCount<T,8> {
    59         static int popcount(uint64 mask) {
    60             return BitsPopCount<uint32>::popcount((uint32)(mask & 0xFFFFFFFFUL)) +
    61                    BitsPopCount<uint32>::popcount((uint32)((mask >> 32) & 0xFFFFFFFFUL));
    68 #if defined(_MSC_VER) && !defined(EVO_NOBUILTIN_BITS)    70         template<
class T,
int S=sizeof(T)> 
struct BitsClz {
    73         template<
class T> 
struct BitsClz<T,1> {
    74             static uint clz(uint8 mask) {
    76                 if (_BitScanReverse(&i, (uint32)mask) == 0)
    81         template<
class T> 
struct BitsClz<T,2> {
    82             static uint clz(uint16 mask) {
    84                 if (_BitScanReverse(&i, (uint32)mask) == 0)
    86                 return (uint)(15 - i);
    89         template<
class T> 
struct BitsClz<T,4> {
    90             static uint clz(uint32 mask) {
    92                 if (_BitScanReverse(&i, mask) == 0)
    94                 return (uint)(31 - i);
    97         template<
class T> 
struct BitsClz<T,8> {
    98             static uint clz(uint64 mask) {
   101                 if (_BitScanReverse64(&i, mask) == 0)
   103                 return (uint)(63 - i);
   105                 if (_BitScanReverse(&i, ((mask >> 32) & 0x00000000FFFFFFFFUL)) != 0)
   106                     return (uint)(31 - i);
   107                 else if (_BitScanReverse(&i, (mask & 0x00000000FFFFFFFFUL)) != 0)
   108                     return (uint)(63 - i);
   120         __cpuid(cpuinfo, 0x00000001);
   121         return (cpuinfo[2] & 0x800000) != 0;
   124 #elif defined(__GNUC__) && !defined(EVO_NOBUILTIN_BITS)   126         template<
class T,
int S=sizeof(T)> 
struct BitsClz {
   129         template<
class T> 
struct BitsClz<T,1> {
   130             static uint clz(uint8 mask) {
   131                 const uint OFFSET = (
sizeof(uint) * 8) - 8;
   134                 return (uint)__builtin_clz((uint)mask) - OFFSET;
   137         template<
class T> 
struct BitsClz<T,2> {
   138             static uint clz(uint16 mask) {
   139                 const uint OFFSET = (
sizeof(uint) * 8) - 16;
   142                 return (uint)__builtin_clz((uint)mask) - OFFSET;
   145         template<
class T> 
struct BitsClz<T,4> {
   146             static uint clz(uint32 mask) {
   150                 return (uint)__builtin_clz(mask);
   152                 return (uint)__builtin_clzl(mask);
   156         template<
class T> 
struct BitsClz<T,8> {
   157             static uint clz(uint64 mask) {
   160                 return (uint)__builtin_clzll(mask);
   171         template<
class T,
int S=sizeof(T)> 
struct BitsClz {
   174         template<
class T> 
struct BitsClz<T,1> {
   175             static uint clz(uint8 mask) {
   181                 return 8 - BitsPopCount<T>::popcount(mask);
   184         template<
class T> 
struct BitsClz<T,2> {
   185             static uint clz(uint16 mask) {
   192                 return 16 - BitsPopCount<T>::popcount(mask);
   195         template<
class T> 
struct BitsClz<T,4> {
   196             static uint clz(uint32 mask) {
   203                 mask |= (mask >> 16);
   204                 return 32 - BitsPopCount<T>::popcount(mask);
   207         template<
class T> 
struct BitsClz<T,8> {
   208             static uint clz(uint64 mask) {
   215                 mask |= (mask >> 16);
   216                 mask |= (mask >> 32);
   217                 return 64 - BitsPopCount<T>::popcount(mask);
   243     return impl::BitsPopCount<T>::popcount(mask);
   256     return impl::BitsClz<T>::clz(mask);
   266     return impl::BitsClz<uint8>::clz(mask);
   276     return impl::BitsClz<uint16>::clz(mask);
   286     return impl::BitsClz<uint32>::clz(mask);
   296     return impl::BitsClz<uint64>::clz(mask);
   308 template<
class T=u
long,
class TSize=SizeT>
   313     static const uint BYTES        = 
sizeof(T);             
   314     static const uint BITS         = BYTES * 8;             
   315     static const uint BITS_MINUS_1 = BITS - 1;              
   316     static const T    RBIT         = 0x01;                  
   317     static const T    LBIT         = RBIT << BITS_MINUS_1;  
   318     static const T    ZERO         = 0;                     
   319     static const T    ALLBITS      = T(~ZERO);              
   332         return value << (BITS - count);
   346         return value >> (BITS - count);
   358     static T 
mask(uint start, uint count) {
   359         assert( start + count <= BITS );
   361             return (((RBIT << count) - 1) << (BITS - (start + count)));
   362         return -(LBIT >> (count - 1));
   375         if (start < BITS && count > 0) {
   376             const uint end = start + count;
   380                     return (((RBIT << count) - 1) << (BITS - end));
   381                 return -(LBIT >> (count - 1));
   382             } 
else if (start > 0)
   383                 return (LBIT >> (start - 1)) - 1;
   397         return (bitsize + BITS_MINUS_1) / BITS;
   408         return (chunks * BITS);
   421         for (Size pos = 0, i = 0; pos < bitsize; pos += BITS, ++i)
   423         assert( count <= bitsize );
   438         if (pos < bitsize && count > 0) {
   444             Size       index  = (pos / BITS);
   445             const Size offset = pos - (index * BITS);
   446             const Size offset_end = offset + count;
   447             const T* p = data + index;
   448             if (offset_end <= BITS) {
   450                 const T maskval = (count == BITS ? ALLBITS : (((RBIT << count) - 1) << (BITS - offset_end)));
   457                     count -= (BITS - offset);
   463                 while (count >= BITS) {
   488         Size i = 0, sz = bitsize / BITS;
   490             if (data[i] != ALLBITS)
   492         Size pos = bitsize - (i * BITS);
   494             if ((data[i] | ((LBIT >> (pos - 1)) - 1)) != ALLBITS)
   510         if (pos < bitsize && count > 0) {
   516             Size       index  = (pos / BITS);
   517             const Size offset = pos - (index * BITS);
   518             const Size offset_end = offset + count;
   519             const T* p = data + index;
   520             if (offset_end <= BITS) {
   522                 const T maskval = (count == BITS ? ALLBITS :  (((RBIT << count) - 1) << (BITS - offset_end)));
   523                 return (*p | (T)~maskval) == ALLBITS;
   527                     count -= (BITS - offset);
   528                     if ((*p | (T)~((LBIT >> (offset - 1)) - 1)) != ALLBITS)
   534                 while (count >= BITS) {
   542                 return (count == 0 || (*p | (T)~-(LBIT >> (count - 1))) == ALLBITS);
   556         for (Size pos = 0, i = 0; pos < bitsize; pos += BITS, ++i)
   573         if (pos < bitsize && count > 0) {
   579             Size       index  = (pos / BITS);
   580             const Size offset = pos - (index * BITS);
   581             const Size offset_end = offset + count;
   582             const T* p = data + index;
   583             if (offset_end <= BITS) {
   585                 const T maskval = (count == BITS ? ALLBITS :  (((RBIT << count) - 1) << (BITS - offset_end)));
   586                 return (*p & maskval) != ZERO;
   590                     count -= (BITS - offset);
   591                     if ((*p & (T)((LBIT >> (offset - 1)) - 1)) != ZERO)
   597                 while (count >= BITS) {
   605                 return (count != 0 && (*p & (T)-(LBIT >> (count - 1))) != ZERO);
   643         state.
size = (bitsize + BITS - 1) / BITS;
   644         for (Size i = 0, sz = state.
size; i < sz; ++i) {
   646                 state.
chunk = data[i];
   649                 return state.
pos + (i * BITS);
   665         Size i  = state.
index;
   666         Size sz = state.
size;
   669             if (state.
pos < BITS_MINUS_1) {
   670                 state.
chunk &= ((LBIT >> state.
pos) - 1);
   671                 if (state.
chunk != 0) {
   674                     return state.
pos + (i * BITS);
   680             for (
const T* data = state.
data; i < sz; ++i) {
   682                     state.
chunk = data[i];
   685                     return state.
pos + (i * BITS);
   702     static bool array_get(
const T* data, Size bitsize, Size pos) {
   705             const Size i = (pos / BITS);
   706             return ( data[i] & (LBIT >> (pos - (i * BITS))) ) != 0;
   721     static bool array_set(T* data, Size bitsize, Size pos, 
bool value=
true) {
   724             const Size i = (pos / BITS);
   725             const T mask = (LBIT >> (pos - (i * BITS)));
   747     #if defined(EVO_OLDCC) // Fixes undefined reference on older compilers   752         if (pos < bitsize && count > 0) {
   760             Size       index  = (pos / BITS);
   761             const Size offset = pos - (index * BITS);
   762             const Size offset_end = offset + count;
   765             if (offset_end <= BITS) {
   767                 maskval = (count == BITS ? ALLBITS :  (((RBIT << count) - 1) << (BITS - offset_end)));
   775                     count -= (BITS - offset);
   776                     maskval = (LBIT >> (offset - 1)) - 1;
   785                 maskval = (value ? ALLBITS : ZERO);
   786                 while (count >= BITS) {
   794                     maskval = -(LBIT >> (count - 1));
   818             const Size i = (pos / BITS);
   819             data[i] ^= (LBIT >> (pos - (i * BITS)));
   837         if (pos < bitsize && count > 0) {
   845             Size       index  = (pos / BITS);
   846             const Size offset = pos - (index * BITS);
   847             const Size offset_end = offset + count;
   849             if (offset_end <= BITS) {
   851                 const T maskval = (count == BITS ? ALLBITS :  (((RBIT << count) - 1) << (BITS - offset_end)));
   856                     count -= (BITS - offset);
   857                     *p ^= (LBIT >> (offset - 1)) - 1;
   862                 while (count >= BITS) {
   870                     *p ^= -(LBIT >> (count - 1));
   895     static bool array_store(T* data, Size bitsize, Size pos, Size count, U value) {
   899                 count = (Size)IntegerT<U>::BITS;
   907             if (count < (Size)IntegerT<U>::BITS)
   911             Size       index  = (pos / BITS);
   912             const Size offset = pos - (index * BITS);
   913             const Size offset_end = offset + count;
   916             if (offset_end <= BITS) {
   918                 const uint lshift = BITS - offset_end;
   919                 maskval = (count == BITS ? 0 : ~(((RBIT << count) - 1) << lshift));
   920                 *p = (*p & maskval) | (T(uvalue) << lshift);
   924                     count -= (BITS - offset);
   925                     maskval = (LBIT >> (offset - 1)) - 1;
   926                     *p = (*p & ~maskval) | (T(uvalue >> count) & maskval);
   931                 while (count >= BITS) {
   933                     *p = T(uvalue >> count);
   939                     maskval = -(LBIT >> (count - 1));
   940                     *p = (*p & ~maskval) | ((T(uvalue) << (BITS - count)) & maskval);
   962     template<
class U EVO_ONCPP11(=u
int32)>
   966         if (pos < bitsize && count > 0) {
   971                 count = (Size)IntegerT<U>::BITS;
   973             Size       index  = (pos / BITS);
   974             const Size offset = pos - (index * BITS);
   975             const Size offset_end = offset + count;
   976             const T* ptr = data + index;
   978             if (offset_end <= BITS) {
   982                 return U( (*ptr & (T(~(ALLBITS >> count)) >> offset)) >> (BITS - offset_end) )
   983                     << ((Size)IntegerT<U>::BITS - count); 
   991                     count -= (BITS - offset);
   992                     result = U(*ptr & (ALLBITS >> offset)) << count;
   998                 while (count >= BITS) {
  1000                     result |= U(*ptr) << count;
  1006                     result |= (*ptr & ~(ALLBITS >> count)) >> (BITS - count);
  1009                 return result << ((Size)IntegerT<U>::BITS - bitsize);
  1032     template<
class U EVO_ONCPP11(=u
int32)>
  1036         if (pos < bitsize && count > 0) {
  1038                 count = (Size)IntegerT<U>::BITS;
  1042             if (count > bitsize) {
  1044                 truncbits = count - bitsize;
  1048             Size       index  = (pos / BITS);
  1049             const Size offset = pos - (index * BITS);
  1050             const Size offset_end = offset + count;
  1051             const T* ptr = data + index;
  1054             if (offset_end <= BITS) {
  1059                     result = U( (*ptr & (T(~(ALLBITS >> count)) >> offset)) >> (BITS - offset_end) );
  1063                     count -= (BITS - offset);
  1064                     result = U(*ptr & (ALLBITS >> offset)) << count;
  1070                 while (count >= BITS) {
  1072                     result |= U(*ptr) << count;
  1078                     result |= (*ptr & ~(ALLBITS >> count)) >> (BITS - count);
  1081             assert( truncbits < (Size)IntegerT<U>::BITS );
  1082             return result << truncbits;
  1100     static Size 
array_copy(T* data, Size bitsize, T* src_data, Size src_bitsize, Size src_pos=0, Size src_count=
ALL) {
  1102         if (src_pos < src_bitsize && src_count > 0) {
  1103             if (src_count > bitsize)
  1104                 src_count = bitsize;
  1107             src_bitsize -= src_pos;
  1108             if (src_count > src_bitsize)
  1109                 src_count = src_bitsize;
  1111                 src_bitsize = src_count;
  1113             Size       src_index  = (src_pos / BITS);
  1114             const Size src_offset = src_pos - (src_index * BITS);
  1115             const Size src_offset_end = src_offset + src_count;
  1116             const T* src_p = src_data + src_index;
  1117             if (src_offset_end <= BITS) {
  1119                 *data = (*data & ~(ALLBITS << src_offset)) | ((*src_p & (ALLBITS >> src_offset)) << src_offset);
  1120             } 
else if (src_offset > 0) {
  1122                 const Size leadbits = (BITS - src_offset);
  1123                 T maskval1 = ALLBITS >> src_offset;
  1124                 T maskval2 = ~maskval1;
  1125                 while (src_count >= BITS) {
  1127                     *data = ((*src_p & maskval1) << src_offset) | ((src_p[1] & maskval2) >> leadbits);
  1132                 if (src_count > 0) {
  1133                     maskval1 = ALLBITS >> src_count;
  1134                     maskval2 = ~maskval1;
  1135                     *data = (*data & maskval1) | ((*src_p << src_offset) & maskval2);
  1139                 while (src_count >= BITS) {
  1146                 if (src_count > 0) {
  1147                     const T maskval = ALLBITS >> src_count;
  1148                     *data = (*data & maskval) | (*src_p & ~maskval);
  1165         assert( count >= 0 );
  1167             if (count >= bitsize) {
  1168                 array_set_multi(data, bitsize, 0, 
ALL, 
false);
  1170                 const Size chunks = count / BITS;
  1171                 const Size offset = count - (chunks * BITS);
  1173                 const T* p_in  = data + chunks;
  1174                 const T* p_end = data + (bitsize / BITS);
  1177                     const Size rbits = BITS - offset;
  1178                     const T* p_shift_end = p_end - chunks - 1;
  1179                     while (p_out < p_shift_end) {
  1180                         *p_out = (*p_in << offset) | (p_in[1] >> rbits);
  1184                     *p_out = (*p_in << offset);
  1188                     const T* p_shift_end = p_end - chunks;
  1189                     while (p_out < p_shift_end) {
  1197                 for (; p_out < p_end; ++p_out)
  1213             if (count >= bitsize) {
  1214                 array_set_multi(data, bitsize, 0, 
ALL, 
false);
  1216                 const Size chunks = count / BITS;
  1217                 const Size offset = count - (chunks * BITS);
  1218                 T*       p_out = data + ((bitsize + (BITS-1)) / BITS);;
  1219                 const T* p_in  = p_out - chunks - 1;
  1222                     const Size lbits = BITS - offset;
  1223                     const T* p_shift_end = data + chunks + 1;
  1224                     const Size partial_tail = bitsize % BITS;
  1225                     if (partial_tail > 0) {
  1227                         if (p_out > p_shift_end) {
  1229                             *--p_out = ((*p_in << lbits) | (p_in[1] >> offset)) & ~(ALLBITS >> partial_tail);
  1231                             *--p_out = (*p_in >> offset) & ~(ALLBITS >> partial_tail);
  1235                     while (p_out > p_shift_end) {
  1237                         *--p_out = (*p_in << lbits) | (p_in[1] >> offset);
  1239                     *--p_out = (*p_in >> offset);
  1242                     const T* p_shift_end = data + chunks;
  1243                     while (p_out > p_shift_end) {
  1250                 while (p_out > data)
  1260 #if defined(_MSC_VER)  1261     #pragma warning(pop) const T * data
Definition: bits.h:616
 
static Size array_set_multi(T *data, Size bitsize, Size pos=0, Size count=ALL, bool value=true)
Set or clear count bits at position in chunked bit array. 
Definition: bits.h:746
 
static Size array_iternext(IterState &state)
Iterate to next set bit in array. 
Definition: bits.h:664
 
static bool array_toggle(T *data, Size bitsize, Size pos)
Toggle bit at position in chunked bit array. 
Definition: bits.h:815
 
static bool array_get(const T *data, Size bitsize, Size pos)
Get bit at position from chunked bit array. 
Definition: bits.h:702
 
static void array_shiftl(T *data, Size bitsize, uint count)
Shift to the left in chunked bit array. 
Definition: bits.h:1163
 
uint bits_clz64(uint64 mask)
Get leading zero count on bitmask (uint64). 
Definition: bits.h:295
 
Size size
Definition: bits.h:617
 
uint bits_clz16(uint16 mask)
Get leading zero count on bitmask (uint16). 
Definition: bits.h:275
 
uint bits_clz(T mask)
Get leading zero count on bitmask. 
Definition: bits.h:255
 
static bool array_checkall(const T *data, Size bitsize)
Check if all bits are set in bit array. 
Definition: bits.h:486
 
static T align_right(T value, uint count)
Align bits on left to the right. 
Definition: bits.h:343
 
static U array_extractl(const T *data, Size bitsize, Size pos, Size count)
Extract bits from chunked bit array. 
Definition: bits.h:963
 
static T align_left(T value, uint count)
Align bits on right to the left. 
Definition: bits.h:329
 
int bits_popcount(T mask)
Get population count (number of bits set) for value. 
Definition: bits.h:242
 
Basic integer type. 
Definition: type.h:980
 
static Size array_countbits(const T *data, Size bitsize, Size pos, Size count)
Count number of set bits in subset of bit array. 
Definition: bits.h:436
 
static Size array_toggle_multi(T *data, Size bitsize, Size pos=0, Size count=ALL)
Toggle count bits at position in chunked bit array. 
Definition: bits.h:835
 
static bool array_store(T *data, Size bitsize, Size pos, Size count, U value)
Stores bits in chunked bit array. 
Definition: bits.h:895
 
static Size array_copy(T *data, Size bitsize, T *src_data, Size src_bitsize, Size src_pos=0, Size src_count=ALL)
Copy bits from another array. 
Definition: bits.h:1100
 
IterState()
Definition: bits.h:622
 
uint bits_clz8(uint8 mask)
Get leading zero count on bitmask (uint8). 
Definition: bits.h:265
 
T Type
Translated type. 
Definition: meta.h:373
 
static bool array_checkany(const T *data, Size bitsize, Size pos, Size count)
Check if any bits are set in subset of bit array. 
Definition: bits.h:571
 
static Size array_countbits(const T *data, Size bitsize)
Count number of set bits in bit array. 
Definition: bits.h:418
 
static const EndT ALL
Special integer value for indicating all items or all remaining items. 
Definition: type.h:1839
 
static U array_extractr(const T *data, Size bitsize, Size pos, Size count)
Extract bits from chunked bit array. 
Definition: bits.h:1033
 
T Value
Chunk value type. 
Definition: bits.h:310
 
Size pos
Definition: bits.h:619
 
static T mask(uint start, uint count)
Get bitmask with count bits set from start position. 
Definition: bits.h:358
 
uint bits_clz32(uint32 mask)
Get leading zero count on bitmask (uint32). 
Definition: bits.h:285
 
Evo C++ Library namespace. 
Definition: alg.h:11
 
static const EndT NONE
Special integer value for indicating no item or unknown item. 
Definition: type.h:1832
 
static T safemask(uint start, uint count)
Get bitmask with count bits set from start position, with bounds checking for safety. 
Definition: bits.h:374
 
static bool array_set(T *data, Size bitsize, Size pos, bool value=true)
Set or clear bit at position in chunked bit array. 
Definition: bits.h:721
 
static bool array_checkall(const T *data, Size bitsize, Size pos, Size count)
Check if all bits are set in subset of bit array. 
Definition: bits.h:508
 
bool bits_cpu_popcnt()
Runtime check whether current CPU supports the POPCNT instruction. 
Definition: bits.h:231
 
static Size array_iter(IterState &state, const T *data, Size bitsize)
Iterate to first set bit in array. 
Definition: bits.h:641
 
Bit array iteration state. 
Definition: bits.h:615
 
static void array_shiftr(T *data, Size bitsize, uint count)
Shift to the right in chunked bit array. 
Definition: bits.h:1210
 
Size index
Definition: bits.h:618
 
static Size array_size(Size bitsize)
Calculate array size in chunks for number of bits. 
Definition: bits.h:396
 
TSize Size
Size integer type. 
Definition: bits.h:311
 
T chunk
Definition: bits.h:620
 
Traits and helpers for bit manipulation. 
Definition: bits.h:309
 
static Size array_bitsize(Size chunks)
Calculate array size in bits for number of chunks. 
Definition: bits.h:407
 
Evo basic types and traits. 
 
static bool array_checkany(const T *data, Size bitsize)
Check if any bits are set in bit array. 
Definition: bits.h:555