31 template <
typename T_Type>
54 template <std::unsigned_integral T_Type,
UST... t_bit_values>
55 [[nodiscard]] consteval
auto bit_construct([[maybe_unused]]
bool left_is_low =
false) noexcept -> T_Type;
79 template <
UST t_num_int_bits, std::unsigned_integral T_Type,
UST... t_integers>
96 template <std::unsigned_integral T_Type,
UST t_num_bits>
110 template <std::unsigned_integral T_Type>
111 constexpr
void clear_bit(T_Type& integer,
UST index) noexcept;
126 template <
UST t_num_bits, std::unsigned_integral T_Type>
127 constexpr
void clear_bits(T_Type& integer,
UST index) noexcept;
148 template <
UST t_index,
150 std::unsigned_integral T_Type =
UST,
151 std::unsigned_integral T_ReturnType = T_Type>
152 [[nodiscard]] constexpr auto
get_bit(T_Type integer) noexcept -> T_ReturnType;
173 template <std::unsigned_integral T_Type =
UST, std::unsigned_integral T_ReturnType = T_Type>
174 [[nodiscard]] constexpr auto
get_bit(T_Type integer,
UST index,
I32 shift = 0) noexcept -> T_ReturnType;
194 template <
UST t_index,
195 bool t_shift_right = true,
196 std::unsigned_integral T_Type =
UST,
197 std::unsigned_integral T_ReturnType = T_Type>
198 [[nodiscard]] constexpr auto
get_bit_shift_max(T_Type integer) noexcept -> T_ReturnType;
218 template <
bool t_shift_right = true, std::unsigned_integral T_Type =
UST, std::unsigned_integral T_ReturnType = T_Type>
219 [[nodiscard]] constexpr auto
get_bit_shift_max(T_Type integer,
UST index) noexcept -> T_ReturnType;
243 template <
UST t_index,
246 std::unsigned_integral T_Type =
UST,
247 std::unsigned_integral T_ReturnType = T_Type>
248 [[nodiscard]] constexpr auto
get_bits(T_Type integer) noexcept -> T_ReturnType;
272 template <
UST t_num_bits, std::unsigned_integral T_Type =
UST, std::unsigned_integral T_ReturnType = T_Type>
273 [[nodiscard]] constexpr auto
get_bits(T_Type integer,
UST index,
I32 shift = 0) noexcept -> T_ReturnType;
295 template <
UST t_index,
297 bool t_shift_right = true,
298 std::unsigned_integral T_Type =
UST,
299 std::unsigned_integral T_ReturnType = T_Type>
300 [[nodiscard]] constexpr auto
get_bits_shift_max(T_Type integer) noexcept -> T_ReturnType;
322 template <
UST t_num_bits,
323 bool t_shift_right = true,
324 std::unsigned_integral T_Type =
UST,
325 std::unsigned_integral T_ReturnType = T_Type>
341 template <typename T_Type>
342 [[nodiscard]] constexpr auto
is_bit_set(T_Type integer,
UST index) noexcept ->
bool;
355 template <std::unsigned_integral T_Type>
356 constexpr
void set_bit(T_Type& integer,
UST index) noexcept;
371 template <
UST t_value, std::unsigned_integral T_Type>
372 constexpr
void set_bit_to(T_Type& integer,
UST index) noexcept;
387 template <
UST t_num_bits, std::unsigned_integral T_Type>
388 constexpr
void set_bits(T_Type& integer,
UST index) noexcept;
408 template <
UST t_num_bits,
bool t_clear_bits = true, std::unsigned_integral T_Type>
419 #include <initializer_list>
434 template <std::
integral T_Type>
435 [[nodiscard]] constexpr
auto abs(T_Type value) noexcept -> T_Type
437 if constexpr (std::is_unsigned_v<T_Type>)
445 int const mask = value >> (
sizeof(T_Type) * CHAR_BIT - 1);
446 return (value + mask) ^ mask;
458 template <std::unsigned_integral T_Type,
UST... t_bit_values>
459 [[nodiscard]] consteval
auto bit_construct([[maybe_unused]]
bool left_is_low) noexcept -> T_Type
461 static_assert(
sizeof...(t_bit_values) <= num_bits<T_Type>,
"Number of bit values exceeds number of type bits.");
464 if constexpr (
sizeof...(t_bit_values) != 0)
469 (void) std::initializer_list<I32>{(set_bit_to<t_bit_values>(integer, bit_index++), 0)...};
473 UST bit_index =
sizeof...(t_bit_values) - 1;
474 (void) std::initializer_list<I32>{(set_bit_to<t_bit_values>(integer, bit_index--), 0)...};
483 template <std::
unsigned_
integral T_Type, UST t_num_bits>
489 if constexpr (t_num_bits >= num_bits<T_Type>)
490 return static_cast<T_Type
>(~(T_Type(0)));
492 return static_cast<T_Type
>(((
UST(1)) << t_num_bits) - 1);
498 template <UST t_num_int_bits, std::unsigned_integral T_Type, UST... t_integers>
501 static_assert(
sizeof...(t_integers) * t_num_int_bits <= num_bits<T_Type>,
502 "Totoal number of provided bits exceeds number of type bits.");
508 (void) std::initializer_list<I32>{(set_bits_with_int<t_num_int_bits, false>(integer, bit_index, t_integers),
509 bit_index += t_num_int_bits,
514 UST bit_index = (
sizeof...(t_integers) - 1) * t_num_int_bits;
515 (void) std::initializer_list<I32>{(set_bits_with_int<t_num_int_bits, false>(integer, bit_index, t_integers),
516 bit_index -= t_num_int_bits,
526 template <std::
unsigned_
integral T_Type>
529 assert(index < num_bits<T_Type> &&
"Index exceeds number of bits.");
531 integer &=
static_cast<T_Type
>(~(
UST(1) << index));
537 template <UST t_num_bits, std::
unsigned_
integral T_Type>
540 assert(index + t_num_bits <= num_bits<T_Type>);
542 constexpr
UST bits = bit_construct_set_first_n_bits<UST, t_num_bits>();
543 integer &=
static_cast<T_Type
>(~(bits << index));
549 template <UST t_index, I32 t_shift, std::
unsigned_
integral T_Type, std::
unsigned_
integral T_ReturnType>
550 [[nodiscard]] constexpr
auto get_bit(T_Type integer) noexcept -> T_ReturnType
552 static_assert(t_index < num_bits<T_Type>,
"Index exceeds number of bits");
554 T_ReturnType bit = (integer &
static_cast<T_Type
>(
UST(1) << t_index));
556 if constexpr (t_shift == 0)
558 else if constexpr (t_shift > 0)
560 static_assert(t_index + t_shift < num_bits<T_ReturnType>,
"Shift exceeds highest bit.");
561 return bit << static_cast<UST>(t_shift);
565 static_assert(t_index >= -t_shift,
"Shift exceeds lowest bit");
574 template <std::
unsigned_
integral T_Type, std::
unsigned_
integral T_ReturnType>
575 [[nodiscard]] constexpr
auto get_bit(T_Type integer,
UST index,
I32 shift) noexcept -> T_ReturnType
577 assert(index < num_bits<T_Type>);
579 T_ReturnType bit = (integer &
static_cast<T_Type
>(
UST(1) << index));
583 assert(index + shift < num_bits<T_ReturnType>);
584 return bit << static_cast<UST>(shift);
594 template <UST t_index,
bool t_shift_right, std::
unsigned_
integral T_Type, std::
unsigned_
integral T_ReturnType>
598 constexpr
I32 shift =
599 t_shift_right ? -
static_cast<I32>(t_index) :
static_cast<I32>(num_bits<T_ReturnType> - t_index - 1);
600 return get_bit<t_index, shift, T_Type, T_ReturnType>(integer);
606 template <
bool t_shift_right, std::
unsigned_
integral T_Type, std::
unsigned_
integral T_ReturnType>
609 if constexpr (t_shift_right)
610 return get_bit<T_Type, T_ReturnType>(integer, index, -
static_cast<I32>(index));
612 return get_bit<T_Type, T_ReturnType>(integer, index,
static_cast<I32>(num_bits<T_ReturnType> - index - 1));
618 template <UST t_index, UST t_num_bits, I32 t_shift, std::
unsigned_
integral T_Type, std::
unsigned_
integral T_ReturnType>
619 [[nodiscard]] constexpr
auto get_bits(T_Type integer) noexcept -> T_ReturnType
621 static_assert(t_num_bits > 1,
"Number of bits must be larger than 0.");
622 static_assert(t_index + t_num_bits <= num_bits<T_Type>,
"Required bits exceed maximum number of bits.");
624 constexpr
UST mask = bit_construct_set_first_n_bits<UST, t_num_bits>() << t_index;
625 auto bits =
static_cast<T_ReturnType
>(integer & mask);
627 if constexpr (t_shift == 0)
629 static_assert(t_index + t_num_bits <= num_bits<T_ReturnType>,
"Shifted bits exceed highest bit.");
632 else if constexpr (t_shift > 0)
634 static_assert(t_index + t_num_bits + t_shift <= num_bits<T_ReturnType>,
"Shifted bits exceed highest bit.");
635 return bits << static_cast<UST>(t_shift);
639 static_assert(t_index >= -t_shift,
"Shifted bits exceed lowest bit.");
647 template <UST t_num_bits, std::
unsigned_
integral T_Type, std::
unsigned_
integral T_ReturnType>
648 [[nodiscard]] constexpr
auto get_bits(T_Type integer,
UST index,
I32 shift) noexcept -> T_ReturnType
650 static_assert(t_num_bits > 1,
"Number of bits must be larger than 0.");
651 assert(index + t_num_bits <= num_bits<T_Type>);
653 UST mask = bit_construct_set_first_n_bits<UST, t_num_bits>() << index;
654 auto bits =
static_cast<T_ReturnType
>(integer & mask);
658 assert(index + t_num_bits + shift <= num_bits<T_ReturnType>);
659 return bits << static_cast<UST>(shift);
669 template <UST t_index,
672 std::unsigned_integral T_Type,
673 std::unsigned_integral T_ReturnType>
677 constexpr
I32 shift = t_shift_right ? -
static_cast<I32>(t_index)
678 :
static_cast<I32>(num_bits<T_ReturnType> - t_index - t_num_bits);
679 return get_bits<t_index, t_num_bits, shift, T_Type, T_ReturnType>(integer);
685 template <UST t_num_bits,
bool t_shift_right, std::
unsigned_
integral T_Type, std::
unsigned_
integral T_ReturnType>
688 if constexpr (t_shift_right)
689 return get_bits<t_num_bits, T_Type, T_ReturnType>(integer, index, -
static_cast<I32>(index));
691 return get_bits<t_num_bits, T_Type, T_ReturnType>(
692 integer, index,
static_cast<I32>(num_bits<T_ReturnType> - index - t_num_bits));
698 template <
typename T_Type>
699 [[nodiscard]] constexpr
auto is_bit_set(T_Type integer,
UST index) noexcept ->
bool
701 return static_cast<bool>(
get_bit(integer, index));
707 template <std::
unsigned_
integral T_Type>
710 assert(index < num_bits<T_Type> &&
"Index exceeds number of bits.");
712 integer |=
static_cast<T_Type
>(
UST(1) << index);
718 template <UST t_value, std::
unsigned_
integral T_Type>
721 static_assert(t_value <= 1UL,
"Bit value must either be 0 or 1.");
723 if constexpr (t_value == 1UL)
732 template <UST t_num_bits, std::
unsigned_
integral T_Type>
735 assert(index + t_num_bits <= num_bits<T_Type>);
737 constexpr
UST bits = bit_construct_set_first_n_bits<UST, t_num_bits>();
738 integer |=
static_cast<T_Type
>(bits << index);
744 template <UST t_num_bits,
bool t_clear_bits, std::
unsigned_
integral T_Type>
747 [[maybe_unused]] constexpr
UST max_value = bit_construct_set_first_n_bits<UST, t_num_bits>();
749 assert(value <= max_value &&
"Value doesn't fit into specified number of bits.");
750 assert(index + t_num_bits <= num_bits<T_Type>);
752 if constexpr (t_clear_bits)
753 clear_bits<t_num_bits>(integer, index);
755 integer |=
static_cast<T_Type
>(value << index);
Defines the fundamental data types.
std::int32_t I32
32 bit signed integer type
Definition: fundamental_types.h:22
std::size_t UST
Unsigned integer type that is returned by sizeof operations.
Definition: fundamental_types.h:29
constexpr auto get_bit_shift_max(T_Type integer, UST index) noexcept -> T_ReturnType
Extract a bit from an integer and shift it maximally.
Definition: bit_operations.h:607
constexpr auto get_bit(T_Type integer, UST index, I32 shift=0) noexcept -> T_ReturnType
Extract a bit from an integer and store it with an optional shift in a new integer.
Definition: bit_operations.h:575
consteval auto bit_construct([[maybe_unused]] bool left_is_low=false) noexcept -> T_Type
Construct an unsigned integer by setting its individual bits.
Definition: bit_operations.h:459
constexpr void set_bit_to(T_Type &integer, UST index) noexcept
Set a single bit of an unsigned integer to the specified value.
Definition: bit_operations.h:719
constexpr void clear_bit(T_Type &integer, UST index) noexcept
Clear a single specific bit of an unsigned integer.
Definition: bit_operations.h:527
constexpr void set_bit(T_Type &integer, UST index) noexcept
Set a single specific bit of an unsigned integer.
Definition: bit_operations.h:708
constexpr auto get_bits(T_Type integer, UST index, I32 shift=0) noexcept -> T_ReturnType
Extract a bit pattern from an integer and store it with an optional shift in a new integer.
Definition: bit_operations.h:648
constexpr auto is_bit_set(T_Type integer, UST index) noexcept -> bool
Return true if a specific bit is set and false otherwise.
Definition: bit_operations.h:699
constexpr auto get_bits_shift_max(T_Type integer, UST index) noexcept -> T_ReturnType
Extract a bit pattern from an integer and store it with a maximal shift in a new integer.
Definition: bit_operations.h:686
constexpr void set_bits_with_int(T_Type &integer, UST index, UST value) noexcept
Set multiple consecutive bits of an unsigned integer using the bit pattern of another integer value.
Definition: bit_operations.h:745
consteval auto bit_construct_from_ints(bool left_is_low=false) noexcept -> T_Type
Construct an unsigned integer from the bit patterns of multiple integer values.
Definition: bit_operations.h:499
constexpr auto bit_construct_set_first_n_bits() noexcept -> T_Type
Construct an unsigned integer with its first t_num_bits set to 1.
Definition: bit_operations.h:484
constexpr void set_bits(T_Type &integer, UST index) noexcept
Set multiple consecutive bits of an unsigned integer.
Definition: bit_operations.h:733
constexpr UST num_bits
The size of a type in bits.
Definition: bit_operations.h:32
constexpr void clear_bits(T_Type &integer, UST index) noexcept
Clear multiple consecutive bits of an unsigned integer.
Definition: bit_operations.h:538
auto abs(T_RegisterType src) noexcept -> T_RegisterType
Return a new register with the absolute values of the input register.
Definition: sign_manipulation.h:108