104 lines
2.7 KiB
C++
104 lines
2.7 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright 2011-2018 Danny Robson <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#ifndef CRUFT_UTIL_BITWISE_HPP
|
|
#define CRUFT_UTIL_BITWISE_HPP
|
|
|
|
#include "types/bits.hpp"
|
|
#include "debug.hpp"
|
|
|
|
#include <type_traits>
|
|
#include <cstdint>
|
|
|
|
|
|
namespace cruft {
|
|
///////////////////////////////////////////////////////////////////////////
|
|
template <typename T>
|
|
constexpr T
|
|
rotatel [[gnu::pure]] (const T value, std::size_t magnitude)
|
|
{
|
|
return (value << magnitude) | (value >> (sizeof (value) * 8 - magnitude));
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
constexpr T
|
|
rotater [[gnu::pure]] (const T value, std::size_t magnitude)
|
|
{
|
|
return (value >> magnitude) | (value << (sizeof (value) * 8 - magnitude));
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// adapted from 'bit twiddling hacks'
|
|
template <typename T>
|
|
constexpr
|
|
std::enable_if_t<std::is_integral<T>::value, T>
|
|
reverse (T src)
|
|
{
|
|
T dst = src; // dst will be reversed bits of v; first get LSB of v
|
|
|
|
int bits = sizeof (src) * 8 - 1; // extra shift needed at end
|
|
for (src >>= 1; src; src >>= 1) {
|
|
dst <<= 1;
|
|
dst |= src & 1;
|
|
bits--;
|
|
}
|
|
|
|
dst <<= bits; // shift when src's highest bits are zero
|
|
return dst;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// adapted from 'bit twiddling hacks'
|
|
template <>
|
|
constexpr
|
|
uint8_t
|
|
reverse (uint8_t val)
|
|
{
|
|
return ((val * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
template <
|
|
typename T,
|
|
typename = std::enable_if_t<
|
|
std::is_integral_v<T>
|
|
>
|
|
>
|
|
constexpr T
|
|
popcount (T t)
|
|
{
|
|
return __builtin_popcount (t);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
/// returns the integral value composed of the bits from `val' in the
|
|
/// inclusive range [lo, hi].
|
|
template <typename ValueT, typename IndexT>
|
|
constexpr ValueT
|
|
from_bits (ValueT val, IndexT hi, IndexT lo)
|
|
{
|
|
CHECK_LT (hi, IndexT (sizeof (ValueT) * 8));
|
|
CHECK_LT (lo, IndexT (sizeof (ValueT) * 8));
|
|
CHECK_GE (hi, 0);
|
|
CHECK_GE (lo, 1);
|
|
CHECK_GE (hi, lo);
|
|
|
|
ValueT zero = 0;
|
|
ValueT ones = ~zero;
|
|
|
|
return (val >> lo) & (ones >> (sizeof (ValueT) * 8 - (hi - lo + 1)));
|
|
}
|
|
}
|
|
|
|
#endif
|