diff options
Diffstat (limited to 'src/lib/util/coretmpl.h')
-rw-r--r-- | src/lib/util/coretmpl.h | 106 |
1 files changed, 95 insertions, 11 deletions
diff --git a/src/lib/util/coretmpl.h b/src/lib/util/coretmpl.h index 8b6bafa30fb..95d8230f565 100644 --- a/src/lib/util/coretmpl.h +++ b/src/lib/util/coretmpl.h @@ -32,15 +32,6 @@ #include <utility> #include <vector> -// Generate a N-bit mask at compile time. N better be constant. -// Works even for signed types - -template<typename T> constexpr T make_bitmask(unsigned int N) -{ - return T((N < (8 * sizeof(T)) ? (std::make_unsigned_t<T>(1) << N) : std::make_unsigned_t<T>(0)) - 1); -} - - // ======================> simple_list // a simple_list is a singly-linked list whose 'next' pointer is owned @@ -939,17 +930,108 @@ constexpr typename std::enable_if_t<std::is_enum<E>::value && std::is_integral<T } -// useful functions to deal with bit shuffling +/// \defgroup bitutils Useful functions for bit shuffling +/// \{ + +/// \brief Generate a right-aligned bit mask +/// +/// Generates a right aligned mask of the specified width. Works with +/// signed and unsigned integer types. +/// \tparam T Desired output type. +/// \tparam U Type of the input (generally resolved by the compiler). +/// \param [in] n Width of the mask to generate in bits. +/// \return Right-aligned mask of the specified width. + +template <typename T, typename U> constexpr T make_bitmask(U n) +{ + return T((n < (8 * sizeof(T)) ? (std::make_unsigned_t<T>(1) << n) : std::make_unsigned_t<T>(0)) - 1); +} + + +/// \brief Extract a single bit from an integer +/// +/// Extracts a single bit from an integer into the least significant bit +/// position. +/// +/// \param [in] x The integer to extract the bit from. +/// \param [in] n The bit to extract, where zero is the least +/// significant bit of the input. +/// \return Zero if the specified bit is unset, or one if it is set. +/// \sa bitswap template <typename T, typename U> constexpr T BIT(T x, U n) noexcept { return (x >> n) & T(1); } + +/// \brief Extract a bit field from an integer +/// +/// Extracts and right-aligns a bit field from an integer. +/// +/// \param [in] x The integer to extract the bit field from. +/// \param [in] n The least significant bit position of the field to +/// extract, where zero is the least significant bit of the input. +/// \param [in] w The width of the field to extract in bits. +/// \return The field [n..(n+w-1)] from the input. +/// \sa bitswap +template <typename T, typename U, typename V> constexpr T BIT(T x, U n, V w) +{ + return (x >> n) & make_bitmask<T>(w); +} + + +/// \brief Extract and right-align a single bit field +/// +/// This overload is used to terminate a recursive template +/// implementation. It is functionally equivalent to the BIT +/// function for extracting a single bit. +/// +/// \param [in] val The integer to extract the bit from. +/// \param [in] b The bit to extract, where zero is the least +/// significant bit of the input. +/// \return The specified bit of the input extracted to the least +/// significant position. template <typename T, typename U> constexpr T bitswap(T val, U b) noexcept { return BIT(val, b) << 0U; } + +/// \brief Extract bits in arbitrary order +/// +/// Extracts bits from an integer. Specify the bits in the order they +/// should be arranged in the output, from most significant to least +/// significant. The extracted bits will be packed into a right-aligned +/// field in the output. +/// +/// \param [in] val The integer to extract bits from. +/// \param [in] b The first bit to extract from the input +/// extract, where zero is the least significant bit of the input. +/// This bit will appear in the most significant position of the +/// right-aligned output field. +/// \param [in] c The remaining bits to extract, where zero is the +/// least significant bit of the input. +/// \return The extracted bits packed into a right-aligned field. template <typename T, typename U, typename... V> constexpr T bitswap(T val, U b, V... c) noexcept { return (BIT(val, b) << sizeof...(c)) | bitswap(val, c...); } -// explicit version that checks number of bit position arguments + +/// \brief Extract bits in arbitrary order with explicit count +/// +/// Extracts bits from an integer. Specify the bits in the order they +/// should be arranged in the output, from most significant to least +/// significant. The extracted bits will be packed into a right-aligned +/// field in the output. The number of bits to extract must be supplied +/// as a template argument. +/// +/// A compile error will be generated if the number of bit positions +/// supplied does not match the specified number of bits to extract, or +/// if the output type is too small to hold the extracted bits. This +/// guards against some simple errors. +/// +/// \tparam B The number of bits to extract. Must match the number of +/// bit positions supplied. +/// \param [in] val The integer to extract bits from. +/// \param [in] b Bits to extract, where zero is the least significant +/// bit of the input. Specify bits in the order they should appear in +/// the output field, from most significant to least significant. +/// \return The extracted bits packed into a right-aligned field. template <unsigned B, typename T, typename... U> T bitswap(T val, U... b) noexcept { static_assert(sizeof...(b) == B, "wrong number of bits"); @@ -957,6 +1039,8 @@ template <unsigned B, typename T, typename... U> T bitswap(T val, U... b) noexce return bitswap(val, b...); } +/// \} + // constexpr absolute value of an integer template <typename T> |