From 3500d0d49cbfc5b23a6e25175ed68a5622ad9767 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Fri, 22 Jun 2012 22:56:25 +0900 Subject: [PATCH] add popcount, clz, ctz --- sprout/bit/clz.hpp | 52 ++++++++++++++++++++++++++++++++++ sprout/bit/ctz.hpp | 46 ++++++++++++++++++++++++++++++ sprout/bit/operation.hpp | 9 ++++++ sprout/bit/popcount.hpp | 47 ++++++++++++++++++++++++++++++ sprout/bitset/bitset.hpp | 46 ++++++------------------------ sprout/config/auto_config.hpp | 9 ++++++ sprout/config/compiler/gcc.hpp | 4 +++ sprout/config/config.hpp | 6 ++++ 8 files changed, 181 insertions(+), 38 deletions(-) create mode 100644 sprout/bit/clz.hpp create mode 100644 sprout/bit/ctz.hpp create mode 100644 sprout/bit/operation.hpp create mode 100644 sprout/bit/popcount.hpp diff --git a/sprout/bit/clz.hpp b/sprout/bit/clz.hpp new file mode 100644 index 00000000..b7685f5f --- /dev/null +++ b/sprout/bit/clz.hpp @@ -0,0 +1,52 @@ +#ifndef SPROUT_BIT_CLZ_HPP +#define SPROUT_BIT_CLZ_HPP + +#include +#include +#include + +namespace sprout { + namespace detail { +# if SPROUT_USE_BUILTIN_BIT_OPERATION + inline SPROUT_CONSTEXPR int + clz(unsigned n) { + return __builtin_clz(n); + } + inline SPROUT_CONSTEXPR int + clz(unsigned long n) { + return __builtin_clzl(n); + } + inline SPROUT_CONSTEXPR int + clz(unsigned long long n) { + return __builtin_clzll(n); + } +# endif + template + inline SPROUT_CONSTEXPR int + clz_impl(T n, T m = T(1) << (CHAR_BIT * sizeof(T) - 1)) { + return m == 0 || n & m ? 0 + : 1 + sprout::detail::clz_impl(n, static_cast(m >> 1)) + ; + } + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR int + clz(T n) { + return sprout::detail::clz_impl(static_cast(n)); + } + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR int + clz(T n) { + return sprout::detail::clz(static_cast::type>(n)); + } + } // namespace detail + // + // clz + // + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR int + clz(T n) { + return sprout::detail::clz(n); + } +} // namespace sprout + +#endif // #ifndef SPROUT_BIT_CLZ_HPP diff --git a/sprout/bit/ctz.hpp b/sprout/bit/ctz.hpp new file mode 100644 index 00000000..06eb7622 --- /dev/null +++ b/sprout/bit/ctz.hpp @@ -0,0 +1,46 @@ +#ifndef SPROUT_BIT_CTZ_HPP +#define SPROUT_BIT_CTZ_HPP + +#include +#include + +namespace sprout { + namespace detail { +# if SPROUT_USE_BUILTIN_BIT_OPERATION + inline SPROUT_CONSTEXPR int + ctz(unsigned n) { + return __builtin_ctz(n); + } + inline SPROUT_CONSTEXPR int + ctz(unsigned long n) { + return __builtin_ctzl(n); + } + inline SPROUT_CONSTEXPR int + ctz(unsigned long long n) { + return __builtin_ctzll(n); + } +# endif + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR int + ctz(T n) { + return n & 1 ? 0 + : 1 + sprout::detail::ctz(static_cast(n >> 1)) + ; + } + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR int + ctz(T n) { + return sprout::detail::ctz(static_cast::type>(n)); + } + } // namespace detail + // + // ctz + // + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR int + ctz(T n) { + return sprout::detail::ctz(n); + } +} // namespace sprout + +#endif // #ifndef SPROUT_BIT_CTZ_HPP diff --git a/sprout/bit/operation.hpp b/sprout/bit/operation.hpp new file mode 100644 index 00000000..397de650 --- /dev/null +++ b/sprout/bit/operation.hpp @@ -0,0 +1,9 @@ +#ifndef SPROUT_BIT_OPERATION_HPP +#define SPROUT_BIT_OPERATION_HPP + +#include +#include +#include +#include + +#endif // #ifndef SPROUT_BIT_OPERATION_HPP diff --git a/sprout/bit/popcount.hpp b/sprout/bit/popcount.hpp new file mode 100644 index 00000000..7067735d --- /dev/null +++ b/sprout/bit/popcount.hpp @@ -0,0 +1,47 @@ +#ifndef SPROUT_BIT_POPCOUNT_HPP +#define SPROUT_BIT_POPCOUNT_HPP + +#include +#include +#include + +namespace sprout { + namespace detail { +# if SPROUT_USE_BUILTIN_BIT_OPERATION + inline SPROUT_CONSTEXPR int + popcount(unsigned n) { + return __builtin_popcount(n); + } + inline SPROUT_CONSTEXPR int + popcount(unsigned long n) { + return __builtin_popcountl(n); + } + inline SPROUT_CONSTEXPR int + popcount(unsigned long long n) { + return __builtin_popcountll(n); + } +# endif + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR int + popcount(T n) { + return n == 0 ? 0 + : 1 + sprout::detail::popcount(static_cast(n & (n - 1))) + ; + } + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR int + popcount(T n) { + return sprout::detail::popcount(static_cast::type>(n)); + } + } // namespace detail + // + // popcount + // + template::value>::type = sprout::enabler> + inline SPROUT_CONSTEXPR int + popcount(T n) { + return sprout::detail::popcount(n); + } +} // namespace sprout + +#endif // #ifndef SPROUT_BIT_POPCOUNT_HPP diff --git a/sprout/bitset/bitset.hpp b/sprout/bitset/bitset.hpp index fbdebda4..ede9e689 100644 --- a/sprout/bitset/bitset.hpp +++ b/sprout/bitset/bitset.hpp @@ -15,42 +15,12 @@ #include #include #include +#include #include HDR_ALGORITHM_SSCRISK_CEL_OR_SPROUT #include HDR_NUMERIC_SSCRISK_CEL_OR_SPROUT #include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { - namespace detail { - template - inline SPROUT_CONSTEXPR std::size_t - popcount(T n) { - return n == 0 ? 0 - : 1 + sprout::detail::popcount(n & (n - 1)) - ; - } - - template - inline SPROUT_CONSTEXPR std::size_t - clz_impl(T n, T m = 1 << (CHAR_BIT * sizeof(T))) { - return m == 0 || n & m ? 0 - : 1 + sprout::detail::clz_impl(n, m >> 1) - ; - } - template - inline SPROUT_CONSTEXPR std::size_t - clz(T n) { - return sprout::detail::clz_impl(n >> 1); - } - - template - inline SPROUT_CONSTEXPR std::size_t - ctz(T n) { - return n & 1 ? 0 - : 1 + sprout::detail::ctz(n >> 1) - ; - } - } // namespace detail - namespace detail { struct base_bitset_from_words_construct_tag {}; @@ -92,7 +62,7 @@ namespace sprout { public: SPROUT_CONSTEXPR std::size_t operator()(std::size_t lhs, std::size_t rhs) const SPROUT_NOEXCEPT { - return lhs + sprout::detail::popcount(rhs); + return lhs + sprout::popcount(rhs); } }; public: @@ -123,7 +93,7 @@ namespace sprout { { return first == last ? not_found : *first != static_cast(0) - ? i * (CHAR_BIT * sizeof(unsigned long)) + sprout::detail::ctz(*first) + ? i * (CHAR_BIT * sizeof(unsigned long)) + sprout::ctz(*first) : find_first_impl(not_found, first + 1, last, i + 1) ; } @@ -135,14 +105,14 @@ namespace sprout { { return first == last ? not_found : *first != static_cast(0) - ? i * (CHAR_BIT * sizeof(unsigned long)) + sprout::detail::ctz(*first) + ? i * (CHAR_BIT * sizeof(unsigned long)) + sprout::ctz(*first) : find_next_impl_2(not_found, first + 1, last) ; } SPROUT_CONSTEXPR std::size_t find_next_impl_1(std::size_t not_found, std::size_t i, word_type thisword) const SPROUT_NOEXCEPT { return thisword != static_cast(0) - ? i * (CHAR_BIT * sizeof(unsigned long)) + sprout::detail::ctz(thisword) + ? i * (CHAR_BIT * sizeof(unsigned long)) + sprout::ctz(thisword) : find_next_impl_2(not_found, begin() + (i + 1), end(), i + 1) ; } @@ -512,7 +482,7 @@ namespace sprout { private: SPROUT_CONSTEXPR std::size_t find_next_impl(std::size_t prev, std::size_t not_found, word_type x) const SPROUT_NOEXCEPT { - return x != 0 ? sprout::detail::ctz(x) + prev + return x != 0 ? sprout::ctz(x) + prev : not_found ; } @@ -641,7 +611,7 @@ namespace sprout { } SPROUT_CONSTEXPR std::size_t do_count() const SPROUT_NOEXCEPT { - return sprout::detail::popcount(w_); + return sprout::popcount(w_); } SPROUT_CONSTEXPR unsigned long @@ -655,7 +625,7 @@ namespace sprout { SPROUT_CONSTEXPR std::size_t find_first(std::size_t not_found) const SPROUT_NOEXCEPT { - return w_ != 0 ? sprout::detail::ctz(w_) + return w_ != 0 ? sprout::ctz(w_) : not_found ; } diff --git a/sprout/config/auto_config.hpp b/sprout/config/auto_config.hpp index 472d6daa..2d81945d 100644 --- a/sprout/config/auto_config.hpp +++ b/sprout/config/auto_config.hpp @@ -61,6 +61,15 @@ # endif // #ifdef SPROUT_HAS_CONSTEXPR_CMATH_FUNCTION #endif // #ifndef SPROUT_CONFIG_DISABLE_BUILTIN_CMATH_FUNCTION +// +// SPROUT_CONFIG_DISABLE_BUILTIN_BIT_OPERATION +// +#ifndef SPROUT_CONFIG_DISABLE_BUILTIN_BIT_OPERATION +# ifndef SPROUT_HAS_CONSTEXPR_BIT_OPERATION +# define SPROUT_CONFIG_DISABLE_BUILTIN_BIT_OPERATION +# endif // #ifdef SPROUT_HAS_CONSTEXPR_BIT_OPERATION +#endif // #ifndef SPROUT_CONFIG_DISABLE_BUILTIN_BIT_OPERATION + // // SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION // SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION diff --git a/sprout/config/compiler/gcc.hpp b/sprout/config/compiler/gcc.hpp index 6df80508..43839099 100644 --- a/sprout/config/compiler/gcc.hpp +++ b/sprout/config/compiler/gcc.hpp @@ -25,4 +25,8 @@ # define SPROUT_HAS_CONSTEXPR_CMATH_FUNCTION #endif +#if ((__GNUC__ >= 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) +# define SPROUT_HAS_CONSTEXPR_BIT_OPERATION +#endif + #endif // #ifndef SPROUT_CONFIG_COMPILER_GCC_HPP diff --git a/sprout/config/config.hpp b/sprout/config/config.hpp index 8ec3cf2b..4b50d643 100644 --- a/sprout/config/config.hpp +++ b/sprout/config/config.hpp @@ -69,6 +69,12 @@ # define SPROUT_USE_BUILTIN_CMATH_FUNCTION 0 #endif // #ifndef SPROUT_CONFIG_DISABLE_BUILTIN_CMATH_FUNCTION +#ifndef SPROUT_CONFIG_DISABLE_BUILTIN_BIT_OPERATION +# define SPROUT_USE_BUILTIN_BIT_OPERATION 1 +#else // #ifndef SPROUT_CONFIG_DISABLE_BUILTIN_BIT_OPERATION +# define SPROUT_USE_BUILTIN_BIT_OPERATION 0 +#endif // #ifndef SPROUT_CONFIG_DISABLE_BUILTIN_BIT_OPERATION + #ifndef SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION # define SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION 1 #else // #ifndef SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION