mirror of
https://github.com/bolero-MURAKAMI/Sprout
synced 2024-11-12 21:09:01 +00:00
1452 lines
44 KiB
C++
1452 lines
44 KiB
C++
#ifndef SPROUT_BITSET_HPP
|
|
#define SPROUT_BITSET_HPP
|
|
|
|
#include <cstddef>
|
|
#include <climits>
|
|
#include <cstring>
|
|
#include <string>
|
|
#include <functional>
|
|
#include <algorithm>
|
|
#include <iosfwd>
|
|
#include <stdexcept>
|
|
#include <sprout/config.hpp>
|
|
#include <sprout/container/traits.hpp>
|
|
#include <sprout/iterator/index_iterator.hpp>
|
|
#include <sprout/utility/forward.hpp>
|
|
#include <sprout/algorithm/fixed/transform.hpp>
|
|
#include <sprout/algorithm/fixed/fill.hpp>
|
|
#include <sprout/operation/fixed/set.hpp>
|
|
#include <sprout/functional/hash.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 {};
|
|
|
|
template<std::size_t N>
|
|
class base_bitset {
|
|
public:
|
|
typedef unsigned long word_type;
|
|
typedef word_type value_type;
|
|
typedef sprout::index_iterator<base_bitset<N>&> iterator;
|
|
typedef sprout::index_iterator<base_bitset<N> const&> const_iterator;
|
|
typedef value_type& reference;
|
|
typedef value_type const& const_reference;
|
|
typedef std::size_t size_type;
|
|
typedef std::ptrdiff_t difference_type;
|
|
SPROUT_STATIC_CONSTEXPR std::size_t static_size = N;
|
|
public:
|
|
struct are_all_pred {
|
|
public:
|
|
SPROUT_CONSTEXPR bool
|
|
operator()(word_type t) const SPROUT_NOEXCEPT {
|
|
return t == ~static_cast<word_type>(0);
|
|
}
|
|
};
|
|
struct is_any_pred {
|
|
public:
|
|
SPROUT_CONSTEXPR bool
|
|
operator()(word_type t) const SPROUT_NOEXCEPT {
|
|
return t != static_cast<word_type>(0);
|
|
}
|
|
};
|
|
struct to_ulong_pred {
|
|
public:
|
|
SPROUT_CONSTEXPR bool
|
|
operator()(word_type t) const SPROUT_NOEXCEPT {
|
|
return t != 0;
|
|
}
|
|
};
|
|
struct count_op {
|
|
public:
|
|
SPROUT_CONSTEXPR std::size_t
|
|
operator()(std::size_t lhs, std::size_t rhs) const SPROUT_NOEXCEPT {
|
|
return lhs + sprout::detail::popcount(rhs);
|
|
}
|
|
};
|
|
public:
|
|
static SPROUT_CONSTEXPR std::size_t
|
|
whichword(std::size_t pos) SPROUT_NOEXCEPT {
|
|
return pos / (CHAR_BIT * sizeof(unsigned long));
|
|
}
|
|
static SPROUT_CONSTEXPR std::size_t
|
|
whichbyte(std::size_t pos) SPROUT_NOEXCEPT {
|
|
return (pos % (CHAR_BIT * sizeof(unsigned long))) / CHAR_BIT;
|
|
}
|
|
static SPROUT_CONSTEXPR std::size_t
|
|
whichbit(std::size_t pos) SPROUT_NOEXCEPT {
|
|
return pos % (CHAR_BIT * sizeof(unsigned long));
|
|
}
|
|
static SPROUT_CONSTEXPR word_type
|
|
maskbit(std::size_t pos) SPROUT_NOEXCEPT {
|
|
return (static_cast<word_type>(1)) << whichbit(pos);
|
|
}
|
|
private:
|
|
word_type w_[N];
|
|
private:
|
|
SPROUT_CONSTEXPR std::size_t
|
|
find_first_impl(
|
|
std::size_t not_found, const_iterator first, const_iterator last,
|
|
std::size_t i = 0
|
|
) const SPROUT_NOEXCEPT
|
|
{
|
|
return first == last ? not_found
|
|
: *first != static_cast<word_type>(0)
|
|
? i * (CHAR_BIT * sizeof(unsigned long)) + sprout::detail::ctz(*first)
|
|
: find_first_impl(not_found, first + 1, last, i + 1)
|
|
;
|
|
}
|
|
SPROUT_CONSTEXPR std::size_t
|
|
find_next_impl_2(
|
|
std::size_t not_found, const_iterator first, const_iterator last,
|
|
std::size_t i
|
|
) const SPROUT_NOEXCEPT
|
|
{
|
|
return first == last ? not_found
|
|
: *first != static_cast<word_type>(0)
|
|
? i * (CHAR_BIT * sizeof(unsigned long)) + sprout::detail::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)
|
|
: find_next_impl_2(not_found, begin() + (i + 1), end(), i + 1)
|
|
;
|
|
}
|
|
SPROUT_CONSTEXPR std::size_t
|
|
find_next_impl(std::size_t prev, std::size_t not_found, std::size_t i) const SPROUT_NOEXCEPT {
|
|
return find_next_impl_1(not_found, i, w_[i] & ~static_cast<word_type>(0) << whichbit(prev));
|
|
}
|
|
template<sprout::index_t... Indexes>
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_left_shift_impl_2(
|
|
std::size_t wshift, std::size_t offset, std::size_t sub_offset,
|
|
sprout::index_tuple<Indexes...>
|
|
) const SPROUT_NOEXCEPT
|
|
{
|
|
return base_bitset(
|
|
sprout::detail::base_bitset_from_words_construct_tag(),
|
|
(static_cast<std::size_t>(Indexes) > wshift
|
|
? (w_[Indexes - wshift] << offset) | (w_[Indexes - wshift - 1] >> sub_offset)
|
|
: Indexes == wshift ? w_[0] << offset
|
|
: static_cast<word_type>(0)
|
|
)...
|
|
);
|
|
}
|
|
template<sprout::index_t... Indexes>
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_left_shift_impl_1(
|
|
std::size_t wshift, std::size_t offset,
|
|
sprout::index_tuple<Indexes...>
|
|
) const SPROUT_NOEXCEPT
|
|
{
|
|
return base_bitset(
|
|
sprout::detail::base_bitset_from_words_construct_tag(),
|
|
(static_cast<std::size_t>(Indexes) >= wshift ? w_[Indexes - wshift]
|
|
: static_cast<word_type>(0)
|
|
)...
|
|
);
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_left_shift_impl(std::size_t wshift, std::size_t offset) const SPROUT_NOEXCEPT {
|
|
return offset == 0
|
|
? do_left_shift_impl_1(
|
|
wshift, offset,
|
|
sprout::index_range<0, N>::make()
|
|
)
|
|
: do_left_shift_impl_2(
|
|
wshift, offset, (CHAR_BIT * sizeof(unsigned long)) - offset,
|
|
sprout::index_range<0, N>::make()
|
|
)
|
|
;
|
|
}
|
|
template<sprout::index_t... Indexes>
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_right_shift_impl_2(
|
|
std::size_t wshift, std::size_t offset, std::size_t limit, std::size_t sub_offset,
|
|
sprout::index_tuple<Indexes...>
|
|
) const SPROUT_NOEXCEPT
|
|
{
|
|
return base_bitset(
|
|
sprout::detail::base_bitset_from_words_construct_tag(),
|
|
(static_cast<std::size_t>(Indexes) < limit
|
|
? (w_[Indexes + wshift] >> offset) | (w_[Indexes + wshift + 1] << sub_offset)
|
|
: Indexes == limit ? w_[N-1] >> offset
|
|
: static_cast<word_type>(0)
|
|
)...
|
|
);
|
|
}
|
|
template<sprout::index_t... Indexes>
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_right_shift_impl_1(
|
|
std::size_t wshift, std::size_t offset, std::size_t limit,
|
|
sprout::index_tuple<Indexes...>
|
|
) const SPROUT_NOEXCEPT
|
|
{
|
|
return base_bitset(
|
|
sprout::detail::base_bitset_from_words_construct_tag(),
|
|
(static_cast<std::size_t>(Indexes) <= limit ? w_[Indexes + wshift]
|
|
: static_cast<word_type>(0)
|
|
)...
|
|
)
|
|
;
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_right_shift_impl(std::size_t wshift, std::size_t offset, std::size_t limit) const SPROUT_NOEXCEPT {
|
|
return offset == 0
|
|
? do_right_shift_impl_1(
|
|
wshift, offset, limit,
|
|
sprout::index_range<0, N>::make()
|
|
)
|
|
: do_right_shift_impl_2(
|
|
wshift, offset, limit, (CHAR_BIT * sizeof(unsigned long)) - offset,
|
|
sprout::index_range<0, N>::make()
|
|
)
|
|
;
|
|
}
|
|
public:
|
|
SPROUT_CONSTEXPR base_bitset() SPROUT_NOEXCEPT
|
|
: w_()
|
|
{}
|
|
SPROUT_CONSTEXPR base_bitset(unsigned long long val) SPROUT_NOEXCEPT
|
|
: w_{word_type(val), word_type(val >> (CHAR_BIT * sizeof(unsigned long)))}
|
|
{}
|
|
template<typename... Words>
|
|
SPROUT_CONSTEXPR base_bitset(sprout::detail::base_bitset_from_words_construct_tag, Words... words)
|
|
: w_{words...}
|
|
{}
|
|
|
|
void
|
|
setword(std::size_t pos, word_type word) SPROUT_NOEXCEPT {
|
|
w_[whichword(pos)] = word;
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
setword(std::size_t pos, word_type word) const SPROUT_NOEXCEPT {
|
|
return sprout::fixed::set(*this, whichword(pos), word);
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
hiword(word_type word) const SPROUT_NOEXCEPT {
|
|
return sprout::fixed::set(*this, N - 1, word);
|
|
}
|
|
|
|
word_type&
|
|
getword(std::size_t pos) SPROUT_NOEXCEPT {
|
|
return w_[whichword(pos)];
|
|
}
|
|
SPROUT_CONSTEXPR word_type
|
|
getword(std::size_t pos) const SPROUT_NOEXCEPT {
|
|
return w_[whichword(pos)];
|
|
}
|
|
SPROUT_CONSTEXPR word_type const*
|
|
getdata() const SPROUT_NOEXCEPT {
|
|
return w_;
|
|
}
|
|
word_type&
|
|
hiword() SPROUT_NOEXCEPT {
|
|
return w_[N - 1];
|
|
}
|
|
SPROUT_CONSTEXPR word_type
|
|
hiword() const SPROUT_NOEXCEPT {
|
|
return w_[N - 1];
|
|
}
|
|
|
|
void
|
|
do_and(base_bitset<N> const& x) SPROUT_NOEXCEPT {
|
|
for (std::size_t i = 0; i < N; i++) {
|
|
w_[i] &= x.w_[i];
|
|
}
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_and(base_bitset<N> const& x) const SPROUT_NOEXCEPT {
|
|
return sprout::fixed::transform(
|
|
begin(), end(), x.begin(), *this, NS_SSCRISK_CEL_OR_SPROUT::bit_and<word_type>()
|
|
);
|
|
}
|
|
void
|
|
do_or(base_bitset<N> const& x) SPROUT_NOEXCEPT {
|
|
for (std::size_t i = 0; i < N; i++) {
|
|
w_[i] |= x.w_[i];
|
|
}
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_or(base_bitset<N> const& x) const SPROUT_NOEXCEPT {
|
|
return sprout::fixed::transform(
|
|
begin(), end(), x.begin(), *this, NS_SSCRISK_CEL_OR_SPROUT::bit_or<word_type>()
|
|
);
|
|
}
|
|
void
|
|
do_xor(base_bitset<N> const& x) SPROUT_NOEXCEPT {
|
|
for (std::size_t i = 0; i < N; i++) {
|
|
w_[i] ^= x.w_[i];
|
|
}
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_xor(base_bitset<N> const& x) const SPROUT_NOEXCEPT {
|
|
return sprout::fixed::transform(
|
|
begin(), end(), x.begin(), *this, NS_SSCRISK_CEL_OR_SPROUT::bit_xor<word_type>()
|
|
);
|
|
}
|
|
void
|
|
do_left_shift(std::size_t shift) SPROUT_NOEXCEPT {
|
|
if (shift != 0) {
|
|
std::size_t const wshift = shift / (CHAR_BIT * sizeof(unsigned long));
|
|
std::size_t const offset = shift % (CHAR_BIT * sizeof(unsigned long));
|
|
if (offset == 0) {
|
|
for (std::size_t n = N - 1; n >= wshift; --n) {
|
|
w_[n] = w_[n - wshift];
|
|
}
|
|
} else {
|
|
std::size_t const sub_offset = (CHAR_BIT * sizeof(unsigned long)) - offset;
|
|
for (std::size_t n = N - 1; n > wshift; --n) {
|
|
w_[n] = (w_[n - wshift] << offset) | (w_[n - wshift - 1] >> sub_offset);
|
|
}
|
|
w_[wshift] = w_[0] << offset;
|
|
}
|
|
std::fill(w_ + 0, w_ + wshift, static_cast<word_type>(0));
|
|
}
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_left_shift(std::size_t shift) const SPROUT_NOEXCEPT {
|
|
return shift != 0 ? do_left_shift_impl(
|
|
shift / (CHAR_BIT * sizeof(unsigned long)),
|
|
shift % (CHAR_BIT * sizeof(unsigned long))
|
|
)
|
|
: *this
|
|
;
|
|
}
|
|
void
|
|
do_right_shift(std::size_t shift) SPROUT_NOEXCEPT {
|
|
if (shift != 0) {
|
|
std::size_t const wshift = shift / (CHAR_BIT * sizeof(unsigned long));
|
|
std::size_t const offset = shift % (CHAR_BIT * sizeof(unsigned long));
|
|
std::size_t const limit = N - wshift - 1;
|
|
if (offset == 0) {
|
|
for (std::size_t n = 0; n <= limit; ++n) {
|
|
w_[n] = w_[n + wshift];
|
|
}
|
|
} else {
|
|
std::size_t const sub_offset = (CHAR_BIT * sizeof(unsigned long)) - offset;
|
|
for (std::size_t n = 0; n < limit; ++n) {
|
|
w_[n] = (w_[n + wshift] >> offset) | (w_[n + wshift + 1] << sub_offset);
|
|
}
|
|
w_[limit] = w_[N-1] >> offset;
|
|
}
|
|
std::fill(w_ + limit + 1, w_ + N, static_cast<word_type>(0));
|
|
}
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_right_shift(std::size_t shift) const SPROUT_NOEXCEPT {
|
|
return shift != 0 ? do_right_shift_impl(
|
|
shift / (CHAR_BIT * sizeof(unsigned long)),
|
|
shift % (CHAR_BIT * sizeof(unsigned long)),
|
|
N - shift / (CHAR_BIT * sizeof(unsigned long)) - 1
|
|
)
|
|
: *this
|
|
;
|
|
}
|
|
void
|
|
do_flip() SPROUT_NOEXCEPT {
|
|
for (std::size_t i = 0; i < N; i++) {
|
|
w_[i] = ~w_[i];
|
|
}
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_flip() const SPROUT_NOEXCEPT {
|
|
return sprout::fixed::transform(
|
|
begin(), end(), *this, NS_SSCRISK_CEL_OR_SPROUT::bit_not<word_type>()
|
|
);
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_set() const SPROUT_NOEXCEPT {
|
|
return sprout::fixed::fill(*this, ~static_cast<word_type>(0));
|
|
}
|
|
void
|
|
do_set() SPROUT_NOEXCEPT {
|
|
for (std::size_t i = 0; i < N; i++) {
|
|
w_[i] = ~static_cast<word_type>(0);
|
|
}
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<N>
|
|
do_reset() SPROUT_NOEXCEPT {
|
|
return base_bitset();
|
|
}
|
|
void
|
|
do_reset() SPROUT_NOEXCEPT {
|
|
std::memset(w_, 0, N * sizeof(word_type));
|
|
}
|
|
|
|
SPROUT_CONSTEXPR bool
|
|
is_equal(base_bitset<N> const& x) const SPROUT_NOEXCEPT {
|
|
return NS_SSCRISK_CEL_OR_SPROUT::equal(begin(), end(), x.begin());
|
|
}
|
|
template<std::size_t N2>
|
|
SPROUT_CONSTEXPR bool
|
|
are_all() const SPROUT_NOEXCEPT {
|
|
return NS_SSCRISK_CEL_OR_SPROUT::all_of(begin(), end() - 1, are_all_pred())
|
|
&& hiword() == (~static_cast<word_type>(0) >> (N * (CHAR_BIT * sizeof(unsigned long)) - N2))
|
|
;
|
|
}
|
|
SPROUT_CONSTEXPR bool
|
|
is_any() const SPROUT_NOEXCEPT {
|
|
return NS_SSCRISK_CEL_OR_SPROUT::any_of(begin(), end(), is_any_pred());
|
|
}
|
|
SPROUT_CONSTEXPR std::size_t
|
|
do_count() const SPROUT_NOEXCEPT {
|
|
return NS_SSCRISK_CEL_OR_SPROUT::accumulate(begin(), end(),static_cast<std::size_t>(0), count_op());
|
|
}
|
|
|
|
SPROUT_CONSTEXPR unsigned long
|
|
do_to_ulong() const {
|
|
return NS_SSCRISK_CEL_OR_SPROUT::find_if(begin() + 1, end(), to_ulong_pred()) != end()
|
|
? throw std::overflow_error("base_bitset::do_to_ulong")
|
|
: w_[0]
|
|
;
|
|
}
|
|
SPROUT_CONSTEXPR unsigned long long
|
|
do_to_ullong() const {
|
|
return NS_SSCRISK_CEL_OR_SPROUT::find_if(
|
|
sizeof(unsigned long long) > sizeof(unsigned long) ? begin() + 2
|
|
: begin() + 1
|
|
,
|
|
end(),
|
|
to_ulong_pred()
|
|
) != end()
|
|
? throw std::overflow_error("base_bitset::to_ullong")
|
|
: sizeof(unsigned long long) > sizeof(unsigned long)
|
|
? w_[0] + (static_cast<unsigned long long>(w_[1]) << (CHAR_BIT * sizeof(unsigned long)))
|
|
: w_[0]
|
|
;
|
|
}
|
|
|
|
SPROUT_CONSTEXPR std::size_t
|
|
find_first(std::size_t not_found) const SPROUT_NOEXCEPT {
|
|
return find_first_impl(not_found, begin(), end());
|
|
}
|
|
SPROUT_CONSTEXPR std::size_t
|
|
find_next(std::size_t prev, std::size_t not_found) const SPROUT_NOEXCEPT {
|
|
return prev + 1 >= N * (CHAR_BIT * sizeof(unsigned long)) ? not_found
|
|
: find_next_impl(prev + 1, not_found, whichword(prev + 1));
|
|
;
|
|
}
|
|
|
|
word_type& operator[](std::size_t i) {
|
|
return w_[i];
|
|
}
|
|
SPROUT_CONSTEXPR word_type const& operator[](std::size_t i) const {
|
|
return w_[i];
|
|
}
|
|
iterator begin() SPROUT_NOEXCEPT {
|
|
return iterator(*this, 0);
|
|
}
|
|
SPROUT_CONSTEXPR const_iterator begin() const SPROUT_NOEXCEPT {
|
|
return const_iterator(*this, 0);
|
|
}
|
|
iterator end() SPROUT_NOEXCEPT {
|
|
return iterator(*this, N);
|
|
}
|
|
SPROUT_CONSTEXPR const_iterator end() const SPROUT_NOEXCEPT {
|
|
return const_iterator(*this, N);
|
|
}
|
|
};
|
|
|
|
template<>
|
|
class base_bitset<1> {
|
|
public:
|
|
typedef unsigned long word_type;
|
|
private:
|
|
word_type w_;
|
|
public:
|
|
static SPROUT_CONSTEXPR std::size_t
|
|
whichword(std::size_t pos) SPROUT_NOEXCEPT {
|
|
return pos / (CHAR_BIT * sizeof(unsigned long));
|
|
}
|
|
static SPROUT_CONSTEXPR std::size_t
|
|
whichbyte(std::size_t pos) SPROUT_NOEXCEPT {
|
|
return (pos % (CHAR_BIT * sizeof(unsigned long))) / CHAR_BIT;
|
|
}
|
|
static SPROUT_CONSTEXPR std::size_t
|
|
whichbit(std::size_t pos) SPROUT_NOEXCEPT {
|
|
return pos % (CHAR_BIT * sizeof(unsigned long));
|
|
}
|
|
static SPROUT_CONSTEXPR word_type
|
|
maskbit(std::size_t pos) SPROUT_NOEXCEPT {
|
|
return (static_cast<word_type>(1)) << whichbit(pos);
|
|
}
|
|
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
|
|
: not_found
|
|
;
|
|
}
|
|
public:
|
|
SPROUT_CONSTEXPR base_bitset() SPROUT_NOEXCEPT
|
|
: w_(0)
|
|
{}
|
|
SPROUT_CONSTEXPR base_bitset(unsigned long long val) SPROUT_NOEXCEPT
|
|
: w_(val)
|
|
{}
|
|
SPROUT_CONSTEXPR base_bitset(sprout::detail::base_bitset_from_words_construct_tag, word_type word)
|
|
: w_(word)
|
|
{}
|
|
|
|
void
|
|
setword(std::size_t, word_type word) SPROUT_NOEXCEPT {
|
|
w_ = word;
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<1>
|
|
setword(std::size_t, word_type word) const SPROUT_NOEXCEPT {
|
|
return base_bitset(sprout::detail::base_bitset_from_words_construct_tag(), word);
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<1>
|
|
hiword(word_type word) const SPROUT_NOEXCEPT {
|
|
return base_bitset(sprout::detail::base_bitset_from_words_construct_tag(), word);
|
|
}
|
|
|
|
word_type&
|
|
getword(std::size_t) SPROUT_NOEXCEPT {
|
|
return w_;
|
|
}
|
|
SPROUT_CONSTEXPR word_type
|
|
getword(std::size_t) const SPROUT_NOEXCEPT {
|
|
return w_;
|
|
}
|
|
SPROUT_CONSTEXPR word_type const*
|
|
getdata() const SPROUT_NOEXCEPT {
|
|
return &w_;
|
|
}
|
|
word_type&
|
|
hiword() SPROUT_NOEXCEPT {
|
|
return w_;
|
|
}
|
|
SPROUT_CONSTEXPR word_type
|
|
hiword() const SPROUT_NOEXCEPT {
|
|
return w_;
|
|
}
|
|
|
|
void
|
|
do_and(base_bitset<1> const& x) SPROUT_NOEXCEPT {
|
|
w_ &= x.w_;
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<1>
|
|
do_and(base_bitset<1> const& x) const SPROUT_NOEXCEPT {
|
|
return base_bitset<1>(w_ & x.w_);
|
|
}
|
|
void
|
|
do_or(base_bitset<1> const& x) SPROUT_NOEXCEPT {
|
|
w_ |= x.w_;
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<1>
|
|
do_or(base_bitset<1> const& x) const SPROUT_NOEXCEPT {
|
|
return base_bitset<1>(w_ | x.w_);
|
|
}
|
|
void
|
|
do_xor(base_bitset<1> const& x) SPROUT_NOEXCEPT {
|
|
w_ ^= x.w_;
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<1>
|
|
do_xor(base_bitset<1> const& x) const SPROUT_NOEXCEPT {
|
|
return base_bitset<1>(w_ ^ x.w_);
|
|
}
|
|
void
|
|
do_left_shift(std::size_t shift) SPROUT_NOEXCEPT {
|
|
w_ <<= shift;
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<1>
|
|
do_left_shift(base_bitset<1> const& x) const SPROUT_NOEXCEPT {
|
|
return base_bitset<1>(w_ << x.w_);
|
|
}
|
|
void
|
|
do_right_shift(std::size_t shift) SPROUT_NOEXCEPT {
|
|
w_ >>= shift;
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<1>
|
|
do_right_shift(base_bitset<1> const& x) const SPROUT_NOEXCEPT {
|
|
return base_bitset<1>(w_ >> x.w_);
|
|
}
|
|
void
|
|
do_flip() SPROUT_NOEXCEPT {
|
|
w_ = ~w_;
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<1>
|
|
do_flip() const SPROUT_NOEXCEPT {
|
|
return base_bitset<1>(~w_);
|
|
}
|
|
void
|
|
do_set() SPROUT_NOEXCEPT {
|
|
w_ = ~static_cast<word_type>(0);
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<1>
|
|
do_set() const SPROUT_NOEXCEPT {
|
|
return base_bitset<1>(~static_cast<word_type>(0));
|
|
}
|
|
void
|
|
do_reset() SPROUT_NOEXCEPT {
|
|
w_ = 0;
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<1>
|
|
do_reset() const SPROUT_NOEXCEPT {
|
|
return base_bitset<1>(0);
|
|
}
|
|
|
|
SPROUT_CONSTEXPR bool
|
|
is_equal(base_bitset<1> const& x) const SPROUT_NOEXCEPT {
|
|
return w_ == x.w_;
|
|
}
|
|
template<std::size_t N2>
|
|
SPROUT_CONSTEXPR bool
|
|
are_all() const SPROUT_NOEXCEPT {
|
|
return w_ == ~static_cast<word_type>(0) >> ((CHAR_BIT * sizeof(unsigned long)) - N2);
|
|
}
|
|
SPROUT_CONSTEXPR bool
|
|
is_any() const SPROUT_NOEXCEPT {
|
|
return w_ != 0;
|
|
}
|
|
SPROUT_CONSTEXPR std::size_t
|
|
do_count() const SPROUT_NOEXCEPT {
|
|
return sprout::detail::popcount(w_);
|
|
}
|
|
|
|
SPROUT_CONSTEXPR unsigned long
|
|
do_to_ulong() const SPROUT_NOEXCEPT {
|
|
return w_;
|
|
}
|
|
SPROUT_CONSTEXPR unsigned long long
|
|
do_to_ullong() const SPROUT_NOEXCEPT {
|
|
return w_;
|
|
}
|
|
|
|
SPROUT_CONSTEXPR std::size_t
|
|
find_first(std::size_t not_found) const SPROUT_NOEXCEPT {
|
|
return w_ != 0 ? sprout::detail::ctz(w_)
|
|
: not_found
|
|
;
|
|
}
|
|
SPROUT_CONSTEXPR std::size_t
|
|
find_next(std::size_t prev, std::size_t not_found) const SPROUT_NOEXCEPT {
|
|
return prev + 1 >= static_cast<std::size_t>(CHAR_BIT * sizeof(unsigned long)) ? not_found
|
|
: find_next_impl(prev + 1, not_found, w_ >> (prev + 1))
|
|
;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
class base_bitset<0> {
|
|
public:
|
|
typedef unsigned long word_type;
|
|
public:
|
|
static SPROUT_CONSTEXPR std::size_t
|
|
whichword(std::size_t pos) SPROUT_NOEXCEPT {
|
|
return pos / (CHAR_BIT * sizeof(unsigned long));
|
|
}
|
|
|
|
static SPROUT_CONSTEXPR std::size_t
|
|
whichbyte(std::size_t pos) SPROUT_NOEXCEPT {
|
|
return (pos % (CHAR_BIT * sizeof(unsigned long))) / CHAR_BIT;
|
|
}
|
|
|
|
static SPROUT_CONSTEXPR std::size_t
|
|
whichbit(std::size_t pos) SPROUT_NOEXCEPT {
|
|
return pos % (CHAR_BIT * sizeof(unsigned long));
|
|
}
|
|
|
|
static SPROUT_CONSTEXPR word_type
|
|
maskbit(std::size_t pos) SPROUT_NOEXCEPT {
|
|
return (static_cast<word_type>(1)) << whichbit(pos);
|
|
}
|
|
public:
|
|
SPROUT_CONSTEXPR base_bitset() SPROUT_NOEXCEPT {}
|
|
SPROUT_CONSTEXPR base_bitset(unsigned long long) SPROUT_NOEXCEPT {}
|
|
SPROUT_CONSTEXPR base_bitset(sprout::detail::base_bitset_from_words_construct_tag) {}
|
|
|
|
void
|
|
setword(std::size_t, word_type) SPROUT_NOEXCEPT {}
|
|
SPROUT_CONSTEXPR base_bitset<0>
|
|
setword(std::size_t, word_type) const SPROUT_NOEXCEPT {
|
|
return *this;
|
|
}
|
|
SPROUT_CONSTEXPR base_bitset<0>
|
|
hiword(word_type) const SPROUT_NOEXCEPT {
|
|
return *this;
|
|
}
|
|
|
|
word_type&
|
|
getword(std::size_t) SPROUT_NOEXCEPT {
|
|
return throw std::out_of_range("base_bitset::getword"), *new word_type();
|
|
}
|
|
SPROUT_CONSTEXPR word_type
|
|
getword(std::size_t pos) const SPROUT_NOEXCEPT {
|
|
return 0;
|
|
}
|
|
SPROUT_CONSTEXPR word_type
|
|
hiword() const SPROUT_NOEXCEPT {
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
do_and(base_bitset<0> const&) SPROUT_NOEXCEPT {}
|
|
SPROUT_CONSTEXPR base_bitset<0>
|
|
do_and(base_bitset<0> const&) const SPROUT_NOEXCEPT {
|
|
return *this;
|
|
}
|
|
void
|
|
do_or(base_bitset<0> const&) SPROUT_NOEXCEPT {}
|
|
SPROUT_CONSTEXPR base_bitset<0>
|
|
do_or(base_bitset<0> const&) const SPROUT_NOEXCEPT {
|
|
return *this;
|
|
}
|
|
void
|
|
do_xor(base_bitset<0> const&) SPROUT_NOEXCEPT {}
|
|
SPROUT_CONSTEXPR base_bitset<0>
|
|
do_xor(base_bitset<0> const&) const SPROUT_NOEXCEPT {
|
|
return *this;
|
|
}
|
|
void
|
|
do_left_shift(std::size_t) SPROUT_NOEXCEPT {}
|
|
SPROUT_CONSTEXPR base_bitset<0>
|
|
do_left_shift(base_bitset<0> const&) const SPROUT_NOEXCEPT {
|
|
return *this;
|
|
}
|
|
void
|
|
do_right_shift(std::size_t) SPROUT_NOEXCEPT {}
|
|
SPROUT_CONSTEXPR base_bitset<0>
|
|
do_right_shift(base_bitset<0> const&) const SPROUT_NOEXCEPT {
|
|
return *this;
|
|
}
|
|
void
|
|
do_flip() SPROUT_NOEXCEPT {}
|
|
SPROUT_CONSTEXPR base_bitset<0>
|
|
do_flip() const SPROUT_NOEXCEPT {
|
|
return *this;
|
|
}
|
|
void
|
|
do_set() SPROUT_NOEXCEPT {}
|
|
SPROUT_CONSTEXPR base_bitset<0>
|
|
do_set() SPROUT_NOEXCEPT {
|
|
return base_bitset<0>();
|
|
}
|
|
void
|
|
do_reset() SPROUT_NOEXCEPT {}
|
|
SPROUT_CONSTEXPR base_bitset<0>
|
|
do_reset() SPROUT_NOEXCEPT {
|
|
return base_bitset<0>();
|
|
}
|
|
|
|
SPROUT_CONSTEXPR bool
|
|
is_equal(base_bitset<0> const&) const SPROUT_NOEXCEPT {
|
|
return true;
|
|
}
|
|
template<std::size_t N2>
|
|
SPROUT_CONSTEXPR bool
|
|
are_all() const SPROUT_NOEXCEPT {
|
|
return true;
|
|
}
|
|
SPROUT_CONSTEXPR bool
|
|
is_any() const SPROUT_NOEXCEPT {
|
|
return false;
|
|
}
|
|
SPROUT_CONSTEXPR std::size_t
|
|
do_count() const SPROUT_NOEXCEPT {
|
|
return 0;
|
|
}
|
|
|
|
SPROUT_CONSTEXPR unsigned long
|
|
do_to_ulong() const SPROUT_NOEXCEPT {
|
|
return 0;
|
|
}
|
|
SPROUT_CONSTEXPR unsigned long long
|
|
do_to_ullong() const SPROUT_NOEXCEPT {
|
|
return 0;
|
|
}
|
|
|
|
SPROUT_CONSTEXPR std::size_t
|
|
find_first(std::size_t) const SPROUT_NOEXCEPT {
|
|
return 0;
|
|
}
|
|
SPROUT_CONSTEXPR std::size_t
|
|
find_next(std::size_t, std::size_t) const SPROUT_NOEXCEPT {
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
template<std::size_t Extrabits>
|
|
struct sanitize {
|
|
public:
|
|
typedef unsigned long word_type;
|
|
public:
|
|
static void
|
|
do_sanitize(word_type& val) SPROUT_NOEXCEPT {
|
|
val &= ~(~static_cast<word_type>(0) << Extrabits);
|
|
}
|
|
static SPROUT_CONSTEXPR word_type
|
|
do_sanitize_c(word_type val) SPROUT_NOEXCEPT {
|
|
return val & ~(~static_cast<word_type>(0) << Extrabits);
|
|
}
|
|
};
|
|
template<>
|
|
struct sanitize<0> {
|
|
public:
|
|
typedef unsigned long word_type;
|
|
public:
|
|
static void
|
|
do_sanitize(word_type) SPROUT_NOEXCEPT {}
|
|
static SPROUT_CONSTEXPR word_type
|
|
do_sanitize_c(word_type val) SPROUT_NOEXCEPT {
|
|
return val;
|
|
}
|
|
};
|
|
|
|
template<std::size_t N2, bool = (N2 < (CHAR_BIT * sizeof(unsigned long long)))>
|
|
struct sanitize_val {
|
|
public:
|
|
static SPROUT_CONSTEXPR unsigned long long
|
|
do_sanitize_val(unsigned long long val) {
|
|
return val;
|
|
}
|
|
};
|
|
template<std::size_t N2>
|
|
struct sanitize_val<N2, true> {
|
|
public:
|
|
static SPROUT_CONSTEXPR unsigned long long
|
|
do_sanitize_val(unsigned long long val) {
|
|
return val & ~((~static_cast<unsigned long long>(0)) << N2);
|
|
}
|
|
};
|
|
} // namespace detail
|
|
|
|
template<std::size_t N>
|
|
struct container_construct_traits<sprout::detail::base_bitset<N> > {
|
|
public:
|
|
typedef sprout::detail::base_bitset<N> copied_type;
|
|
public:
|
|
template<typename Cont>
|
|
static SPROUT_CONSTEXPR copied_type deep_copy(Cont&& cont) {
|
|
return sprout::forward<Cont>(cont);
|
|
}
|
|
template<typename... Args>
|
|
static SPROUT_CONSTEXPR copied_type make(Args&&... args) {
|
|
return copied_type(sprout::detail::base_bitset_from_words_construct_tag(), args...);
|
|
}
|
|
template<typename Cont, typename... Args>
|
|
static SPROUT_CONSTEXPR copied_type remake(
|
|
Cont&& cont,
|
|
typename sprout::container_traits<sprout::detail::base_bitset<N> >::difference_type size,
|
|
Args&&... args
|
|
)
|
|
{
|
|
return make(args...);
|
|
}
|
|
};
|
|
|
|
template<std::size_t N>
|
|
class bitset;
|
|
|
|
template<std::size_t N>
|
|
inline SPROUT_CONSTEXPR bitset<N>
|
|
operator&(sprout::bitset<N> const& lhs, sprout::bitset<N> const& rhs) SPROUT_NOEXCEPT;
|
|
template<std::size_t N>
|
|
inline SPROUT_CONSTEXPR bitset<N>
|
|
operator|(sprout::bitset<N> const& lhs, sprout::bitset<N> const& rhs) SPROUT_NOEXCEPT;
|
|
template <std::size_t N>
|
|
inline SPROUT_CONSTEXPR bitset<N>
|
|
operator^(sprout::bitset<N> const& lhs, sprout::bitset<N> const& rhs) SPROUT_NOEXCEPT;
|
|
template<typename Char, typename Traits, std::size_t N>
|
|
inline std::basic_istream<Char, Traits>&
|
|
operator>>(std::basic_istream<Char, Traits>& lhs, sprout::bitset<N>& rhs);
|
|
template <typename Char, typename Traits, std::size_t N>
|
|
inline std::basic_ostream<Char, Traits>&
|
|
operator<<(std::basic_ostream<Char, Traits>& lhs, sprout::bitset<N> const& rhs);
|
|
|
|
template<std::size_t N>
|
|
inline SPROUT_CONSTEXPR std::size_t
|
|
hash_value(sprout::bitset<N> const& v);
|
|
|
|
//
|
|
// bitset
|
|
//
|
|
template<std::size_t N>
|
|
class bitset
|
|
: private sprout::detail::base_bitset<
|
|
N / (CHAR_BIT * sizeof(unsigned long)) + (N % (CHAR_BIT * sizeof(unsigned long)) == 0 ? 0 : 1)
|
|
>
|
|
{
|
|
private:
|
|
typedef sprout::detail::base_bitset<
|
|
N / (CHAR_BIT * sizeof(unsigned long)) + (N % (CHAR_BIT * sizeof(unsigned long)) == 0 ? 0 : 1)
|
|
> base_type;
|
|
typedef unsigned long word_type;
|
|
public:
|
|
class reference {
|
|
friend class bitset;
|
|
private:
|
|
word_type* wp_;
|
|
std::size_t bpos_;
|
|
private:
|
|
reference() = delete;
|
|
public:
|
|
reference(bitset& b, std::size_t pos) SPROUT_NOEXCEPT
|
|
: wp_(&b.getword(pos))
|
|
, bpos_(base_type::whichbit(pos))
|
|
{}
|
|
~reference() SPROUT_NOEXCEPT {}
|
|
|
|
reference&
|
|
operator=(bool x) SPROUT_NOEXCEPT {
|
|
if (x) {
|
|
*wp_ |= base_type::maskbit(bpos_);
|
|
} else {
|
|
*wp_ &= ~base_type::maskbit(bpos_);
|
|
}
|
|
return *this;
|
|
}
|
|
reference&
|
|
operator=(const reference& j) SPROUT_NOEXCEPT {
|
|
if ((*(j.wp_) & base_type::maskbit(j.bpos_))) {
|
|
*wp_ |= base_type::maskbit(bpos_);
|
|
} else {
|
|
*wp_ &= ~base_type::maskbit(bpos_);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
bool
|
|
operator~() const SPROUT_NOEXCEPT {
|
|
return (*wp_ & base_type::maskbit(bpos_)) == 0;
|
|
}
|
|
operator bool() const SPROUT_NOEXCEPT {
|
|
return (*wp_ & base_type::maskbit(bpos_)) != 0;
|
|
}
|
|
reference&
|
|
flip() SPROUT_NOEXCEPT {
|
|
*wp_ ^= base_type::maskbit(bpos_);
|
|
return *this;
|
|
}
|
|
};
|
|
friend class reference;
|
|
private:
|
|
explicit SPROUT_CONSTEXPR bitset(base_type const& base) SPROUT_NOEXCEPT
|
|
: base_type(base)
|
|
{}
|
|
|
|
void
|
|
do_sanitize() SPROUT_NOEXCEPT {
|
|
typedef sprout::detail::sanitize<N % (CHAR_BIT * sizeof(unsigned long))> sanitize_type;
|
|
sanitize_type::do_sanitize(this->hiword());
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
do_sanitize() const SPROUT_NOEXCEPT {
|
|
typedef sprout::detail::sanitize<N % (CHAR_BIT * sizeof(unsigned long))> sanitize_type;
|
|
return bitset(this->hiword(sanitize_type::do_sanitize_c(this->hiword())));
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
do_sanitize_c() const SPROUT_NOEXCEPT {
|
|
return do_sanitize();
|
|
}
|
|
|
|
bitset<N>&
|
|
unchecked_set(std::size_t pos) SPROUT_NOEXCEPT {
|
|
this->getword(pos) |= base_type::maskbit(pos);
|
|
return *this;
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
unchecked_set(std::size_t pos) const SPROUT_NOEXCEPT {
|
|
return bitset(this->setword(pos, this->getword(pos) | base_type::maskbit(pos)));
|
|
}
|
|
bitset<N>&
|
|
unchecked_set(std::size_t pos, int val) SPROUT_NOEXCEPT {
|
|
if (val) {
|
|
this->getword(pos) |= base_type::maskbit(pos);
|
|
} else {
|
|
this->getword(pos) &= ~base_type::maskbit(pos);
|
|
}
|
|
return *this;
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
unchecked_set(std::size_t pos, int val) const SPROUT_NOEXCEPT {
|
|
return val ? bitset(this->setword(pos, this->getword(pos) | base_type::maskbit(pos)))
|
|
: bitset(this->setword(pos, this->getword(pos) & ~base_type::maskbit(pos)))
|
|
;
|
|
}
|
|
bitset<N>&
|
|
unchecked_reset(std::size_t pos) SPROUT_NOEXCEPT {
|
|
this->getword(pos) &= ~base_type::maskbit(pos);
|
|
return *this;
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
unchecked_reset(std::size_t pos) const SPROUT_NOEXCEPT {
|
|
return bitset<N>(this->setword(pos, this->getword(pos) & ~base_type::maskbit(pos)));
|
|
}
|
|
bitset<N>&
|
|
unchecked_flip(std::size_t pos) SPROUT_NOEXCEPT {
|
|
this->getword(pos) ^= base_type::maskbit(pos);
|
|
return *this;
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
unchecked_flip(std::size_t pos) const SPROUT_NOEXCEPT {
|
|
return bitset<N>(this->setword(pos, this->getword(pos) ^ base_type::maskbit(pos)));
|
|
}
|
|
SPROUT_CONSTEXPR bool
|
|
unchecked_test(std::size_t pos) const SPROUT_NOEXCEPT {
|
|
return (this->getword(pos) & base_type::maskbit(pos)) != static_cast<word_type>(0);
|
|
}
|
|
|
|
template<typename Char, typename Traits>
|
|
void
|
|
copy_from_ptr(const Char* s, std::size_t len, std::size_t pos, std::size_t n, Char zero, Char one) {
|
|
reset();
|
|
std::size_t const nbits = std::min(N, std::min(n, len - pos));
|
|
for (std::size_t i = nbits; i > 0; --i) {
|
|
Char const c = s[pos + nbits - i];
|
|
if (Traits::eq(c, zero)) {
|
|
} else if (Traits::eq(c, one)) {
|
|
unchecked_set(i - 1);
|
|
} else {
|
|
throw std::invalid_argument("bitset::copy_from_ptr");
|
|
}
|
|
}
|
|
}
|
|
template<typename Char, typename Traits, typename Alloc>
|
|
void
|
|
copy_from_string(
|
|
std::basic_string<Char, Traits, Alloc> const& s,
|
|
std::size_t pos, std::size_t n, Char zero, Char one
|
|
)
|
|
{
|
|
copy_from_ptr<Char, Traits>(s.data(), s.size(), pos, n, zero, one);
|
|
}
|
|
template<typename Char, typename Traits, typename Alloc>
|
|
void
|
|
copy_to_string(std::basic_string<Char, Traits, Alloc>& s, Char zero, Char one) const {
|
|
s.assign(N, zero);
|
|
for (std::size_t i = N; i > 0; --i) {
|
|
if (unchecked_test(i - 1)) {
|
|
Traits::assign(s[N - i], one);
|
|
}
|
|
}
|
|
}
|
|
template<typename Char, typename Traits, typename Alloc>
|
|
void
|
|
copy_from_string(std::basic_string<Char, Traits, Alloc> const& s, std::size_t pos, std::size_t n) {
|
|
copy_from_string(s, pos, n, Char('0'), Char('1'));
|
|
}
|
|
template<typename Char, typename Traits, typename Alloc>
|
|
void
|
|
copy_to_string(std::basic_string<Char, Traits,Alloc>& s) const {
|
|
copy_to_string(s, Char('0'), Char('1'));
|
|
}
|
|
public:
|
|
// 20.5.1 constructors:
|
|
SPROUT_CONSTEXPR bitset() SPROUT_NOEXCEPT {}
|
|
SPROUT_CONSTEXPR bitset(unsigned long long val) SPROUT_NOEXCEPT
|
|
: base_type(sprout::detail::sanitize_val<N>::do_sanitize_val(val))
|
|
{}
|
|
template<typename Char, typename Traits, typename Alloc>
|
|
explicit bitset(std::basic_string<Char, Traits, Alloc> const& s, std::size_t position = 0)
|
|
: base_type()
|
|
{
|
|
if (position > s.size()) {
|
|
throw std::out_of_range("bitset::bitset initial position not valid");
|
|
}
|
|
copy_from_string(s, position, std::basic_string<Char, Traits, Alloc>::npos, Char('0'), Char('1'));
|
|
}
|
|
template<typename Char, typename Traits, typename Alloc>
|
|
bitset(std::basic_string<Char, Traits, Alloc> const& s, std::size_t position, std::size_t n)
|
|
: base_type()
|
|
{
|
|
if (position > s.size()) {
|
|
throw std::out_of_range("bitset::bitset initial position not valid");
|
|
}
|
|
copy_from_string(s, position, n, Char('0'), Char('1'));
|
|
}
|
|
|
|
template<typename Char, typename Traits, typename Alloc>
|
|
bitset(
|
|
std::basic_string<Char, Traits, Alloc> const& s, std::size_t position, std::size_t n,
|
|
Char zero, Char one = Char('1')
|
|
)
|
|
: base_type()
|
|
{
|
|
if (position > s.size()) {
|
|
throw std::out_of_range("bitset::bitset initial position not valid");
|
|
}
|
|
copy_from_string(s, position, n, zero, one);
|
|
}
|
|
template<typename Char>
|
|
explicit bitset(
|
|
Char const* str, typename std::basic_string<Char>::std::size_type n = std::basic_string<Char>::npos,
|
|
Char zero = Char('0'), Char one = Char('1')
|
|
)
|
|
: base_type()
|
|
{
|
|
if (!str) {
|
|
throw std::out_of_range("bitset::bitset");
|
|
}
|
|
if (n == std::basic_string<Char>::npos) {
|
|
n = std::char_traits<Char>::length(str);
|
|
}
|
|
copy_from_ptr<Char, std::char_traits<Char>>(str, n, 0, n, zero, one);
|
|
}
|
|
// 20.5.2 bitset operations:
|
|
bitset<N>&
|
|
operator&=(bitset<N> const& rhs) SPROUT_NOEXCEPT {
|
|
this->do_and(rhs);
|
|
return *this;
|
|
}
|
|
bitset<N>&
|
|
operator|=(bitset<N> const& rhs) SPROUT_NOEXCEPT {
|
|
this->do_or(rhs);
|
|
return *this;
|
|
}
|
|
bitset<N>&
|
|
operator^=(bitset<N> const& rhs) SPROUT_NOEXCEPT {
|
|
this->do_xor(rhs);
|
|
return *this;
|
|
}
|
|
bitset<N>&
|
|
operator<<=(std::size_t position) SPROUT_NOEXCEPT {
|
|
if (position < N) {
|
|
this->do_left_shift(position);
|
|
this->do_sanitize();
|
|
} else {
|
|
this->do_reset();
|
|
}
|
|
return *this;
|
|
}
|
|
bitset<N>&
|
|
operator>>=(std::size_t position) SPROUT_NOEXCEPT {
|
|
if (position < N) {
|
|
this->do_right_shift(position);
|
|
this->do_sanitize();
|
|
} else {
|
|
this->do_reset();
|
|
}
|
|
return *this;
|
|
}
|
|
bitset<N>&
|
|
set() SPROUT_NOEXCEPT {
|
|
this->do_set();
|
|
this->do_sanitize();
|
|
return *this;
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
set() const SPROUT_NOEXCEPT {
|
|
return bitset(this->do_set()).do_sanitize_c();
|
|
}
|
|
bitset<N>&
|
|
set(std::size_t position, bool val = true) {
|
|
if (position >= N) {
|
|
throw std::out_of_range("bitset::set");
|
|
}
|
|
return unchecked_set(position, val);
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
set(std::size_t position, bool val = true) const {
|
|
return position >= N ? throw std::out_of_range("bitset::set")
|
|
: unchecked_set(position, val)
|
|
;
|
|
}
|
|
bitset<N>&
|
|
reset() SPROUT_NOEXCEPT {
|
|
this->do_reset();
|
|
return *this;
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
reset() const SPROUT_NOEXCEPT {
|
|
return bitset(this->do_reset());
|
|
}
|
|
bitset<N>&
|
|
reset(std::size_t position) {
|
|
if (position >= N) {
|
|
throw std::out_of_range("bitset::reset");
|
|
}
|
|
return unchecked_reset(position);
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
reset(std::size_t position) const {
|
|
return position >= N ? throw std::out_of_range("bitset::reset")
|
|
: unchecked_reset(position)
|
|
;
|
|
}
|
|
bitset<N>&
|
|
flip() SPROUT_NOEXCEPT {
|
|
this->do_flip();
|
|
this->do_sanitize();
|
|
return *this;
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
flip() const SPROUT_NOEXCEPT {
|
|
return bitset(this->do_flip()).do_sanitize_c();
|
|
}
|
|
bitset<N>&
|
|
flip(std::size_t position) {
|
|
if (position >= N) {
|
|
throw std::out_of_range("bitset::flip");
|
|
}
|
|
return unchecked_flip(position);
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
flip(std::size_t position) const {
|
|
return position >= N ? throw std::out_of_range("bitset::flip")
|
|
: unchecked_flip(position)
|
|
;
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
operator~() const SPROUT_NOEXCEPT {
|
|
return flip();
|
|
}
|
|
|
|
// element access:
|
|
reference
|
|
operator[](std::size_t position) {
|
|
return reference(*this, position);
|
|
}
|
|
SPROUT_CONSTEXPR bool
|
|
operator[](std::size_t position) const {
|
|
return unchecked_test(position);
|
|
}
|
|
SPROUT_CONSTEXPR unsigned long
|
|
to_ulong() const {
|
|
return this->do_to_ulong();
|
|
}
|
|
SPROUT_CONSTEXPR unsigned long long
|
|
to_ullong() const {
|
|
return this->do_to_ullong();
|
|
}
|
|
template<typename Char, typename Traits, typename Alloc>
|
|
std::basic_string<Char, Traits, Alloc>
|
|
to_string() const {
|
|
std::basic_string<Char, Traits, Alloc> result;
|
|
copy_to_string(result, Char('0'), Char('1'));
|
|
return result;
|
|
}
|
|
template<typename Char, typename Traits, typename Alloc>
|
|
std::basic_string<Char, Traits, Alloc>
|
|
to_string(Char zero, Char one = Char('1')) const {
|
|
std::basic_string<Char, Traits, Alloc> result;
|
|
copy_to_string(result, zero, one);
|
|
return result;
|
|
}
|
|
template<typename Char, typename Traits>
|
|
std::basic_string<Char, Traits, std::allocator<Char> >
|
|
to_string() const {
|
|
return to_string<Char, Traits, std::allocator<Char> >();
|
|
}
|
|
template<typename Char, typename Traits>
|
|
std::basic_string<Char, Traits, std::allocator<Char> >
|
|
to_string(Char zero, Char one = Char('1')) const {
|
|
return to_string<Char, Traits, std::allocator<Char> >(zero, one);
|
|
}
|
|
template<class Char>
|
|
std::basic_string<Char, std::char_traits<Char>, std::allocator<Char> >
|
|
to_string() const {
|
|
return to_string<Char, std::char_traits<Char>, std::allocator<Char> >();
|
|
}
|
|
template<class Char>
|
|
std::basic_string<Char, std::char_traits<Char>, std::allocator<Char> >
|
|
to_string(Char zero, Char one = Char('1')) const {
|
|
return to_string<Char, std::char_traits<Char>, std::allocator<Char> >(zero, one);
|
|
}
|
|
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
|
|
to_string() const {
|
|
return to_string<char, std::char_traits<char>, std::allocator<char> >();
|
|
}
|
|
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
|
|
to_string(char zero, char one = '1') const {
|
|
return to_string<char, std::char_traits<char>, std::allocator<char> >(zero, one);
|
|
}
|
|
|
|
SPROUT_CONSTEXPR std::size_t
|
|
count() const SPROUT_NOEXCEPT {
|
|
return this->do_count();
|
|
}
|
|
SPROUT_CONSTEXPR std::size_t
|
|
size() const SPROUT_NOEXCEPT {
|
|
return N;
|
|
}
|
|
SPROUT_CONSTEXPR bool
|
|
operator==(bitset<N> const& rhs) const SPROUT_NOEXCEPT {
|
|
return this->is_equal(rhs);
|
|
}
|
|
SPROUT_CONSTEXPR bool
|
|
operator!=(bitset<N> const& rhs) const SPROUT_NOEXCEPT {
|
|
return !this->is_equal(rhs);
|
|
}
|
|
SPROUT_CONSTEXPR bool
|
|
test(std::size_t position) const {
|
|
return position >= N ? throw std::out_of_range("bitset::test")
|
|
: unchecked_test(position)
|
|
;
|
|
}
|
|
SPROUT_CONSTEXPR bool
|
|
all() const SPROUT_NOEXCEPT {
|
|
return this->template are_all<N>();
|
|
}
|
|
SPROUT_CONSTEXPR bool
|
|
any() const SPROUT_NOEXCEPT {
|
|
return this->is_any();
|
|
}
|
|
SPROUT_CONSTEXPR bool
|
|
none() const SPROUT_NOEXCEPT {
|
|
return !this->is_any();
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
operator<<(std::size_t position) const SPROUT_NOEXCEPT {
|
|
return position < N
|
|
? bitset(this->do_left_shift(position)).do_sanitize_c()
|
|
: bitset(this->do_reset())
|
|
;
|
|
}
|
|
SPROUT_CONSTEXPR bitset<N>
|
|
operator>>(std::size_t position) const SPROUT_NOEXCEPT {
|
|
return position < N
|
|
? bitset(this->do_right_shift(position)).do_sanitize_c()
|
|
: bitset(this->do_reset())
|
|
;
|
|
}
|
|
|
|
SPROUT_CONSTEXPR std::size_t
|
|
find_first() const SPROUT_NOEXCEPT {
|
|
return this->find_first(N);
|
|
}
|
|
SPROUT_CONSTEXPR std::size_t
|
|
find_next(std::size_t prev) const SPROUT_NOEXCEPT {
|
|
return this->find_next(prev, N);
|
|
}
|
|
|
|
public:
|
|
friend sprout::bitset<N>
|
|
sprout::operator& <N>(sprout::bitset<N> const& lhs, sprout::bitset<N> const& rhs) SPROUT_NOEXCEPT;
|
|
friend sprout::bitset<N>
|
|
sprout::operator| <N>(sprout::bitset<N> const& lhs, sprout::bitset<N> const& rhs) SPROUT_NOEXCEPT;
|
|
friend sprout::bitset<N>
|
|
sprout::operator^ <N>(sprout::bitset<N> const& lhs, sprout::bitset<N> const& rhs) SPROUT_NOEXCEPT;
|
|
template<typename Char, typename Traits, std::size_t M>
|
|
friend std::basic_istream<Char, Traits>&
|
|
sprout::operator>>(std::basic_istream<Char, Traits>& lhs, sprout::bitset<M>& rhs);
|
|
template <typename Char, typename Traits, std::size_t M>
|
|
friend std::basic_ostream<Char, Traits>&
|
|
sprout::operator<<(std::basic_ostream<Char, Traits>& lhs, sprout::bitset<M> const& rhs);
|
|
|
|
friend std::size_t
|
|
hash_value<N>(sprout::bitset<N> const& v);
|
|
};
|
|
|
|
// 20.5.4 bitset operators:
|
|
template<std::size_t N>
|
|
inline SPROUT_CONSTEXPR bitset<N>
|
|
operator&(sprout::bitset<N> const& lhs, sprout::bitset<N> const& rhs) SPROUT_NOEXCEPT {
|
|
return bitset<N>(lhs.do_and(rhs));
|
|
}
|
|
template<std::size_t N>
|
|
inline SPROUT_CONSTEXPR bitset<N>
|
|
operator|(sprout::bitset<N> const& lhs, sprout::bitset<N> const& rhs) SPROUT_NOEXCEPT {
|
|
return bitset<N>(lhs.do_or(rhs));
|
|
}
|
|
template <std::size_t N>
|
|
inline SPROUT_CONSTEXPR bitset<N>
|
|
operator^(sprout::bitset<N> const& lhs, sprout::bitset<N> const& rhs) SPROUT_NOEXCEPT {
|
|
return bitset<N>(lhs.do_xor(rhs));
|
|
}
|
|
template<typename Char, typename Traits, std::size_t N>
|
|
inline std::basic_istream<Char, Traits>&
|
|
operator>>(std::basic_istream<Char, Traits>& lhs, sprout::bitset<N>& rhs) {
|
|
typedef typename Traits::char_type char_type;
|
|
typedef std::basic_istream<Char, Traits> istream_type;
|
|
typedef typename istream_type::ios_base ios_base;
|
|
|
|
std::basic_string<Char, Traits> tmp;
|
|
tmp.reserve(N);
|
|
char_type const zero = lhs.widen('0');
|
|
char_type const one = lhs.widen('1');
|
|
typename ios_base::iostate state = ios_base::goodbit;
|
|
typename istream_type::sentry sentry(lhs);
|
|
if (sentry) {
|
|
try {
|
|
for (std::size_t i = N; i > 0; --i) {
|
|
static typename Traits::int_type eof = Traits::eof();
|
|
typename Traits::int_type c1 = lhs.rdbuf()->sbumpc();
|
|
if (Traits::eq_int_type(c1, eof)) {
|
|
state |= ios_base::eofbit;
|
|
break;
|
|
} else {
|
|
char_type const c2 = Traits::to_char_type(c1);
|
|
if (Traits::eq(c2, zero)) {
|
|
tmp.push_back(zero);
|
|
} else if (Traits::eq(c2, one)) {
|
|
tmp.push_back(one);
|
|
} else if (Traits::eq_int_type(lhs.rdbuf()->sputbackc(c2), eof)) {
|
|
state |= ios_base::failbit;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} catch(...) {
|
|
lhs.setstate(ios_base::badbit);
|
|
}
|
|
}
|
|
if (tmp.empty() && N) {
|
|
state |= ios_base::failbit;
|
|
} else {
|
|
rhs.copy_from_string(tmp, static_cast<std::size_t>(0), N, zero, one);
|
|
if (state) {
|
|
lhs.setstate(state);
|
|
return lhs;
|
|
}
|
|
}
|
|
return lhs;
|
|
}
|
|
template <typename Char, typename Traits, std::size_t N>
|
|
inline std::basic_ostream<Char, Traits>&
|
|
operator<<(std::basic_ostream<Char, Traits>& lhs, sprout::bitset<N> const& rhs) {
|
|
std::basic_string<Char, Traits> tmp;
|
|
std::ctype<Char> const& ct = std::use_facet<std::ctype<Char> >(lhs.getloc());
|
|
rhs.copy_to_string(tmp, ct.widen('0'), ct.widen('1'));
|
|
return lhs << tmp;
|
|
}
|
|
|
|
// 20.5.3 hash support
|
|
template<std::size_t N>
|
|
inline SPROUT_CONSTEXPR std::size_t
|
|
hash_value(sprout::bitset<N> const& v); // !!!
|
|
inline SPROUT_CONSTEXPR std::size_t
|
|
hash_value(sprout::bitset<0> const& v) {
|
|
return 0;
|
|
}
|
|
} // namespace sprout
|
|
|
|
#endif // #ifndef SPROUT_BITSET_HPP
|