add popcount, clz, ctz

This commit is contained in:
bolero-MURAKAMI 2012-06-22 22:56:25 +09:00
parent ee8c952d05
commit 3500d0d49c
8 changed files with 181 additions and 38 deletions

52
sprout/bit/clz.hpp Normal file
View file

@ -0,0 +1,52 @@
#ifndef SPROUT_BIT_CLZ_HPP
#define SPROUT_BIT_CLZ_HPP
#include <climits>
#include <type_traits>
#include <sprout/config.hpp>
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<typename T>
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<T>(m >> 1))
;
}
template<typename T, typename sprout::enabler_if<std::is_unsigned<T>::value>::type = sprout::enabler>
inline SPROUT_CONSTEXPR int
clz(T n) {
return sprout::detail::clz_impl(static_cast<T>(n));
}
template<typename T, typename sprout::enabler_if<std::is_signed<T>::value>::type = sprout::enabler>
inline SPROUT_CONSTEXPR int
clz(T n) {
return sprout::detail::clz(static_cast<typename std::make_unsigned<T>::type>(n));
}
} // namespace detail
//
// clz
//
template<typename T, typename sprout::enabler_if<std::is_integral<T>::value>::type = sprout::enabler>
inline SPROUT_CONSTEXPR int
clz(T n) {
return sprout::detail::clz(n);
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_CLZ_HPP

46
sprout/bit/ctz.hpp Normal file
View file

@ -0,0 +1,46 @@
#ifndef SPROUT_BIT_CTZ_HPP
#define SPROUT_BIT_CTZ_HPP
#include <type_traits>
#include <sprout/config.hpp>
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<typename T, typename sprout::enabler_if<std::is_unsigned<T>::value>::type = sprout::enabler>
inline SPROUT_CONSTEXPR int
ctz(T n) {
return n & 1 ? 0
: 1 + sprout::detail::ctz(static_cast<T>(n >> 1))
;
}
template<typename T, typename sprout::enabler_if<std::is_signed<T>::value>::type = sprout::enabler>
inline SPROUT_CONSTEXPR int
ctz(T n) {
return sprout::detail::ctz(static_cast<typename std::make_unsigned<T>::type>(n));
}
} // namespace detail
//
// ctz
//
template<typename T, typename sprout::enabler_if<std::is_integral<T>::value>::type = sprout::enabler>
inline SPROUT_CONSTEXPR int
ctz(T n) {
return sprout::detail::ctz(n);
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_CTZ_HPP

9
sprout/bit/operation.hpp Normal file
View file

@ -0,0 +1,9 @@
#ifndef SPROUT_BIT_OPERATION_HPP
#define SPROUT_BIT_OPERATION_HPP
#include <sprout/config.hpp>
#include <sprout/bit/popcount.hpp>
#include <sprout/bit/clz.hpp>
#include <sprout/bit/ctz.hpp>
#endif // #ifndef SPROUT_BIT_OPERATION_HPP

47
sprout/bit/popcount.hpp Normal file
View file

@ -0,0 +1,47 @@
#ifndef SPROUT_BIT_POPCOUNT_HPP
#define SPROUT_BIT_POPCOUNT_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/type_traits/enabler_if.hpp>
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<typename T, typename sprout::enabler_if<std::is_unsigned<T>::value>::type = sprout::enabler>
inline SPROUT_CONSTEXPR int
popcount(T n) {
return n == 0 ? 0
: 1 + sprout::detail::popcount(static_cast<T>(n & (n - 1)))
;
}
template<typename T, typename sprout::enabler_if<std::is_signed<T>::value>::type = sprout::enabler>
inline SPROUT_CONSTEXPR int
popcount(T n) {
return sprout::detail::popcount(static_cast<typename std::make_unsigned<T>::type>(n));
}
} // namespace detail
//
// popcount
//
template<typename T, typename sprout::enabler_if<std::is_integral<T>::value>::type = sprout::enabler>
inline SPROUT_CONSTEXPR int
popcount(T n) {
return sprout::detail::popcount(n);
}
} // namespace sprout
#endif // #ifndef SPROUT_BIT_POPCOUNT_HPP

View file

@ -15,42 +15,12 @@
#include <sprout/algorithm/fixed/fill.hpp>
#include <sprout/operation/fixed/set.hpp>
#include <sprout/utility/forward.hpp>
#include <sprout/bit/operation.hpp>
#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<typename T>
inline SPROUT_CONSTEXPR std::size_t
popcount(T n) {
return n == 0 ? 0
: 1 + sprout::detail::popcount(n & (n - 1))
;
}
template<typename T>
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<typename T>
inline SPROUT_CONSTEXPR std::size_t
clz(T n) {
return sprout::detail::clz_impl(n >> 1);
}
template<typename T>
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<word_type>(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<word_type>(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<word_type>(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
;
}

View file

@ -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

View file

@ -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

View file

@ -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