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