jaulib v1.5.0
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
bitfield.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2022-2025 Gothel Software e.K.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * This Source Code Form is subject to the terms of the MIT License
8 * If a copy of the MIT was not distributed with this file,
9 * you can obtain one at https://opensource.org/license/mit/.
10 */
11#ifndef JAU_BITFIELD_HPP_
12#define JAU_BITFIELD_HPP_
13
14#include <unistd.h>
15
16#include <array>
17#include <cassert>
18#include <climits>
19#include <cmath>
20#include <cstring>
21#include <limits>
22#include <string_view>
23
24#include <jau/basic_types.hpp>
25#include <jau/byte_util.hpp>
26#include <jau/cpp_lang_util.hpp>
27#include <jau/int_math.hpp>
28#include <jau/int_math_ct.hpp>
29#include <jau/int_types.hpp>
30#include <jau/string_util.hpp>
31#include <jau/type_concepts.hpp>
32
33namespace jau {
34
35 /** \addtogroup ByteUtils
36 *
37 * @{
38 */
39
40 /**
41 * Simple statically sized bitfield template for efficient bit storage access.
42 *
43 * Bit-position and bit-order are in least-significant-bits (lsb) first.
44 *
45 * Implementations utilizes an in-memory `std::array<StorageType, (BitSize+StorageTypeBits-1)/StorageTypeBits>`
46 * with unsigned integral StorageType of sizeof(StorageType) <= sizeof(size_t).
47 *
48 * Similar to std::bitset, but providing custom methods.
49 *
50 * @see jau::bitheap
51 */
52 template<jau::req::unsigned_integral StorageType, size_t BitSize>
53 requires requires (StorageType) { sizeof(StorageType) <= sizeof(size_t); }
54 class bitfield_t {
55 public:
56 typedef StorageType unit_type; ///< Unit data type
57 typedef size_t size_type; ///< size_t data type, bit position and count
58 static constexpr size_type unit_byte_size = sizeof(unit_type); ///< One unit size in bytes
59 static constexpr size_type unit_bit_size = unit_byte_size * CHAR_BIT; ///< One unit size in bits
60 static constexpr size_type unit_shift = jau::log2_byteshift(unit_byte_size); ///< One unit shift amount
61 static constexpr size_type bit_size = BitSize; ///< Storage size in bits
62
63 /** Returns storage size in bits */
64 constexpr size_type size() const noexcept { return bit_size; }
65
66 /// Storage size in units
67 static constexpr size_type unit_size = std::max<size_type>(1, (bit_size + unit_bit_size - 1) >> unit_shift);
68
69 private:
70 static constexpr unit_type one_u = 1;
71
72 typedef std::array<unit_type, unit_size> storage_t;
73 storage_t storage;
74
75 public:
76 static constexpr bool in_range(size_type bitpos) { return bitpos < bit_size; }
77 static constexpr bool in_range(size_type bitpos, size_type length) {
78 return bitpos + length <= bit_size;
79 }
80
81 /** Constructs an empty bitfield instance */
82 constexpr bitfield_t() noexcept { clear(); }
83
84 /**
85 * Constructs a bitfield instance, initialized with `bitstr` msb bit-pattern.
86 * @param bitstr most-significat (msb) bit string pattern
87 * @throws jau::IllegalArgumentError if bitstr put failed
88 * @see put(std::string_view)
89 */
90 bitfield_t(std::string_view bitstr) {
91 clear();
92 if( !put(0, bitstr) ) {
93 throw jau::IllegalArgumentError("Invalid bit-patter "+std::string(bitstr), E_FILE_LINE);
94 }
95 }
96
97 /*** Clears whole bitfield, i.e. sets all bits to zero. */
98 constexpr void clear() noexcept {
99 std::memset(storage.data(), 0, unit_byte_size * unit_size);
100 }
101 /*** Clears whole bitfield, i.e. sets all bits to zero. */
102 constexpr bitfield_t &reset() noexcept {
103 clear();
104 return *this;
105 }
106
107 /*** Reads the bit value at position `bitpos`. */
108 constexpr bool operator[](size_type bitpos) const noexcept { return get(bitpos); }
109
110 /*** Reads the bit value at position `bitpos`. */
111 constexpr bool get(size_type bitpos) const noexcept {
112 if ( !in_range(bitpos) ) {
113 return false;
114 }
115 const size_type u = bitpos >> unit_shift;
116 const size_type b = bitpos - (u << unit_shift);
117 return storage[u] & (one_u << b);
118 }
119
120 /**
121 * Writes the bit value `v` to position `bitpos` into this storage.
122 * @returns true on success, otherwise false
123 */
124 constexpr bool put(size_type bitpos, bool v) noexcept {
125 if ( !in_range(bitpos) ) {
126 return false;
127 }
128 const size_type u = bitpos >> unit_shift;
129 const size_type b = bitpos - (u << unit_shift);
130 const unit_type m = one_u << b;
131 if ( v ) {
132 storage[u] |= m;
133 } else {
134 storage[u] &= ~m;
135 }
136 return true;
137 }
138
139 /**
140 * Flips the bit value at position `bitpos` in this storage.
141 * @returns true on success, otherwise false
142 */
143 constexpr bool flip(size_type bitpos) noexcept {
144 if ( !in_range(bitpos) ) {
145 return false;
146 }
147 const size_type u = bitpos >> unit_shift;
148 const size_type b = bitpos - (u << unit_shift);
149 const unit_type m = one_u << b;
150 if ( storage[u] & m ) {
151 storage[u] &= ~m;
152 } else {
153 storage[u] |= m;
154 }
155 return true;
156 }
157
158 /*** Flips all bits in this storage. */
159 constexpr bitfield_t &flip() noexcept {
160 size_type remaining = bit_size;
161 for ( size_type i = 0; i < unit_size; ++i ) {
162 storage[i] = ~storage[i] & bit_mask<unit_type>(remaining);
163 remaining -= unit_bit_size;
164 }
165 return *this;
166 }
167
168 /*** Reverse all bits in this storage. */
169 constexpr bitfield_t &reverse() noexcept {
170 const size_type s0 = bit_size & (unit_bit_size-1); // % unit_bit_size;
171 if( 0 == s0 ) { // fast-path, swap units
172 size_type l = 0, r = unit_size-1;
173 while ( l < r ) {
174 const unit_type v_l = jau::rev_bits(storage[l]);
175 const unit_type v_r = jau::rev_bits(storage[r]);
176 storage[l++] = v_r;
177 storage[r--] = v_l;
178 }
179 if( l == r ) { // last odd middle
180 storage[l] = jau::rev_bits(storage[l]);
181 }
182 } else { // slow-path, swap bits
183 for(size_type l = 0, r = bit_size-1; l < r; ++l, --r) {
184 const bool s = get(l);
185 (void)put(l, get(r));
186 (void)put(r, s);
187 }
188 }
189 return *this;
190 }
191 /**
192 * Sets the bit at position `bitpos` of this storage.
193 * @returns true on success, otherwise false
194 */
195 constexpr bool set(size_type bitpos) noexcept { return put(bitpos, true); }
196 /**
197 * Clear the bit at position `bitpos` of this storage.
198 * @returns true on success, otherwise false
199 */
200 constexpr bool clr(size_type bitpos) noexcept { return put(bitpos, false); }
201 /**
202 * Clear the bit at position `bitpos` of this storage.
203 * @returns true on success, otherwise false
204 */
205 constexpr bool reset(size_type bitpos) noexcept { return put(bitpos, false); }
206
207 /**
208 * Copies the bit at position `srcBitpos` to position `dstBitpos`, returning the copied bit-value.
209 * @returns true on success, otherwise false
210 */
211 bool copy(size_type srcBitpos, size_type dstBitpos) noexcept {
212 return put(dstBitpos, get(srcBitpos));
213 }
214
215 /*** Reads `length` bits from this storage, starting with the lowest bit from the storage position `bitpos`.*/
216 unit_type getUnit(size_type bitpos, size_type length) const noexcept {
217 if ( 0 == length || length > unit_bit_size || !in_range(bitpos, length) ) {
218 return 0;
219 }
220 const size_type u = bitpos >> unit_shift;
221 const size_type b = bitpos - (u << unit_shift);
222 if ( 0 == b ) {
223 // fast path
224 const unit_type m = bit_mask<unit_type>(length); // mask of chunk
225 return m & storage[u];
226 } else {
227 // slow path
228 const size_type left = unit_bit_size - b; // remaining bits of first chunk storage
229 const size_type l1 = std::min(length, left); // length of first chunk < unit_bit_size
230 const unit_type m1 = (one_u << l1) - one_u; // mask of first chunk
231 const unit_type d1 = m1 & (storage[u] >> b); // data of first chunk
232 const size_type l2 = length - l1; // length of second chunk < unit_bit_size
233 if ( l2 > 0 ) {
234 const unit_type m2 = (one_u << l2) - one_u; // mask of second chunk
235 return d1 | ((m2 & storage[u + 1]) << l1); // data combined chunk 1+2
236 } else {
237 return d1; // data of chunk 1 only
238 }
239 }
240 }
241
242 /**
243 * Writes `length` bits of given `data` into this storage, starting with the lowest bit from the storage position `bitpos`.
244 * @returns true on success, otherwise false
245 */
246 bool putUnit(size_type bitpos, size_type length, unit_type data) noexcept {
247 if ( 0 == length ) {
248 return true;
249 } else if ( length > unit_bit_size || !in_range(bitpos, length) ) {
250 return false;
251 }
252 const size_type u = bitpos >> unit_shift;
253 const size_type b = bitpos - (u << unit_shift);
254 if ( 0 == b ) {
255 // fast path
256 const unit_type m = bit_mask<unit_type>(length); // mask of chunk
257 storage[u] = ((~m) & storage[u]) // keep non-written storage bits
258 | (m & data); // overwrite storage w/ used data bits
259 } else {
260 // slow path
261 const size_type left = unit_bit_size - b; // remaining bits of first chunk storage
262 const size_type l1 = std::min(length, left); // length of first chunk < unit_bit_size
263 const unit_type m1 = (one_u << l1) - one_u; // mask of first chunk
264 storage[u] = ((~(m1 << b)) & storage[u]) // keep non-written storage bits
265 | ((m1 & data) << b); // overwrite storage w/ used data bits
266 const size_type l2 = length - l1; // length of second chunk < unit_bit_size
267 if ( l2 > 0 ) {
268 const unit_type m2 = (one_u << l2) - one_u; // mask of second chunk
269 /**
270 * g++ 4:14.2.0-1 Debian 13
271 * g++ bug: False positive of '-Warray-bounds'
272 * See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56456>
273 */
276 storage[u + 1] = ((~m2) & storage[u + 1]) // keep non-written storage bits
277 | (m2 & (data >> l1)); // overwrite storage w/ used data bits
279 }
280 }
281 return true;
282 }
283
284 /**
285 * Writes `bitstr` msb bit-pattern into this storage, starting with the lowest bit from the storage position `bitpos`.
286 * @param bitpos bit position to insert
287 * @param bitstr most-significat (msb) bit string pattern
288 * @returns true on success, otherwise false
289 */
290 bool put(size_type bitpos, std::string_view bitstr) noexcept {
291 if ( 0 == bitstr.size() ) {
292 return true;
293 } else if ( !in_range(bitpos, bitstr.size()) ) {
294 return false;
295 }
296 size_type left = bitstr.size();
297 size_type strPos = left - std::min(unit_bit_size, left);
298 while(left > 0) {
299 size_type len = std::min(unit_bit_size, left);
300 std::string_view segment = bitstr.substr(strPos, len);
301 const auto [val, sz, ok] = jau::fromBitString(segment, bit_order_t::msb);
302 if( !ok || sz != len || !putUnit(bitpos, len, unit_type(val)) ) {
303 return false;
304 }
305 bitpos += len;
306 strPos -= len;
307 left -= len;
308 }
309 return true;
310 }
311
312 /**
313 * Set `length` bits starting at `bitpos` of this bitfield to the given value `bit`.
314 * @returns true on success, otherwise false
315 */
316 bool set(size_type bitpos, size_type length, bool bit) noexcept {
317 if ( 0 == length ) {
318 return true;
319 } else if ( !in_range(bitpos, length) ) {
320 return false;
321 }
322 const unit_type v = bit ? std::numeric_limits<unit_type>::max() : 0;
323 size_type remaining = length;
324 size_type u = bitpos >> unit_shift;
325 {
326 const size_type b = bitpos - (u << unit_shift);
327 if ( b > 0 ) {
328 const size_type l = std::min(unit_bit_size-b, remaining);
329 if (!putUnit(bitpos, l, v)) { // first incomplete unit
330 return false;
331 }
332 remaining -= l;
333 bitpos += l;
334 u = bitpos >> unit_shift;
335 }
336 }
337 while ( remaining > unit_bit_size ) {
338 storage[u++] = v;
339 bitpos += unit_bit_size;
340 remaining -= unit_bit_size;
341 }
342 if ( remaining > 0 ) {
343 const size_type l = std::min(unit_bit_size, remaining);
344 if (!putUnit(bitpos, l, v)) { // last incomplete unit
345 return false;
346 }
347 remaining -= l;
348 }
349 assert(0 == remaining);
350 (void)remaining;
351 return true;
352 }
353 /** Set all bits of this bitfield to the given value `bit`. */
354 bitfield_t &setAll(bool bit) noexcept {
355 (void)set(0, bit_size, bit);
356 return *this;
357 }
358
359 /**
360 * Copies `length` bits at position `srcBitpos` to position `dstBitpos`, returning the copied bits.
361 * @returns true on success, otherwise false
362 */
363 bool copyUnit(size_type srcBitpos, size_type dstBitpos, size_type length) noexcept {
364 return putUnit(dstBitpos, length, getUnit(srcBitpos, length));
365 }
366
367 /*** Returns the number of set bits within this bitfield. */
368 size_type count() const noexcept {
369 size_type c = 0;
370 for ( size_type i = 0; i < unit_size; ++i ) {
371 c += jau::bit_count(storage[i]);
372 }
373 return c;
374 }
375 constexpr bool operator==(const bitfield_t &rhs) const noexcept {
376 if ( this == &rhs ) {
377 return true;
378 }
379 if ( unit_size != rhs.unit_size ) {
380 return false;
381 }
382 size_type i = 0;
383 while ( i < unit_size && storage[i] == rhs.storage[i] ) {
384 ++i;
385 }
386 return i == unit_size;
387 }
388
389 template<size_t OBitSize>
390 bool put(size_t bitpos, const bitfield_t<StorageType, OBitSize>& o) {
391 size_t length = o.bit_size;
392 if ( 0 == length ) {
393 return true;
394 } else if ( !in_range(bitpos, length) ) {
395 return false;
396 }
397 const size_type unit_count = ( length + unit_bit_size - 1 ) >> unit_shift;
398 const size_type unit_pos = bitpos >> unit_shift;
399 const size_type unit_bit_pos = bitpos - (unit_pos << unit_shift);
400 if ( 0 == unit_bit_pos ) {
401 size_type l = std::min(length, unit_bit_size);
402 size_type i = bitpos;
403 for ( size_type u = 0; u < unit_count && 0 < length; ++u ) {
404 if( !putUnit( i, l, o.storage[u] ) ) {
405 return false;
406 }
407 length -= l;
408 i += l;
409 l = std::min(length, unit_bit_size);
410 }
411 } else {
412 for ( size_type i = 0; i < length; ++i ) {
413 if( !put(bitpos + i, o.get(i)) ) {
414 return false;
415 }
416 }
417 }
418 return true;
419 }
420
421 template<size_t BitLength>
422 std::pair<bitfield_t<StorageType, BitLength>, bool> subbits(size_type bitpos) const noexcept {
423 if ( 0 == BitLength ) {
424 return { bitfield_t<StorageType, BitLength>(), true };
425 } else if ( !in_range(bitpos, BitLength) ) {
426 return { bitfield_t<StorageType, BitLength>(), false };
427 }
428 std::pair<bitfield_t<StorageType, BitLength>, bool> r{ bitfield_t<StorageType, BitLength>(), true };
429 size_type length = BitLength;
430 const size_type unit_count = ( BitLength + unit_bit_size - 1 ) >> unit_shift;
431 const size_type unit_pos = bitpos >> unit_shift;
432 const size_type unit_bit_pos = bitpos - (unit_pos << unit_shift);
433 if ( 0 == unit_bit_pos ) {
434 size_type l = std::min(length, unit_bit_size);
435 size_type i = 0;
436 for ( size_type u = unit_pos; u < unit_count && 0 < length; ++u ) {
437 if( !r.first.putUnit( i, l, storage[u] ) ) {
438 return { bitfield_t<StorageType, BitLength>(), false };
439 }
440 length -= l;
441 i += l;
442 l = std::min(length, unit_bit_size);
443 }
444 } else {
445 for(size_type i = 0; i < length; ++i) {
446 if( !r.first.put(i, get(bitpos+i)) ) {
447 return { bitfield_t<StorageType, BitLength>(), false };
448 }
449 }
450 }
451 return r;
452 }
453
454 std::string toString(size_type bitpos, size_type length, PrefixOpt prefix = PrefixOpt::none) const noexcept {
455 if ( 0 == length || !in_range(bitpos, length) ) {
456 return "";
457 }
458 std::string r;
459 r.reserve(length + (prefix == PrefixOpt::none ? 0 : 2));
460 if ( prefix == PrefixOpt::prefix ) {
461 r.append("0b");
462 }
463 const size_type unit_count = ( length + unit_bit_size - 1 ) >> unit_shift;
464 const size_type unit_pos = bitpos >> unit_shift;
465 const size_type bit_pos = bitpos - (unit_pos << unit_shift);
466 if ( 0 == bit_pos ) {
467 // fast path
468 const size_type sz0 = (unit_size - 1) * unit_bit_size;;
469 size_type l = length > sz0 ? length - sz0 : std::min(length, unit_bit_size);
470 for ( size_type i = unit_pos + unit_count; i-- > unit_pos && 0 < length; ) {
471 r.append( jau::toBitString(storage[i], bit_order_t::msb, PrefixOpt::none, l) );
472 length -= l;
473 l = std::min(length, unit_bit_size);
474 }
475 } else {
476 size_type i = bitpos + length;
477 while(length-- > 0) {
478 r.push_back(get(--i) ? '1' : '0');
479 }
480 }
481 return r;
482 }
483 std::string toString(PrefixOpt prefix = PrefixOpt::none) const noexcept {
484 return toString(0, bit_size, prefix);
485 }
486
487 std::string infoString() const noexcept {
488 return "bitfield[unit[bits "+std::to_string(unit_bit_size)+", count "+std::to_string(unit_size)+
489 "], bits"+std::to_string(bit_size)+": "+toString()+"]";
490 }
491 };
492
493 template<jau::req::unsigned_integral StorageType, size_t BitSize>
494 requires requires (StorageType) { sizeof(StorageType) <= sizeof(size_t); }
495 inline std::ostream &operator<<(std::ostream &out, const bitfield_t<StorageType, BitSize> &v) {
496 return out << v.toString();
497 }
498
499 /**
500 * Simple bitfield template for efficient bit storage access.
501 *
502 * Implementations utilizes an in-memory `std::array<StorageType = jau::nsize_t, (BitSize+StorageTypeBits-1)/StorageTypeBits>`.
503 *
504 * @see jau::bitfield_t
505 * @see jau::bitheap
506 * @see jau::nsize_t
507 */
508 template<size_t BitSize>
510
511 /**@}*/
512
513} // namespace jau
514
515#endif /* JAU_BITFIELD_HPP_ */
Simple statically sized bitfield template for efficient bit storage access.
Definition bitfield.hpp:54
constexpr bitfield_t & reset() noexcept
Definition bitfield.hpp:102
static constexpr bool in_range(size_type bitpos)
Definition bitfield.hpp:76
size_t size_type
size_t data type, bit position and count
Definition bitfield.hpp:57
constexpr bitfield_t & flip() noexcept
Definition bitfield.hpp:159
static constexpr size_type unit_shift
Definition bitfield.hpp:60
std::pair< bitfield_t< StorageType, BitLength >, bool > subbits(size_type bitpos) const noexcept
Definition bitfield.hpp:422
constexpr bool operator==(const bitfield_t &rhs) const noexcept
Definition bitfield.hpp:375
bool set(size_type bitpos, size_type length, bool bit) noexcept
Set length bits starting at bitpos of this bitfield to the given value bit.
Definition bitfield.hpp:316
bool putUnit(size_type bitpos, size_type length, unit_type data) noexcept
Writes length bits of given data into this storage, starting with the lowest bit from the storage pos...
Definition bitfield.hpp:246
bitfield_t(std::string_view bitstr)
Constructs a bitfield instance, initialized with bitstr msb bit-pattern.
Definition bitfield.hpp:90
bool put(size_t bitpos, const bitfield_t< StorageType, OBitSize > &o)
Definition bitfield.hpp:390
bitfield_t & setAll(bool bit) noexcept
Set all bits of this bitfield to the given value bit.
Definition bitfield.hpp:354
constexpr bool put(size_type bitpos, bool v) noexcept
Writes the bit value v to position bitpos into this storage.
Definition bitfield.hpp:124
static constexpr size_type unit_bit_size
Definition bitfield.hpp:59
static constexpr size_type unit_size
Definition bitfield.hpp:67
constexpr void clear() noexcept
Definition bitfield.hpp:98
std::string toString(PrefixOpt prefix=PrefixOpt::none) const noexcept
Definition bitfield.hpp:483
bool put(size_type bitpos, std::string_view bitstr) noexcept
Writes bitstr msb bit-pattern into this storage, starting with the lowest bit from the storage positi...
Definition bitfield.hpp:290
std::string infoString() const noexcept
Definition bitfield.hpp:487
constexpr bool clr(size_type bitpos) noexcept
Clear the bit at position bitpos of this storage.
Definition bitfield.hpp:200
constexpr bool set(size_type bitpos) noexcept
Sets the bit at position bitpos of this storage.
Definition bitfield.hpp:195
constexpr bitfield_t() noexcept
Constructs an empty bitfield instance.
Definition bitfield.hpp:82
constexpr bitfield_t & reverse() noexcept
Definition bitfield.hpp:169
bool copyUnit(size_type srcBitpos, size_type dstBitpos, size_type length) noexcept
Copies length bits at position srcBitpos to position dstBitpos, returning the copied bits.
Definition bitfield.hpp:363
static constexpr size_type unit_byte_size
Definition bitfield.hpp:58
std::string toString(size_type bitpos, size_type length, PrefixOpt prefix=PrefixOpt::none) const noexcept
Definition bitfield.hpp:454
static constexpr bool in_range(size_type bitpos, size_type length)
Definition bitfield.hpp:77
size_type count() const noexcept
Definition bitfield.hpp:368
bool copy(size_type srcBitpos, size_type dstBitpos) noexcept
Copies the bit at position srcBitpos to position dstBitpos, returning the copied bit-value.
Definition bitfield.hpp:211
StorageType unit_type
Unit data type.
Definition bitfield.hpp:56
constexpr bool operator[](size_type bitpos) const noexcept
Definition bitfield.hpp:108
unit_type getUnit(size_type bitpos, size_type length) const noexcept
Definition bitfield.hpp:216
constexpr bool reset(size_type bitpos) noexcept
Clear the bit at position bitpos of this storage.
Definition bitfield.hpp:205
constexpr bool get(size_type bitpos) const noexcept
Definition bitfield.hpp:111
static constexpr size_type bit_size
Definition bitfield.hpp:61
constexpr size_type size() const noexcept
Returns storage size in bits.
Definition bitfield.hpp:64
constexpr bool flip(size_type bitpos) noexcept
Flips the bit value at position bitpos in this storage.
Definition bitfield.hpp:143
bitfield_t< jau::nsize_t, BitSize > bitfield
Simple bitfield template for efficient bit storage access.
Definition bitfield.hpp:509
static constexpr T bit_mask(size_t n) noexcept
Returns the T bit mask of n-bits, i.e.
std::ostream & operator<<(std::ostream &out, const bitfield_t< StorageType, BitSize > &v)
Definition bitfield.hpp:495
constexpr uint8_t rev_bits(uint8_t v) noexcept
Reverse bits of one byte.
@ msb
Identifier for most-significant-bit (msb) first.
#define PRAGMA_DISABLE_WARNING_PUSH
#define E_FILE_LINE
#define PRAGMA_DISABLE_WARNING_ARRAY_BOUNDS
#define PRAGMA_DISABLE_WARNING_POP
constexpr size_t log2_byteshift(const size_t bytesize) noexcept
Returns log2(bytesize*8), e.g.
Definition int_math.hpp:150
constexpr size_t bit_count(T n) noexcept
Returns the number of set bits within given unsigned integral.
Definition int_math.hpp:220
std::string toBitString(const void *data, const nsize_t length, const bit_order_t bitOrder=bit_order_t::msb, const PrefixOpt prefix=PrefixOpt::prefix, size_t bit_len=0) noexcept
Produce a binary string representation of the given lsb-first byte values.
SizeBoolPair fromBitString(std::vector< uint8_t > &out, const uint8_t bitstr[], const size_t bitstr_len, const bit_order_t bitOrder=bit_order_t::msb, const Bool checkPrefix=Bool::True)
Converts a given binary string representation, appending to a byte vector (lsb-first).
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition backtrace.hpp:32
static const Mat4f m1(m1_0)
static const Mat4f m2(m2_0)