2011-08-29 14:38:47 +10:00
|
|
|
/*
|
2018-08-04 15:14:06 +10:00
|
|
|
* 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/.
|
2011-08-29 14:38:47 +10:00
|
|
|
*
|
2018-03-20 13:34:19 +11:00
|
|
|
* Copyright 2011-2018 Danny Robson <danny@nerdcruft.net>
|
2011-08-29 14:38:47 +10:00
|
|
|
*/
|
|
|
|
|
2018-03-20 13:34:19 +11:00
|
|
|
#ifndef CRUFT_UTIL_BITWISE_HPP
|
|
|
|
#define CRUFT_UTIL_BITWISE_HPP
|
|
|
|
|
|
|
|
#include "types/bits.hpp"
|
|
|
|
#include "debug.hpp"
|
2011-08-29 14:38:47 +10:00
|
|
|
|
2016-10-11 23:47:57 +11:00
|
|
|
#include <type_traits>
|
2011-08-29 14:38:47 +10:00
|
|
|
#include <cstdint>
|
|
|
|
|
2012-01-04 17:06:57 +11:00
|
|
|
|
2018-08-05 14:42:02 +10:00
|
|
|
namespace cruft {
|
2016-10-11 23:47:57 +11:00
|
|
|
const uint8_t BITMASK_1BITS = 0x01;
|
|
|
|
const uint8_t BITMASK_2BITS = 0x03;
|
|
|
|
const uint8_t BITMASK_3BITS = 0x07;
|
|
|
|
const uint8_t BITMASK_4BITS = 0x0F;
|
|
|
|
const uint8_t BITMASK_5BITS = 0x1F;
|
|
|
|
const uint8_t BITMASK_6BITS = 0x3F;
|
|
|
|
const uint8_t BITMASK_7BITS = 0x7F;
|
|
|
|
const uint8_t BITMASK_8BITS = 0xFF;
|
2011-08-29 14:38:47 +10:00
|
|
|
|
2016-10-11 23:47:57 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename T>
|
|
|
|
constexpr T
|
|
|
|
rotatel [[gnu::pure]] (const T value, std::size_t magnitude)
|
|
|
|
{
|
2018-03-27 20:16:32 +11:00
|
|
|
return (value << magnitude) | (value >> (sizeof (value) * 8 - magnitude));
|
2016-10-11 23:47:57 +11:00
|
|
|
}
|
2012-01-04 17:06:57 +11:00
|
|
|
|
2014-04-16 19:15:54 +10:00
|
|
|
|
2016-10-11 23:47:57 +11:00
|
|
|
template <typename T>
|
|
|
|
constexpr T
|
|
|
|
rotater [[gnu::pure]] (const T value, std::size_t magnitude)
|
|
|
|
{
|
2018-03-27 20:16:32 +11:00
|
|
|
return (value >> magnitude) | (value << (sizeof (value) * 8 - magnitude));
|
2016-10-11 23:47:57 +11:00
|
|
|
}
|
2014-04-16 19:15:54 +10:00
|
|
|
|
2015-11-25 13:46:13 +11:00
|
|
|
|
2016-10-11 23:47:57 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
2017-02-13 17:14:30 +11:00
|
|
|
// adapted from 'bit twiddling hacks'
|
2016-10-11 23:47:57 +11:00
|
|
|
template <typename T>
|
2017-02-13 17:14:30 +11:00
|
|
|
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--;
|
2016-10-11 23:47:57 +11:00
|
|
|
}
|
2014-07-15 19:49:29 +10:00
|
|
|
|
2017-02-13 17:14:30 +11:00
|
|
|
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;
|
2016-10-11 23:47:57 +11:00
|
|
|
}
|
2014-07-15 19:49:29 +10:00
|
|
|
|
2015-11-25 13:46:13 +11:00
|
|
|
|
2016-10-11 23:47:57 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
2018-08-07 16:58:02 +10:00
|
|
|
template <
|
|
|
|
typename T,
|
|
|
|
typename = std::enable_if_t<
|
|
|
|
std::is_integral_v<T>
|
|
|
|
>
|
|
|
|
>
|
2016-10-11 23:47:57 +11:00
|
|
|
constexpr T
|
2018-08-07 16:58:02 +10:00
|
|
|
popcount (T t)
|
2016-10-11 23:47:57 +11:00
|
|
|
{
|
|
|
|
return __builtin_popcount (t);
|
|
|
|
}
|
2018-03-20 13:34:19 +11:00
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
/// 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)));
|
|
|
|
}
|
2015-11-25 13:46:13 +11:00
|
|
|
}
|
|
|
|
|
2015-04-13 18:06:08 +10:00
|
|
|
#endif
|