Browse Source

Finish documenting and organizing bitwise functions in bit-math.hpp

master
C. J. Howard 3 years ago
parent
commit
2037230060
1 changed files with 68 additions and 90 deletions
  1. +68
    -90
      src/utility/bit-math.hpp

+ 68
- 90
src/utility/bit-math.hpp View File

@ -24,7 +24,10 @@ namespace bit
{
/**
* Compresses the even bits of a value into the lower half, then clears the upper half.
*
* @param x Value to compress.
* @return Compressed value.
*/
template <class T>
constexpr T compress(T x) noexcept;
@ -70,6 +73,15 @@ constexpr T crossover_n(T a, T b, T mask) noexcept;
template <class T>
constexpr T deposit(T x, T mask) noexcept;
/**
* Interleaves bits of the lower and upper halves of a value.
*
* @param x Value to desegregate.
* @return Value with bits from the upper half of @p x interleaved with bits from the lower half.
*/
template <class T>
constexpr T desegregate(T x) noexcept;
/**
* Returns the number of differing bits between two values, known as *Hamming distance*.
*
@ -80,6 +92,15 @@ constexpr T deposit(T x, T mask) noexcept;
template <class T>
constexpr int difference(T x, T y) noexcept;
/**
* Moves bits from the lower half of a value to occupy all even bits, and clears all odd bits.
*
* @param x Value to expand.
* @return Expanded value.
*/
template <class T>
constexpr T expand(T x) noexcept;
/**
* Reads bits from a value in the positions marked by a mask and returns them in the least significant bits.
*
@ -101,13 +122,22 @@ template
constexpr T flip(T x, int i) noexcept;
/**
* Returns a value with even bits containing the first value's lower half, and odd bits containing the second value's lower half.
*
* @param a First value.
* @param b Second value.
* @return Value with bits from the lower halves of @p a and @p b interleaved.
*/
template <class T, class U = T>
constexpr U interleave(T a, T b) noexcept;
/**
* Merges the bits of two values using a bit mask.
*
* @param a First value.
* @param b Second value.
* @param mask Bit mask with zeros where bits from @p a should be used, and ones where bits from @p b should be used.
* @return Merged value.
*/
template <class T>
constexpr T merge(T a, T b, T mask) noexcept;
@ -121,13 +151,6 @@ constexpr T merge(T a, T b, T mask) noexcept;
template <class T>
constexpr T parity(T x) noexcept;
/**
*
*/
template <class T>
constexpr T swap_adjacent(T x) noexcept;
/**
* Segregates the odd and even bits of a value.
*
@ -135,66 +158,16 @@ constexpr T swap_adjacent(T x) noexcept;
* @return Value with even bits of @p x in the lower half, and odd bits in the upper half.
*/
template <class T>
T segregate(T x)
{
T odd = bit::compress(x);
T even = bit::compress(x >> 1);
return odd | (even << (sizeof(T) << 2));
}
/**
* Interleaves bits of the lower and upper halves of a value.
*
* @param x Value to desegregate.
* @return Value with bits from the upper half of @p x interleaved with bits from the lower half.
*/
template <class T>
T desegregate(T x)
{
return bit::interleave<T>(x, x >> (sizeof(T) << 2));
}
constexpr T segregate(T x) noexcept;
/**
* Replicates each bit in the lower half of a value.
* Swaps the each odd bit with its following even bit.
*
* @param x Value to replicate.
* @return Value of @p x interleaved with itself.
* @param x Value in which adjacent bits should be swap.
* @return Copy of @p x with adjacent bits swapped.
*/
template <class T>
T replicate(T x)
{
x = bit::expand(x);
return x | (x << 1);
}
/**
* Isolates a pair of bits and returns them in the two least significant bits.
*
* @param x Diploid chromosome with interleaved alleles.
* @param i Index of the pair to isolate.
* @return Isolated pair of bits in the two least significant bits.
*/
template <class T>
T isolate(T x, int i)
{
return (x >> (i << 1)) & 0b11;
}
/**
* Isolates a sequence of genes and returns their alleles in the least significant bits.
*
* @param x Diploid chromosome with interleaed alleles.
* @param i Index of the first gene in the sequence.
* @param n Length of the sequence, in genes.
* @return Alleles of the sequeuence in the least significant bits.
*/
template <class T>
T isolate_n(T x, int i, int n)
{
T mask = (T(1) << (n << 1)) - 1;
return (x >> (i << 1)) & mask;
}
constexpr T swap_adjacent(T x) noexcept;
template <class T>
@ -228,13 +201,13 @@ template
inline constexpr T crossover(T a, T b, int i) noexcept
{
T mask = (T(1) << i) - 1;
return bit::merge(b, a, mask);
return merge(b, a, mask);
}
template <class T>
constexpr T crossover_n(T a, T b, T mask) noexcept
{
T merge = ~T(0) * bit::parity(mask);
T merge = ~T(0) * parity(mask);
while (mask)
{
@ -242,7 +215,13 @@ constexpr T crossover_n(T a, T b, T mask) noexcept
mask &= mask - 1;
}
return bit::merge(a, b, merge);
return merge(a, b, merge);
}
template <class T>
inline constexpr T desegregate(T x) noexcept
{
return interleave<T>(x, x >> (sizeof(T) << 2));
}
template <class T>
@ -263,28 +242,6 @@ constexpr T expand(T x) noexcept
return x;
}
template <class T>
inline constexpr T flip(T x, int i) noexcept
{
return x ^ (T(1) << i);
}
template <class T, class U>
inline constexpr U interleave(T a, T b) noexcept
{
return expand<U>(a) | (expand<U>(b) << 1);
}
/**
* For an n-bit number with r set bits, there are `n! / ((n - r)! * r!)` permutations.
*/
template <class T>
constexpr T next_permutation(T x) noexcept
{
T y = (x | (x - 1)) + 1;
return y | ((((y & -y) / (x & -x)) >> 1) - 1);
}
template <class T>
constexpr T deposit(T x, T mask) noexcept
{
@ -300,6 +257,12 @@ constexpr T deposit(T x, T mask) noexcept
return result;
}
template <class T>
inline constexpr int difference(T x, T y) noexcept
{
return count(x ^ y);
}
template <class T>
constexpr T extract(T x, T mask) noexcept
{
@ -316,13 +279,19 @@ constexpr T extract(T x, T mask) noexcept
}
template <class T>
inline constexpr int difference(T x, T y) noexcept
inline constexpr T flip(T x, int i) noexcept
{
return count(x ^ y);
return x ^ (T(1) << i);
}
template <class T, class U>
inline constexpr U interleave(T a, T b) noexcept
{
return expand<U>(a) | (expand<U>(b) << 1);
}
template <class T>
constexpr T merge(T a, T b, T mask) noexcept
inline constexpr T merge(T a, T b, T mask) noexcept
{
return a ^ ((a ^ b) & mask);
}
@ -342,6 +311,15 @@ constexpr T parity(T x) noexcept
return (0x6996 >> (x & 0xf)) & 1;
}
template <class T>
constexpr T segregate(T x) noexcept
{
T odd = compress(x);
T even = compress(x >> 1);
return odd | (even << (sizeof(T) << 2));
}
template <class T>
constexpr T swap_adjacent(T x) noexcept
{

Loading…
Cancel
Save