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