From 49dab5622b31421eb6af84eae376d73fae1cd4a0 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 16 Sep 2022 15:39:48 -0400 Subject: Switch to meson build system --- include/chilbert/detail/operations.hpp | 169 +++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 include/chilbert/detail/operations.hpp (limited to 'include/chilbert/detail/operations.hpp') diff --git a/include/chilbert/detail/operations.hpp b/include/chilbert/detail/operations.hpp new file mode 100644 index 0000000..7e846b3 --- /dev/null +++ b/include/chilbert/detail/operations.hpp @@ -0,0 +1,169 @@ +/* + Copyright (C) 2018 David Robillard + Copyright (C) 2006-2007 Chris Hamilton + + This program 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 2 of the License, or (at your option) any later + version. + + This program 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 + this program. If not, see . +*/ + +#ifndef CHILBERT_OPERATIONS_HPP +#define CHILBERT_OPERATIONS_HPP + +#include "chilbert/detail/traits.hpp" +#include "chilbert/operators.hpp" + +#include +#include +#include +#include +#include + +namespace chilbert { +namespace detail { + +/// Reset all bits in `field` +template +std::enable_if_t::value> +reset_bits(T& field) +{ + field = static_cast(0); +} + +/// Reset all bits in `field` +template +std::enable_if_t> +reset_bits(T& field) +{ + field.reset(); +} + +/// Return the `index`th bit in `field` +template +std::enable_if_t::value, bool> +test_bit(const T& field, const size_t index) +{ + assert(size_t(index) < sizeof(field) * CHAR_BIT); + return field & (T{1} << index); +} + +/// Return the `index`th bit in `field` +template +std::enable_if_t, bool> +test_bit(const T& field, const size_t index) +{ + return field.test(index); +} + +/// Set the `index`th bit in `field` +template +std::enable_if_t::value> +set_bit(T& field, const size_t index) +{ + assert(size_t(index) < sizeof(field) * CHAR_BIT); + field |= (T{1} << index); + assert(test_bit(field, index)); +} + +/// Set the `index`th bit in `field` to `value` +template +std::enable_if_t::value> +set_bit(T& field, const size_t index, const bool value) +{ + assert(size_t(index) < sizeof(field) * CHAR_BIT); + field ^= (-T{value} ^ field) & (T{1U} << index); + assert(test_bit(field, index) == value); +} + +/// Set the `index`th bit in `field` +template +std::enable_if_t> +set_bit(T& field, const size_t index) +{ + field.set(index); +} + +/// Set the `index`th bit in `field` to `value` +template +std::enable_if_t> +set_bit(T& field, const size_t index, const bool value) +{ + field.set(index, value); +} + +/// Return 1 + the index of the least significant 1-bit of `field`, or zero +template +inline int pop_count(const T& field); + +template <> +inline int +pop_count(const unsigned long& field) +{ + return __builtin_popcountl(field); +} + +template <> +inline int +pop_count(const unsigned long long& field) +{ + return __builtin_popcountll(field); +} + +/// Return 1 + the index of the least significant 1-bit of `field`, or zero +template +inline int find_first(const T field); + +template <> +inline int +find_first(const unsigned long field) +{ + return __builtin_ffsl(static_cast(field)); +} + +template <> +inline int +find_first(const unsigned long long field) +{ + return __builtin_ffsll(static_cast(field)); +} + +/// Calculates the Gray Code of `value` in place +template +std::enable_if_t> gray_code(T& value); + +/// Implementation of grayCode for any integral type +template +std::enable_if_t::value> +gray_code(T& value) +{ + value ^= (value >> 1); +} + +/// Calculates the inverse Gray Code of `value` in place +template +std::enable_if_t> gray_code_inv(T& value); + +/// Implementation of gray_code_inv for any integral type +template +std::enable_if_t::value> +gray_code_inv(T& value) +{ + constexpr T shift_end = sizeof(T) * CHAR_BIT; + for (T shift = 1; shift < shift_end; shift <<= 1) { + value ^= (value >> shift); + } +} + +} // namespace detail +} // namespace chilbert + +#endif -- cgit v1.2.1