From ecc2b47a3087eba14aabc5e014886a16cf3469e5 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Mon, 23 Nov 2020 18:04:33 +0800 Subject: [PATCH] Add bit-math.hpp --- src/game/genetics/bit-math.hpp | 96 +++++++++++++++++++ .../{genetic-operators.hpp => crossover.hpp} | 27 ++---- src/game/genetics/gene.hpp | 33 ------- src/game/genetics/{allele.hpp => mutate.hpp} | 27 +++--- src/game/genetics/popcount.hpp | 41 -------- src/game/genetics/zygosity.hpp | 6 +- 6 files changed, 120 insertions(+), 110 deletions(-) create mode 100644 src/game/genetics/bit-math.hpp rename src/game/genetics/{genetic-operators.hpp => crossover.hpp} (61%) delete mode 100644 src/game/genetics/gene.hpp rename src/game/genetics/{allele.hpp => mutate.hpp} (69%) delete mode 100644 src/game/genetics/popcount.hpp diff --git a/src/game/genetics/bit-math.hpp b/src/game/genetics/bit-math.hpp new file mode 100644 index 0000000..e2b0e9a --- /dev/null +++ b/src/game/genetics/bit-math.hpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_BIT_MATH_HPP +#define ANTKEEPER_BIT_MATH_HPP + +namespace dna +{ + +/** + * Reads bits from the least significant bits of a value and returns them in the positions marked by a mask. + * + * @param x Value from which bits should be read. + * @param mask Bit mask indicating where bits should be deposited. + * @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; + +/** + * Reads bits from a value in the positions marked by a mask and returns them in the least significant bits. + * + * @param x Value from which bits should be read. + * @param mask Bit mask indicating which bits to extract. + * @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; + +/** + * 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 +constexpr int popcount(T x) noexcept; + +template +constexpr T bit_deposit(T x, T mask) noexcept +{ + T result = 0; + + for (T i = 1; mask; i <<= 1) + { + if (x & i) + result |= mask & -mask; + mask &= mask - 1; + } + + return result; +} + +template +constexpr T bit_extract(T x, T mask) noexcept +{ + T result = 0; + + for (T i = 1; mask; i <<= 1) + { + if (x & mask & -mask) + result |= i; + mask &= mask - 1; + } + + return result; +} + +template +constexpr int popcount(T x) noexcept +{ + int n = 0; + for (; x; ++n) + x &= x - 1; + return n; +} + +} // namespace dna + +#endif // ANTKEEPER_BIT_MATH_HPP diff --git a/src/game/genetics/genetic-operators.hpp b/src/game/genetics/crossover.hpp similarity index 61% rename from src/game/genetics/genetic-operators.hpp rename to src/game/genetics/crossover.hpp index 996952f..51cb4ae 100644 --- a/src/game/genetics/genetic-operators.hpp +++ b/src/game/genetics/crossover.hpp @@ -17,19 +17,19 @@ * along with Antkeeper source code. If not, see . */ -#ifndef ANTKEEPER_GENETIC_OPERATORS_HPP -#define ANTKEEPER_GENETIC_OPERATORS_HPP +#ifndef ANTKEEPER_CROSSOVER_HPP +#define ANTKEEPER_CROSSOVER_HPP namespace dna { /** - * Performs a genetic crossover on two blocks of interleaved alleles. + * Performs a genetic crossover between two chromosomes. * - * @param a Interleaved allele block of the first parent. - * @param b Interleaved allele block of the second parent. + * @param a Chromosome of the first parent. + * @param b Chromosome of the second parent. * @param g Uniform random bit generator. - * @return Interleaved allele block of the new offspring. + * @return Chromosome of the new offspring. */ template T crossover(T a, T b, URBG&& g) @@ -48,19 +48,6 @@ T crossover(T a, T b, URBG&& g) return c; } -/** - * Mutates a single allele in an interleaved allele block. - * - * @param x Interleaved allele block to mutate. - * @param g Uniform random bit generator. - * @return Mutated copy of @p x. - */ -template -T mutate(T x, URBG&& g) -{ - return x ^ (T(1) << (g() % (sizeof(T) << 3))); -} - } // namespace dna -#endif // ANTKEEPER_GENETIC_OPERATORS_HPP +#endif // ANTKEEPER_CROSSOVER_HPP diff --git a/src/game/genetics/gene.hpp b/src/game/genetics/gene.hpp deleted file mode 100644 index 324939f..0000000 --- a/src/game/genetics/gene.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2020 Christopher J. Howard - * - * This file is part of Antkeeper source code. - * - * Antkeeper source code is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Antkeeper source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Antkeeper source code. If not, see . - */ - -#ifndef ANTKEEPER_GENE_HPP -#define ANTKEEPER_GENE_HPP - -#include - -namespace dna -{ - -/// A 2-bit gene with two alleles. -typedef std::uint8_t gene; - -} // namespace dna - -#endif // ANTKEEPER_GENE_HPP diff --git a/src/game/genetics/allele.hpp b/src/game/genetics/mutate.hpp similarity index 69% rename from src/game/genetics/allele.hpp rename to src/game/genetics/mutate.hpp index ef8f2ef..638b4d5 100644 --- a/src/game/genetics/allele.hpp +++ b/src/game/genetics/mutate.hpp @@ -17,24 +17,25 @@ * along with Antkeeper source code. If not, see . */ -#ifndef ANTKEEPER_ALLELE_HPP -#define ANTKEEPER_ALLELE_HPP - -#include +#ifndef ANTKEEPER_MUTATE_HPP +#define ANTKEEPER_MUTATE_HPP namespace dna { -/// Enumerates allele types. -enum allele: std::uint8_t +/** + * Mutates a value by flipping a single random bit. + * + * @param x Value to mutate. + * @param g Uniform random bit generator. + * @return Mutated copy of @p x. + */ +template +T mutate(T x, URBG&& g) { - /// Indicates an allele is recessive. - recessive = 0, - - /// Indicates an allele is dominant. - dominant = 1 -}; + return x ^ (T(1) << (g() % (sizeof(T) << 3))); +} } // namespace dna -#endif // ANTKEEPER_ALLELE_HPP +#endif // ANTKEEPER_MUTATE_HPP diff --git a/src/game/genetics/popcount.hpp b/src/game/genetics/popcount.hpp deleted file mode 100644 index 5c8d75f..0000000 --- a/src/game/genetics/popcount.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2020 Christopher J. Howard - * - * This file is part of Antkeeper source code. - * - * Antkeeper source code is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Antkeeper source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Antkeeper source code. If not, see . - */ - -#ifndef ANTKEEPER_POPCOUNT_HPP -#define ANTKEEPER_POPCOUNT_HPP - -namespace dna -{ - -/// Returns the number of set bits (*population count*) in @p x. Also known as the *Hamming weight*. -template -constexpr int popcount(T x) noexcept; - -template -inline constexpr int popcount(T x) noexcept -{ - int n; - for (n = 0; x; ++n) - x &= x - 1; - return n; -} - -} // namespace dna - -#endif // ANTKEEPER_POPCOUNT_HPP diff --git a/src/game/genetics/zygosity.hpp b/src/game/genetics/zygosity.hpp index 450dada..ad1cd1e 100644 --- a/src/game/genetics/zygosity.hpp +++ b/src/game/genetics/zygosity.hpp @@ -22,7 +22,7 @@ namespace dna { - + /** * Tests a gene for heterozygosity. * @@ -44,13 +44,13 @@ bool is_homozygous(T x); template inline bool is_heterozygous(T x) { - return x & 1 != (x >> 1) & 1; + return (x & 1) != (x >> 1); } template inline bool is_homozygous(T x) { - return x & 1 == (x >> 1) & 1; + return (x & 1) == (x >> 1); } } // namespace dna