-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbitarray.hh
125 lines (111 loc) · 3.59 KB
/
bitarray.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <cstdint>
#include <limits>
#include <iostream>
#include <bit>
#include <stdexcept>
#include <algorithm>
#include <optional>
#include <array>
#include <vector>
#include <span>
#include "pdep-pext.hh"
#include "bitarray-impl.hh"
namespace bitarray::detail
{
template<typename WordType>
constexpr size_t words_needed(size_t bits) {
if (bits == std::dynamic_extent)
{
return std::dynamic_extent;
}
else
{
size_t WordBits = std::numeric_limits<WordType>::digits;
return (bits + WordBits - 1) / WordBits;
}
}
template<typename Container>
constexpr size_t bits_in_container(Container data) {
return data.size() * std::numeric_limits<typename Container::value_type>::digits;
}
}
namespace bitarray {
template <size_t Bits, typename WordType>
struct bitarray_traits
{
using Container = std::array<WordType, detail::words_needed<WordType>(Bits)>;
};
template <size_t Bits, typename WordType = size_t>
struct bitarray : bitarray_impl<bitarray<Bits, WordType>, bitarray_traits<Bits, WordType>>
{
using self_type = bitarray<Bits, WordType>;
using base_type = bitarray_impl<bitarray<Bits, WordType>, bitarray_traits<Bits, WordType>>;
bitarray()
{
base_type::sanitize();
}
bitarray(std::initializer_list<WordType> l) : base_type(l) {}
};
template <typename WordType>
struct bitvector_traits
{
using Container = std::vector<WordType>;
};
template <typename WordType = size_t>
struct bitvector : bitarray_impl<bitvector<WordType>, bitvector_traits<WordType>>
{
using self_type = bitvector<WordType>;
using base_type = bitarray_impl<bitvector<WordType>, bitvector_traits<WordType>>;
size_t _size = std::dynamic_extent;
bitvector() {}
bitvector(std::vector<WordType> v) : base_type(v)
{
_size = detail::bits_in_container(base_type::data_);
}
bitvector(size_t size) : _size(size)
{
resize(_size);
}
bitvector(size_t size, std::vector<WordType> v) : base_type(v), _size(size)
{
base_type::sanitize();
}
void resize(size_t s)
{
size_t needed = detail::words_needed<WordType>(s);
if (std::size(base_type::data_) < needed)
{
base_type::data_.resize(needed);
}
_size = s;
}
};
template <size_t Bits, typename WordType>
struct bitspan_traits
{
using Container = std::span<WordType, detail::words_needed<WordType>(Bits)>;
};
template <size_t Bits = std::dynamic_extent, typename WordType = size_t>
struct bitspan : bitarray_impl<bitspan<Bits, WordType>, bitspan_traits<Bits, WordType>>
{
using self_type = bitspan<Bits, WordType>;
using base_type = bitarray_impl<bitspan<Bits, WordType>, bitspan_traits<Bits, WordType>>;
size_t _size;
bitspan(std::span<WordType, Bits> s) : base_type(s), _size(Bits) {}
bitspan(size_t size, std::span<WordType, Bits> s) : base_type(s), _size(size)
{
base_type::sanitize();
}
void resize(size_t s)
{
size_t needed = detail::words_needed<WordType>(s);
if (std::size(base_type::data_) < needed)
{
base_type::data_.resize(needed);
}
_size = s;
}
self_type operator<<(size_t) = delete;
self_type operator>>(size_t) = delete;
};
}