Chris@16
|
1 // -----------------------------------------------------------
|
Chris@16
|
2 //
|
Chris@16
|
3 // Copyright (c) 2001-2002 Chuck Allison and Jeremy Siek
|
Chris@16
|
4 // Copyright (c) 2003-2006, 2008 Gennaro Prota
|
Chris@16
|
5 //
|
Chris@101
|
6 // Copyright (c) 2014 Glen Joseph Fernandes
|
Chris@101
|
7 // glenfe at live dot com
|
Chris@101
|
8 //
|
Chris@16
|
9 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
10 // (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
11 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
12 //
|
Chris@16
|
13 // -----------------------------------------------------------
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_DETAIL_DYNAMIC_BITSET_HPP
|
Chris@16
|
16 #define BOOST_DETAIL_DYNAMIC_BITSET_HPP
|
Chris@16
|
17
|
Chris@101
|
18 #include <memory>
|
Chris@16
|
19 #include <cstddef>
|
Chris@16
|
20 #include "boost/config.hpp"
|
Chris@16
|
21 #include "boost/detail/workaround.hpp"
|
Chris@16
|
22
|
Chris@16
|
23
|
Chris@16
|
24 namespace boost {
|
Chris@16
|
25
|
Chris@16
|
26 namespace detail {
|
Chris@16
|
27 namespace dynamic_bitset_impl {
|
Chris@16
|
28
|
Chris@16
|
29 // Gives (read-)access to the object representation
|
Chris@16
|
30 // of an object of type T (3.9p4). CANNOT be used
|
Chris@16
|
31 // on a base sub-object
|
Chris@16
|
32 //
|
Chris@16
|
33 template <typename T>
|
Chris@16
|
34 inline const unsigned char * object_representation (T* p)
|
Chris@16
|
35 {
|
Chris@16
|
36 return static_cast<const unsigned char *>(static_cast<const void *>(p));
|
Chris@16
|
37 }
|
Chris@16
|
38
|
Chris@16
|
39 template<typename T, int amount, int width /* = default */>
|
Chris@16
|
40 struct shifter
|
Chris@16
|
41 {
|
Chris@16
|
42 static void left_shift(T & v) {
|
Chris@16
|
43 amount >= width ? (v = 0)
|
Chris@16
|
44 : (v >>= BOOST_DYNAMIC_BITSET_WRAP_CONSTANT(amount));
|
Chris@16
|
45 }
|
Chris@16
|
46 };
|
Chris@16
|
47
|
Chris@16
|
48 // ------- count function implementation --------------
|
Chris@16
|
49
|
Chris@16
|
50 typedef unsigned char byte_type;
|
Chris@16
|
51
|
Chris@16
|
52 // These two entities
|
Chris@16
|
53 //
|
Chris@16
|
54 // enum mode { access_by_bytes, access_by_blocks };
|
Chris@16
|
55 // template <mode> struct mode_to_type {};
|
Chris@16
|
56 //
|
Chris@16
|
57 // were removed, since the regression logs (as of 24 Aug 2008)
|
Chris@16
|
58 // showed that several compilers had troubles with recognizing
|
Chris@16
|
59 //
|
Chris@16
|
60 // const mode m = access_by_bytes
|
Chris@16
|
61 //
|
Chris@16
|
62 // as a constant expression
|
Chris@16
|
63 //
|
Chris@16
|
64 // * So, we'll use bool, instead of enum *.
|
Chris@16
|
65 //
|
Chris@16
|
66 template <bool value>
|
Chris@16
|
67 struct value_to_type
|
Chris@16
|
68 {
|
Chris@16
|
69 value_to_type() {}
|
Chris@16
|
70 };
|
Chris@16
|
71 const bool access_by_bytes = true;
|
Chris@16
|
72 const bool access_by_blocks = false;
|
Chris@16
|
73
|
Chris@16
|
74
|
Chris@16
|
75 // the table: wrapped in a class template, so
|
Chris@16
|
76 // that it is only instantiated if/when needed
|
Chris@16
|
77 //
|
Chris@16
|
78 template <bool dummy_name = true>
|
Chris@16
|
79 struct count_table { static const byte_type table[]; };
|
Chris@16
|
80
|
Chris@16
|
81 template <>
|
Chris@16
|
82 struct count_table<false> { /* no table */ };
|
Chris@16
|
83
|
Chris@16
|
84
|
Chris@16
|
85 const unsigned int table_width = 8;
|
Chris@16
|
86 template <bool b>
|
Chris@16
|
87 const byte_type count_table<b>::table[] =
|
Chris@16
|
88 {
|
Chris@16
|
89 // Automatically generated by GPTableGen.exe v.1.0
|
Chris@16
|
90 //
|
Chris@16
|
91 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
Chris@16
|
92 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
Chris@16
|
93 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
Chris@16
|
94 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
Chris@16
|
95 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
Chris@16
|
96 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
Chris@16
|
97 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
Chris@16
|
98 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
|
Chris@16
|
99 };
|
Chris@16
|
100
|
Chris@16
|
101
|
Chris@16
|
102 // overload for access by bytes
|
Chris@16
|
103 //
|
Chris@16
|
104
|
Chris@16
|
105 template <typename Iterator>
|
Chris@16
|
106 inline std::size_t do_count(Iterator first, std::size_t length,
|
Chris@16
|
107 int /*dummy param*/,
|
Chris@16
|
108 value_to_type<access_by_bytes>* )
|
Chris@16
|
109 {
|
Chris@16
|
110 std::size_t num = 0;
|
Chris@16
|
111 if (length)
|
Chris@16
|
112 {
|
Chris@16
|
113 const byte_type * p = object_representation(&*first);
|
Chris@16
|
114 length *= sizeof(*first);
|
Chris@16
|
115
|
Chris@16
|
116 do {
|
Chris@16
|
117 num += count_table<>::table[*p];
|
Chris@16
|
118 ++p;
|
Chris@16
|
119 --length;
|
Chris@16
|
120
|
Chris@16
|
121 } while (length);
|
Chris@16
|
122 }
|
Chris@16
|
123
|
Chris@16
|
124 return num;
|
Chris@16
|
125 }
|
Chris@16
|
126
|
Chris@16
|
127
|
Chris@16
|
128 // overload for access by blocks
|
Chris@16
|
129 //
|
Chris@16
|
130 template <typename Iterator, typename ValueType>
|
Chris@16
|
131 inline std::size_t do_count(Iterator first, std::size_t length, ValueType,
|
Chris@16
|
132 value_to_type<access_by_blocks>*)
|
Chris@16
|
133 {
|
Chris@16
|
134 std::size_t num = 0;
|
Chris@16
|
135 while (length){
|
Chris@16
|
136
|
Chris@16
|
137 ValueType value = *first;
|
Chris@16
|
138 while (value) {
|
Chris@16
|
139 num += count_table<>::table[value & ((1u<<table_width) - 1)];
|
Chris@16
|
140 value >>= table_width;
|
Chris@16
|
141 }
|
Chris@16
|
142
|
Chris@16
|
143 ++first;
|
Chris@16
|
144 --length;
|
Chris@16
|
145 }
|
Chris@16
|
146
|
Chris@16
|
147 return num;
|
Chris@16
|
148 }
|
Chris@16
|
149
|
Chris@16
|
150 // -------------------------------------------------------
|
Chris@16
|
151
|
Chris@16
|
152
|
Chris@16
|
153 // Some library implementations simply return a dummy
|
Chris@16
|
154 // value such as
|
Chris@16
|
155 //
|
Chris@16
|
156 // size_type(-1) / sizeof(T)
|
Chris@16
|
157 //
|
Chris@16
|
158 // from vector<>::max_size. This tries to get more
|
Chris@16
|
159 // meaningful info.
|
Chris@16
|
160 //
|
Chris@16
|
161 template <typename T>
|
Chris@101
|
162 inline typename T::size_type vector_max_size_workaround(const T & v)
|
Chris@101
|
163 BOOST_NOEXCEPT
|
Chris@101
|
164 {
|
Chris@101
|
165 typedef typename T::allocator_type allocator_type;
|
Chris@16
|
166
|
Chris@101
|
167 const allocator_type& alloc = v.get_allocator();
|
Chris@16
|
168
|
Chris@101
|
169 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
Chris@101
|
170 typedef std::allocator_traits<allocator_type> allocator_traits;
|
Chris@16
|
171
|
Chris@101
|
172 const typename allocator_traits::size_type alloc_max =
|
Chris@101
|
173 allocator_traits::max_size(alloc);
|
Chris@101
|
174 #else
|
Chris@101
|
175 const typename allocator_type::size_type alloc_max = alloc.max_size();
|
Chris@101
|
176 #endif
|
Chris@101
|
177
|
Chris@101
|
178 const typename T::size_type container_max = v.max_size();
|
Chris@101
|
179
|
Chris@101
|
180 return alloc_max < container_max ? alloc_max : container_max;
|
Chris@16
|
181 }
|
Chris@16
|
182
|
Chris@16
|
183 // for static_asserts
|
Chris@16
|
184 template <typename T>
|
Chris@16
|
185 struct allowed_block_type {
|
Chris@16
|
186 enum { value = T(-1) > 0 }; // ensure T has no sign
|
Chris@16
|
187 };
|
Chris@16
|
188
|
Chris@16
|
189 template <>
|
Chris@16
|
190 struct allowed_block_type<bool> {
|
Chris@16
|
191 enum { value = false };
|
Chris@16
|
192 };
|
Chris@16
|
193
|
Chris@16
|
194
|
Chris@16
|
195 template <typename T>
|
Chris@16
|
196 struct is_numeric {
|
Chris@16
|
197 enum { value = false };
|
Chris@16
|
198 };
|
Chris@16
|
199
|
Chris@16
|
200 # define BOOST_dynamic_bitset_is_numeric(x) \
|
Chris@16
|
201 template<> \
|
Chris@16
|
202 struct is_numeric< x > { \
|
Chris@16
|
203 enum { value = true }; \
|
Chris@16
|
204 } /**/
|
Chris@16
|
205
|
Chris@16
|
206 BOOST_dynamic_bitset_is_numeric(bool);
|
Chris@16
|
207 BOOST_dynamic_bitset_is_numeric(char);
|
Chris@16
|
208
|
Chris@16
|
209 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
Chris@16
|
210 BOOST_dynamic_bitset_is_numeric(wchar_t);
|
Chris@16
|
211 #endif
|
Chris@16
|
212
|
Chris@16
|
213 BOOST_dynamic_bitset_is_numeric(signed char);
|
Chris@16
|
214 BOOST_dynamic_bitset_is_numeric(short int);
|
Chris@16
|
215 BOOST_dynamic_bitset_is_numeric(int);
|
Chris@16
|
216 BOOST_dynamic_bitset_is_numeric(long int);
|
Chris@16
|
217
|
Chris@16
|
218 BOOST_dynamic_bitset_is_numeric(unsigned char);
|
Chris@16
|
219 BOOST_dynamic_bitset_is_numeric(unsigned short);
|
Chris@16
|
220 BOOST_dynamic_bitset_is_numeric(unsigned int);
|
Chris@16
|
221 BOOST_dynamic_bitset_is_numeric(unsigned long);
|
Chris@16
|
222
|
Chris@16
|
223 #if defined(BOOST_HAS_LONG_LONG)
|
Chris@16
|
224 BOOST_dynamic_bitset_is_numeric(::boost::long_long_type);
|
Chris@16
|
225 BOOST_dynamic_bitset_is_numeric(::boost::ulong_long_type);
|
Chris@16
|
226 #endif
|
Chris@16
|
227
|
Chris@16
|
228 // intentionally omitted
|
Chris@16
|
229 //BOOST_dynamic_bitset_is_numeric(float);
|
Chris@16
|
230 //BOOST_dynamic_bitset_is_numeric(double);
|
Chris@16
|
231 //BOOST_dynamic_bitset_is_numeric(long double);
|
Chris@16
|
232
|
Chris@16
|
233 #undef BOOST_dynamic_bitset_is_numeric
|
Chris@16
|
234
|
Chris@16
|
235 } // dynamic_bitset_impl
|
Chris@16
|
236 } // namespace detail
|
Chris@16
|
237
|
Chris@16
|
238 } // namespace boost
|
Chris@16
|
239
|
Chris@16
|
240 #endif // include guard
|
Chris@16
|
241
|