libcruft-util/bitwise.hpp
Danny Robson 9eb2784d84 bitwise: convert popcount template into explicit overloads
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.
2018-12-06 15:56:37 +11:00

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