Danny Robson
9eb2784d84
popcount, popcountl, and popcountll need to be used for each appropriate fundamental type. It's easiest to just provide overloads for popcount for the few cases we have available than to deal with templates.
114 lines
3.0 KiB
C++
114 lines
3.0 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;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
constexpr unsigned
|
|
popcount (unsigned t)
|
|
{
|
|
return __builtin_popcount (t);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
constexpr unsigned long
|
|
popcount (unsigned long t)
|
|
{
|
|
return __builtin_popcountl (t);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
constexpr unsigned long long
|
|
popcount (unsigned long long t)
|
|
{
|
|
return __builtin_popcountll (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
|