|
|
@ -23,6 +23,43 @@ |
|
|
|
namespace bit |
|
|
|
{ |
|
|
|
|
|
|
|
/**
|
|
|
|
* |
|
|
|
*/ |
|
|
|
template <class T> |
|
|
|
constexpr T compress(T x) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the number of set bits in a value, known as a *population count* or *Hamming weight*. |
|
|
|
* |
|
|
|
* @param x Value to count. |
|
|
|
* @return Number of set bits in @p x. |
|
|
|
*/ |
|
|
|
template <class T> |
|
|
|
constexpr int count(T x) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Performs a single-point crossover between two values. |
|
|
|
* |
|
|
|
* @param a First value. |
|
|
|
* @param b Second value. |
|
|
|
* @param i Index of the crossover point. |
|
|
|
* @return Crossed over value. |
|
|
|
*/ |
|
|
|
template <class T> |
|
|
|
constexpr T crossover(T a, T b, int i) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Performs an n-point crossover between two values. |
|
|
|
* |
|
|
|
* @param a First value. |
|
|
|
* @param b Second value. |
|
|
|
* @param mask Bit mask with set bits marking crossover points. |
|
|
|
* @return Crossed over value. |
|
|
|
*/ |
|
|
|
template <class T> |
|
|
|
constexpr T crossover_n(T a, T b, T mask) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads bits from the least significant bits of a value and returns them in the positions marked by a mask. |
|
|
|
* |
|
|
@ -33,6 +70,16 @@ namespace bit |
|
|
|
template <class T> |
|
|
|
constexpr T deposit(T x, T mask) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the number of differing bits between two values, known as *Hamming distance*. |
|
|
|
* |
|
|
|
* @param x First value. |
|
|
|
* @param y Second value. |
|
|
|
* @return Hamming distance between @px and @p y. |
|
|
|
*/ |
|
|
|
template <class T> |
|
|
|
constexpr int difference(T x, T y) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads bits from a value in the positions marked by a mask and returns them in the least significant bits. |
|
|
|
* |
|
|
@ -44,75 +91,112 @@ template |
|
|
|
constexpr T extract(T x, T mask) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the number of set bits in a value, known as a *population count* or *Hamming weight*. |
|
|
|
* Flips a single bit in a value. |
|
|
|
* |
|
|
|
* @param x Value to count. |
|
|
|
* @return Number of set bits in @p x. |
|
|
|
* @param x Value to modify. |
|
|
|
* @param i Index of the bit to flip. |
|
|
|
* @return Copy of @p x with one bit flipped. |
|
|
|
*/ |
|
|
|
template <class T> |
|
|
|
constexpr int count(T x) noexcept; |
|
|
|
constexpr T flip(T x, int i) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the number of differing bits between two values, known as *Hamming distance*. |
|
|
|
* |
|
|
|
* @param x First value. |
|
|
|
* @param y Second value. |
|
|
|
* @return Hamming distance between @px and @p y. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
template <class T, class U = T> |
|
|
|
constexpr U interleave(T a, T b) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* |
|
|
|
*/ |
|
|
|
template <class T> |
|
|
|
constexpr int difference(T x, T y) noexcept; |
|
|
|
constexpr T merge(T a, T b, T mask) noexcept; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the parity of a value. |
|
|
|
* |
|
|
|
* @param x Value to test. |
|
|
|
* @return `1` if an odd number of bits are set, `0` otherwise. |
|
|
|
*/ |
|
|
|
template <class T> |
|
|
|
constexpr T merge(T a, T b, T mask) noexcept |
|
|
|
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. |
|
|
|
* |
|
|
|
* @param x Value to segregate. |
|
|
|
* @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) |
|
|
|
{ |
|
|
|
return a ^ ((a ^ b) & mask); |
|
|
|
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> |
|
|
|
constexpr T expand(T x) noexcept |
|
|
|
T desegregate(T x) |
|
|
|
{ |
|
|
|
x &= (1 << (sizeof(T) << 2)) - 1; |
|
|
|
|
|
|
|
if constexpr(sizeof(T) >= 8) |
|
|
|
x = (x ^ (x << 16)) & T(0x0000ffff0000ffff); |
|
|
|
if constexpr(sizeof(T) >= 4) |
|
|
|
x = (x ^ (x << 8)) & T(0x00ff00ff00ff00ff); |
|
|
|
if constexpr(sizeof(T) >= 2) |
|
|
|
x = (x ^ (x << 4)) & T(0x0f0f0f0f0f0f0f0f); |
|
|
|
|
|
|
|
x = (x ^ (x << 2)) & T(0x3333333333333333); |
|
|
|
x = (x ^ (x << 1)) & T(0x5555555555555555); |
|
|
|
|
|
|
|
return x; |
|
|
|
return bit::interleave<T>(x, x >> (sizeof(T) << 2)); |
|
|
|
} |
|
|
|
|
|
|
|
template <class T, class U = T> |
|
|
|
inline constexpr U interleave(T a, T b) noexcept |
|
|
|
/**
|
|
|
|
* Replicates each bit in the lower half of a value. |
|
|
|
* |
|
|
|
* @param x Value to replicate. |
|
|
|
* @return Value of @p x interleaved with itself. |
|
|
|
*/ |
|
|
|
template <class T> |
|
|
|
T replicate(T x) |
|
|
|
{ |
|
|
|
return bit_expand<U>(a) | (bit_expand<U>(b) << 1); |
|
|
|
x = bit::expand(x); |
|
|
|
return x | (x << 1); |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the parity of a value. |
|
|
|
* Isolates a pair of bits and returns them in the two least significant bits. |
|
|
|
* |
|
|
|
* @param x Value to test. |
|
|
|
* @return `1` if an odd number of bits are set, `0` otherwise. |
|
|
|
* @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> |
|
|
|
constexpr T parity(T x) noexcept |
|
|
|
T isolate(T x, int i) |
|
|
|
{ |
|
|
|
if constexpr(sizeof(T) >= 8) |
|
|
|
x ^= x >> 32; |
|
|
|
if constexpr(sizeof(T) >= 4) |
|
|
|
x ^= x >> 16; |
|
|
|
if constexpr(sizeof(T) >= 2) |
|
|
|
x ^= x >> 8; |
|
|
|
|
|
|
|
x ^= x >> 4; |
|
|
|
|
|
|
|
return (0x6996 >> (x & 0xf)) & 1; |
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <class T> |
|
|
|
constexpr T compress(T x) noexcept |
|
|
|
{ |
|
|
@ -132,9 +216,63 @@ constexpr T compress(T x) noexcept |
|
|
|
} |
|
|
|
|
|
|
|
template <class T> |
|
|
|
constexpr T swap_adjacent(T x) noexcept |
|
|
|
constexpr int count(T x) noexcept |
|
|
|
{ |
|
|
|
return ((x & T(0xaaaaaaaaaaaaaaaa)) >> 1) | ((x & T(0x5555555555555555)) << 1); |
|
|
|
int n = 0; |
|
|
|
for (; x; ++n) |
|
|
|
x &= x - 1; |
|
|
|
return n; |
|
|
|
} |
|
|
|
|
|
|
|
template <class T> |
|
|
|
inline constexpr T crossover(T a, T b, int i) noexcept |
|
|
|
{ |
|
|
|
T mask = (T(1) << i) - 1; |
|
|
|
return bit::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); |
|
|
|
|
|
|
|
while (mask) |
|
|
|
{ |
|
|
|
merge ^= (mask ^ (mask - 1)) >> 1; |
|
|
|
mask &= mask - 1; |
|
|
|
} |
|
|
|
|
|
|
|
return bit::merge(a, b, merge); |
|
|
|
} |
|
|
|
|
|
|
|
template <class T> |
|
|
|
constexpr T expand(T x) noexcept |
|
|
|
{ |
|
|
|
x &= (1 << (sizeof(T) << 2)) - 1; |
|
|
|
|
|
|
|
if constexpr(sizeof(T) >= 8) |
|
|
|
x = (x ^ (x << 16)) & T(0x0000ffff0000ffff); |
|
|
|
if constexpr(sizeof(T) >= 4) |
|
|
|
x = (x ^ (x << 8)) & T(0x00ff00ff00ff00ff); |
|
|
|
if constexpr(sizeof(T) >= 2) |
|
|
|
x = (x ^ (x << 4)) & T(0x0f0f0f0f0f0f0f0f); |
|
|
|
|
|
|
|
x = (x ^ (x << 2)) & T(0x3333333333333333); |
|
|
|
x = (x ^ (x << 1)) & T(0x5555555555555555); |
|
|
|
|
|
|
|
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); |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
@ -148,7 +286,7 @@ constexpr T next_permutation(T x) noexcept |
|
|
|
} |
|
|
|
|
|
|
|
template <class T> |
|
|
|
constexpr T bit_deposit(T x, T mask) noexcept |
|
|
|
constexpr T deposit(T x, T mask) noexcept |
|
|
|
{ |
|
|
|
T result = 0; |
|
|
|
|
|
|
@ -178,18 +316,36 @@ constexpr T extract(T x, T mask) noexcept |
|
|
|
} |
|
|
|
|
|
|
|
template <class T> |
|
|
|
constexpr int count(T x) noexcept |
|
|
|
inline constexpr int difference(T x, T y) noexcept |
|
|
|
{ |
|
|
|
int n = 0; |
|
|
|
for (; x; ++n) |
|
|
|
x &= x - 1; |
|
|
|
return n; |
|
|
|
return count(x ^ y); |
|
|
|
} |
|
|
|
|
|
|
|
template <class T> |
|
|
|
inline constexpr int difference(T x, T y) noexcept |
|
|
|
constexpr T merge(T a, T b, T mask) noexcept |
|
|
|
{ |
|
|
|
return count(x ^ y); |
|
|
|
return a ^ ((a ^ b) & mask); |
|
|
|
} |
|
|
|
|
|
|
|
template <class T> |
|
|
|
constexpr T parity(T x) noexcept |
|
|
|
{ |
|
|
|
if constexpr(sizeof(T) >= 8) |
|
|
|
x ^= x >> 32; |
|
|
|
if constexpr(sizeof(T) >= 4) |
|
|
|
x ^= x >> 16; |
|
|
|
if constexpr(sizeof(T) >= 2) |
|
|
|
x ^= x >> 8; |
|
|
|
|
|
|
|
x ^= x >> 4; |
|
|
|
|
|
|
|
return (0x6996 >> (x & 0xf)) & 1; |
|
|
|
} |
|
|
|
|
|
|
|
template <class T> |
|
|
|
constexpr T swap_adjacent(T x) noexcept |
|
|
|
{ |
|
|
|
return ((x & T(0xaaaaaaaaaaaaaaaa)) >> 1) | ((x & T(0x5555555555555555)) << 1); |
|
|
|
} |
|
|
|
|
|
|
|
} // namespace bit
|
|
|
|