aboutsummaryrefslogtreecommitdiffstats
path: root/include/chilbert/detail/operations.hpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2022-09-16 15:39:48 -0400
committerDavid Robillard <d@drobilla.net>2022-09-16 22:31:06 -0400
commit49dab5622b31421eb6af84eae376d73fae1cd4a0 (patch)
tree86290707551320ab35952bccc11c66df05714b26 /include/chilbert/detail/operations.hpp
parent342a22b6d75597ee22c195b60607402e3ed028b2 (diff)
downloadchilbert-49dab5622b31421eb6af84eae376d73fae1cd4a0.tar.gz
chilbert-49dab5622b31421eb6af84eae376d73fae1cd4a0.tar.bz2
chilbert-49dab5622b31421eb6af84eae376d73fae1cd4a0.zip
Switch to meson build system
Diffstat (limited to 'include/chilbert/detail/operations.hpp')
-rw-r--r--include/chilbert/detail/operations.hpp169
1 files changed, 169 insertions, 0 deletions
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 <d@drobilla.net>
+ Copyright (C) 2006-2007 Chris Hamilton <chamilton@cs.dal.ca>
+
+ 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 <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef CHILBERT_OPERATIONS_HPP
+#define CHILBERT_OPERATIONS_HPP
+
+#include "chilbert/detail/traits.hpp"
+#include "chilbert/operators.hpp"
+
+#include <cassert>
+#include <climits>
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+
+namespace chilbert {
+namespace detail {
+
+/// Reset all bits in `field`
+template <typename T>
+std::enable_if_t<std::is_integral<T>::value>
+reset_bits(T& field)
+{
+ field = static_cast<T>(0);
+}
+
+/// Reset all bits in `field`
+template <typename T>
+std::enable_if_t<is_bitvec_v<T>>
+reset_bits(T& field)
+{
+ field.reset();
+}
+
+/// Return the `index`th bit in `field`
+template <typename T>
+std::enable_if_t<std::is_integral<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 <typename T>
+std::enable_if_t<is_bitvec_v<T>, bool>
+test_bit(const T& field, const size_t index)
+{
+ return field.test(index);
+}
+
+/// Set the `index`th bit in `field`
+template <typename T>
+std::enable_if_t<std::is_integral<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 <typename T>
+std::enable_if_t<std::is_integral<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 <typename T>
+std::enable_if_t<is_bitvec_v<T>>
+set_bit(T& field, const size_t index)
+{
+ field.set(index);
+}
+
+/// Set the `index`th bit in `field` to `value`
+template <typename T>
+std::enable_if_t<is_bitvec_v<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 <typename T>
+inline int pop_count(const T& field);
+
+template <>
+inline int
+pop_count<unsigned long>(const unsigned long& field)
+{
+ return __builtin_popcountl(field);
+}
+
+template <>
+inline int
+pop_count<unsigned long long>(const unsigned long long& field)
+{
+ return __builtin_popcountll(field);
+}
+
+/// Return 1 + the index of the least significant 1-bit of `field`, or zero
+template <typename T>
+inline int find_first(const T field);
+
+template <>
+inline int
+find_first<unsigned long>(const unsigned long field)
+{
+ return __builtin_ffsl(static_cast<long>(field));
+}
+
+template <>
+inline int
+find_first<unsigned long long>(const unsigned long long field)
+{
+ return __builtin_ffsll(static_cast<long long>(field));
+}
+
+/// Calculates the Gray Code of `value` in place
+template <typename T>
+std::enable_if_t<is_bitvec_v<T>> gray_code(T& value);
+
+/// Implementation of grayCode for any integral type
+template <typename T>
+std::enable_if_t<std::is_integral<T>::value>
+gray_code(T& value)
+{
+ value ^= (value >> 1);
+}
+
+/// Calculates the inverse Gray Code of `value` in place
+template <typename T>
+std::enable_if_t<is_bitvec_v<T>> gray_code_inv(T& value);
+
+/// Implementation of gray_code_inv for any integral type
+template <typename T>
+std::enable_if_t<std::is_integral<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