diff --git a/src/game/genetics/chromosome.hpp b/src/game/genetics/chromosome.hpp index fd6f924..cd2afb8 100644 --- a/src/game/genetics/chromosome.hpp +++ b/src/game/genetics/chromosome.hpp @@ -20,7 +20,7 @@ #ifndef ANTKEEPER_CHROMOSOME_HPP #define ANTKEEPER_CHROMOSOME_HPP -#include "bit-math.hpp" +#include "utility/bit-math.hpp" #include namespace dna @@ -35,8 +35,8 @@ namespace dna template T segregate(T x) { - T odd = deinterleave(x); - T even = deinterleave(x >> 1); + T odd = bit::compress(x); + T even = bit::compress(x >> 1); return odd | (even << (sizeof(T) << 2)); } @@ -50,7 +50,7 @@ T segregate(T x) template T desegregate(T x) { - return interleave(x, x >> (sizeof(T) << 2)); + return bit::interleave(x, x >> (sizeof(T) << 2)); } /** @@ -62,26 +62,26 @@ T desegregate(T x) template T replicate(T x) { - x = bit_expand(x); + x = bit::expand(x); return x | (x << 1); } /** - * Performs + * Generates four daughter chromosomes from a 2n/2c chromosome pair. + * + * @param x Homologous pair of chromosomes. + * @param mask Bit mask with set bits marking crossover points. + * @return Array of four 1n, 1c chromosomes. */ -template -std::array meiosis(T x, T mask) +template +std::array meiosis(T x, U mask) { - x = segregate(x); - T xl = x & (sizeof(T) << 2); - T xh = x >> (sizeof(T) << 2); - - T a = xl; - T b = crossover_n(xl, xh, mask); - T c = crossover_n(xh, xl, mask); - T d = xh; + U a = bit::compress(x); + U b = bit::compress(x >> 1); + U c = crossover_n(a, b, mask); + U d = crossover_n(b, a, mask); - return {a, b, c, d}; + return {a, c, d, b}; } /** diff --git a/src/game/genetics/bit-math.hpp b/src/utility/bit-math.hpp similarity index 76% rename from src/game/genetics/bit-math.hpp rename to src/utility/bit-math.hpp index 5efd020..775a708 100644 --- a/src/game/genetics/bit-math.hpp +++ b/src/utility/bit-math.hpp @@ -20,7 +20,7 @@ #ifndef ANTKEEPER_BIT_MATH_HPP #define ANTKEEPER_BIT_MATH_HPP -namespace dna +namespace bit { /** @@ -31,7 +31,7 @@ namespace dna * @return Bits from the least significant bits of @p x in the positions marked by @p mask. */ template -constexpr T bit_deposit(T x, T mask) noexcept; +constexpr T deposit(T x, T mask) noexcept; /** * Reads bits from a value in the positions marked by a mask and returns them in the least significant bits. @@ -41,7 +41,7 @@ constexpr T bit_deposit(T x, T mask) noexcept; * @return Bits of @p x from the positions marked by @p mask in the least significant bits. */ template -constexpr T bit_extract(T x, T mask) noexcept; +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*. @@ -50,7 +50,7 @@ constexpr T bit_extract(T x, T mask) noexcept; * @return Number of set bits in @p x. */ template -constexpr int popcount(T x) noexcept; +constexpr int count(T x) noexcept; /** * Returns the number of differing bits between two values, known as *Hamming distance*. @@ -60,17 +60,16 @@ constexpr int popcount(T x) noexcept; * @return Hamming distance between @px and @p y. */ template -constexpr int hamming_distance(T x, T y) noexcept; - +constexpr int difference(T x, T y) noexcept; template -constexpr T bit_merge(T a, T b, T mask) noexcept +constexpr T merge(T a, T b, T mask) noexcept { return a ^ ((a ^ b) & mask); } template -constexpr T bit_expand(T x) noexcept +constexpr T expand(T x) noexcept { x &= (1 << (sizeof(T) << 2)) - 1; @@ -88,7 +87,7 @@ constexpr T bit_expand(T x) noexcept } template -constexpr U interleave(T a, T b) noexcept +inline constexpr U interleave(T a, T b) noexcept { return bit_expand(a) | (bit_expand(b) << 1); } @@ -115,7 +114,7 @@ constexpr T parity(T x) noexcept } template -constexpr T deinterleave(T x) noexcept +constexpr T compress(T x) noexcept { x &= T(0x5555555555555555); @@ -133,46 +132,16 @@ constexpr T deinterleave(T x) noexcept } template -constexpr T bit_swap_adjacent(T x) noexcept +constexpr T swap_adjacent(T x) noexcept { return ((x & T(0xaaaaaaaaaaaaaaaa)) >> 1) | ((x & T(0x5555555555555555)) << 1); } -template -constexpr T bit_shuffle_adjacent(T x, T mask) noexcept -{ - T y = bit_swap_adjacent(x); - return bit_merge(x, y, bit_interleave(mask, mask)); -} - -/** - * Shuffles the adjacent bits of a value. - * - * @param x Value to shuffle. - * @param g Uniform random bit generator. - * @return Value with adjacent bits shuffled. - */ -/* -template -constexpr T bit_shuffle_adjacent(T x, URBG&& g) noexcept -{ - return bit_swap_adjacent(x, static_cast(g())); -}*/ - -/** - * - */ -template -U bit_splice(T a, T b, U mask) -{ - return bit_deposit(static_cast(a), ~mask) | bit_deposit(static_cast(b), mask); -} - /** * For an n-bit number with r set bits, there are `n! / ((n - r)! * r!)` permutations. */ template -T next_bit_permutation(T x) +constexpr T next_permutation(T x) noexcept { T y = (x | (x - 1)) + 1; return y | ((((y & -y) / (x & -x)) >> 1) - 1); @@ -194,7 +163,7 @@ constexpr T bit_deposit(T x, T mask) noexcept } template -constexpr T bit_extract(T x, T mask) noexcept +constexpr T extract(T x, T mask) noexcept { T result = 0; @@ -209,7 +178,7 @@ constexpr T bit_extract(T x, T mask) noexcept } template -constexpr int popcount(T x) noexcept +constexpr int count(T x) noexcept { int n = 0; for (; x; ++n) @@ -218,11 +187,11 @@ constexpr int popcount(T x) noexcept } template -inline constexpr int hamming_distance(T x, T y) noexcept +inline constexpr int difference(T x, T y) noexcept { - return popcount(x ^ y); + return count(x ^ y); } -} // namespace dna +} // namespace bit #endif // ANTKEEPER_BIT_MATH_HPP