Chris@16
|
1
|
Chris@16
|
2 // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
|
Chris@16
|
3 // Copyright (C) 2005-2011 Daniel James
|
Chris@16
|
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6
|
Chris@16
|
7 #ifndef BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
|
Chris@16
|
8 #define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
|
Chris@16
|
9
|
Chris@101
|
10 #include <boost/config.hpp>
|
Chris@101
|
11 #if defined(BOOST_HAS_PRAGMA_ONCE)
|
Chris@101
|
12 #pragma once
|
Chris@16
|
13 #endif
|
Chris@16
|
14
|
Chris@16
|
15 #include <boost/type_traits/is_convertible.hpp>
|
Chris@16
|
16 #include <boost/type_traits/is_empty.hpp>
|
Chris@16
|
17 #include <boost/iterator/iterator_categories.hpp>
|
Chris@16
|
18 #include <boost/utility/enable_if.hpp>
|
Chris@16
|
19 #include <boost/detail/select_type.hpp>
|
Chris@16
|
20 #include <boost/move/move.hpp>
|
Chris@16
|
21 #include <boost/preprocessor/seq/size.hpp>
|
Chris@16
|
22 #include <boost/preprocessor/seq/enum.hpp>
|
Chris@16
|
23 #include <boost/swap.hpp>
|
Chris@16
|
24
|
Chris@16
|
25 namespace boost { namespace unordered { namespace detail {
|
Chris@16
|
26
|
Chris@16
|
27 static const float minimum_max_load_factor = 1e-3f;
|
Chris@16
|
28 static const std::size_t default_bucket_count = 11;
|
Chris@16
|
29 struct move_tag {};
|
Chris@16
|
30 struct empty_emplace {};
|
Chris@16
|
31
|
Chris@16
|
32 namespace func {
|
Chris@16
|
33 template <class T>
|
Chris@16
|
34 inline void ignore_unused_variable_warning(T const&) {}
|
Chris@16
|
35 }
|
Chris@16
|
36
|
Chris@16
|
37 ////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
38 // iterator SFINAE
|
Chris@16
|
39
|
Chris@16
|
40 template <typename I>
|
Chris@16
|
41 struct is_forward :
|
Chris@16
|
42 boost::is_convertible<
|
Chris@16
|
43 typename boost::iterator_traversal<I>::type,
|
Chris@16
|
44 boost::forward_traversal_tag>
|
Chris@16
|
45 {};
|
Chris@16
|
46
|
Chris@16
|
47 template <typename I, typename ReturnType>
|
Chris@16
|
48 struct enable_if_forward :
|
Chris@16
|
49 boost::enable_if_c<
|
Chris@16
|
50 boost::unordered::detail::is_forward<I>::value,
|
Chris@16
|
51 ReturnType>
|
Chris@16
|
52 {};
|
Chris@16
|
53
|
Chris@16
|
54 template <typename I, typename ReturnType>
|
Chris@16
|
55 struct disable_if_forward :
|
Chris@16
|
56 boost::disable_if_c<
|
Chris@16
|
57 boost::unordered::detail::is_forward<I>::value,
|
Chris@16
|
58 ReturnType>
|
Chris@16
|
59 {};
|
Chris@16
|
60
|
Chris@16
|
61 ////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
62 // primes
|
Chris@16
|
63
|
Chris@16
|
64 #define BOOST_UNORDERED_PRIMES \
|
Chris@16
|
65 (17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
|
Chris@16
|
66 (97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \
|
Chris@16
|
67 (1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \
|
Chris@16
|
68 (49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \
|
Chris@16
|
69 (1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul) \
|
Chris@16
|
70 (50331653ul)(100663319ul)(201326611ul)(402653189ul)(805306457ul) \
|
Chris@16
|
71 (1610612741ul)(3221225473ul)(4294967291ul)
|
Chris@16
|
72
|
Chris@16
|
73 template<class T> struct prime_list_template
|
Chris@16
|
74 {
|
Chris@16
|
75 static std::size_t const value[];
|
Chris@16
|
76
|
Chris@16
|
77 #if !defined(SUNPRO_CC)
|
Chris@16
|
78 static std::ptrdiff_t const length;
|
Chris@16
|
79 #else
|
Chris@16
|
80 static std::ptrdiff_t const length
|
Chris@16
|
81 = BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
|
Chris@16
|
82 #endif
|
Chris@16
|
83 };
|
Chris@16
|
84
|
Chris@16
|
85 template<class T>
|
Chris@16
|
86 std::size_t const prime_list_template<T>::value[] = {
|
Chris@16
|
87 BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIMES)
|
Chris@16
|
88 };
|
Chris@16
|
89
|
Chris@16
|
90 #if !defined(SUNPRO_CC)
|
Chris@16
|
91 template<class T>
|
Chris@16
|
92 std::ptrdiff_t const prime_list_template<T>::length
|
Chris@16
|
93 = BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
|
Chris@16
|
94 #endif
|
Chris@16
|
95
|
Chris@16
|
96 #undef BOOST_UNORDERED_PRIMES
|
Chris@16
|
97
|
Chris@16
|
98 typedef prime_list_template<std::size_t> prime_list;
|
Chris@16
|
99
|
Chris@16
|
100 // no throw
|
Chris@16
|
101 inline std::size_t next_prime(std::size_t num) {
|
Chris@16
|
102 std::size_t const* const prime_list_begin = prime_list::value;
|
Chris@16
|
103 std::size_t const* const prime_list_end = prime_list_begin +
|
Chris@16
|
104 prime_list::length;
|
Chris@16
|
105 std::size_t const* bound =
|
Chris@16
|
106 std::lower_bound(prime_list_begin, prime_list_end, num);
|
Chris@16
|
107 if(bound == prime_list_end)
|
Chris@16
|
108 bound--;
|
Chris@16
|
109 return *bound;
|
Chris@16
|
110 }
|
Chris@16
|
111
|
Chris@16
|
112 // no throw
|
Chris@16
|
113 inline std::size_t prev_prime(std::size_t num) {
|
Chris@16
|
114 std::size_t const* const prime_list_begin = prime_list::value;
|
Chris@16
|
115 std::size_t const* const prime_list_end = prime_list_begin +
|
Chris@16
|
116 prime_list::length;
|
Chris@16
|
117 std::size_t const* bound =
|
Chris@16
|
118 std::upper_bound(prime_list_begin,prime_list_end, num);
|
Chris@16
|
119 if(bound != prime_list_begin)
|
Chris@16
|
120 bound--;
|
Chris@16
|
121 return *bound;
|
Chris@16
|
122 }
|
Chris@16
|
123
|
Chris@16
|
124 ////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
125 // insert_size/initial_size
|
Chris@16
|
126
|
Chris@16
|
127 #if !defined(BOOST_NO_STD_DISTANCE)
|
Chris@16
|
128
|
Chris@16
|
129 using ::std::distance;
|
Chris@16
|
130
|
Chris@16
|
131 #else
|
Chris@16
|
132
|
Chris@16
|
133 template <class ForwardIterator>
|
Chris@16
|
134 inline std::size_t distance(ForwardIterator i, ForwardIterator j) {
|
Chris@16
|
135 std::size_t x;
|
Chris@16
|
136 std::distance(i, j, x);
|
Chris@16
|
137 return x;
|
Chris@16
|
138 }
|
Chris@16
|
139
|
Chris@16
|
140 #endif
|
Chris@16
|
141
|
Chris@16
|
142 template <class I>
|
Chris@16
|
143 inline typename
|
Chris@16
|
144 boost::unordered::detail::enable_if_forward<I, std::size_t>::type
|
Chris@16
|
145 insert_size(I i, I j)
|
Chris@16
|
146 {
|
Chris@16
|
147 return std::distance(i, j);
|
Chris@16
|
148 }
|
Chris@16
|
149
|
Chris@16
|
150 template <class I>
|
Chris@16
|
151 inline typename
|
Chris@16
|
152 boost::unordered::detail::disable_if_forward<I, std::size_t>::type
|
Chris@16
|
153 insert_size(I, I)
|
Chris@16
|
154 {
|
Chris@16
|
155 return 1;
|
Chris@16
|
156 }
|
Chris@16
|
157
|
Chris@16
|
158 template <class I>
|
Chris@16
|
159 inline std::size_t initial_size(I i, I j,
|
Chris@16
|
160 std::size_t num_buckets =
|
Chris@16
|
161 boost::unordered::detail::default_bucket_count)
|
Chris@16
|
162 {
|
Chris@16
|
163 // TODO: Why +1?
|
Chris@16
|
164 return (std::max)(
|
Chris@16
|
165 boost::unordered::detail::insert_size(i, j) + 1,
|
Chris@16
|
166 num_buckets);
|
Chris@16
|
167 }
|
Chris@16
|
168
|
Chris@16
|
169 ////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
170 // compressed
|
Chris@16
|
171
|
Chris@16
|
172 template <typename T, int Index>
|
Chris@16
|
173 struct compressed_base : private T
|
Chris@16
|
174 {
|
Chris@16
|
175 compressed_base(T const& x) : T(x) {}
|
Chris@16
|
176 compressed_base(T& x, move_tag) : T(boost::move(x)) {}
|
Chris@16
|
177
|
Chris@16
|
178 T& get() { return *this; }
|
Chris@16
|
179 T const& get() const { return *this; }
|
Chris@16
|
180 };
|
Chris@16
|
181
|
Chris@16
|
182 template <typename T, int Index>
|
Chris@16
|
183 struct uncompressed_base
|
Chris@16
|
184 {
|
Chris@16
|
185 uncompressed_base(T const& x) : value_(x) {}
|
Chris@16
|
186 uncompressed_base(T& x, move_tag) : value_(boost::move(x)) {}
|
Chris@16
|
187
|
Chris@16
|
188 T& get() { return value_; }
|
Chris@16
|
189 T const& get() const { return value_; }
|
Chris@16
|
190 private:
|
Chris@16
|
191 T value_;
|
Chris@16
|
192 };
|
Chris@16
|
193
|
Chris@16
|
194 template <typename T, int Index>
|
Chris@16
|
195 struct generate_base
|
Chris@16
|
196 : boost::detail::if_true<
|
Chris@16
|
197 boost::is_empty<T>::value
|
Chris@16
|
198 >:: BOOST_NESTED_TEMPLATE then<
|
Chris@16
|
199 boost::unordered::detail::compressed_base<T, Index>,
|
Chris@16
|
200 boost::unordered::detail::uncompressed_base<T, Index>
|
Chris@16
|
201 >
|
Chris@16
|
202 {};
|
Chris@16
|
203
|
Chris@16
|
204 template <typename T1, typename T2>
|
Chris@16
|
205 struct compressed
|
Chris@16
|
206 : private boost::unordered::detail::generate_base<T1, 1>::type,
|
Chris@16
|
207 private boost::unordered::detail::generate_base<T2, 2>::type
|
Chris@16
|
208 {
|
Chris@16
|
209 typedef typename generate_base<T1, 1>::type base1;
|
Chris@16
|
210 typedef typename generate_base<T2, 2>::type base2;
|
Chris@16
|
211
|
Chris@16
|
212 typedef T1 first_type;
|
Chris@16
|
213 typedef T2 second_type;
|
Chris@16
|
214
|
Chris@16
|
215 first_type& first() {
|
Chris@16
|
216 return static_cast<base1*>(this)->get();
|
Chris@16
|
217 }
|
Chris@16
|
218
|
Chris@16
|
219 first_type const& first() const {
|
Chris@16
|
220 return static_cast<base1 const*>(this)->get();
|
Chris@16
|
221 }
|
Chris@16
|
222
|
Chris@16
|
223 second_type& second() {
|
Chris@16
|
224 return static_cast<base2*>(this)->get();
|
Chris@16
|
225 }
|
Chris@16
|
226
|
Chris@16
|
227 second_type const& second() const {
|
Chris@16
|
228 return static_cast<base2 const*>(this)->get();
|
Chris@16
|
229 }
|
Chris@16
|
230
|
Chris@16
|
231 template <typename First, typename Second>
|
Chris@16
|
232 compressed(First const& x1, Second const& x2)
|
Chris@16
|
233 : base1(x1), base2(x2) {}
|
Chris@16
|
234
|
Chris@16
|
235 compressed(compressed const& x)
|
Chris@16
|
236 : base1(x.first()), base2(x.second()) {}
|
Chris@16
|
237
|
Chris@16
|
238 compressed(compressed& x, move_tag m)
|
Chris@16
|
239 : base1(x.first(), m), base2(x.second(), m) {}
|
Chris@16
|
240
|
Chris@16
|
241 void assign(compressed const& x)
|
Chris@16
|
242 {
|
Chris@16
|
243 first() = x.first();
|
Chris@16
|
244 second() = x.second();
|
Chris@16
|
245 }
|
Chris@16
|
246
|
Chris@16
|
247 void move_assign(compressed& x)
|
Chris@16
|
248 {
|
Chris@16
|
249 first() = boost::move(x.first());
|
Chris@16
|
250 second() = boost::move(x.second());
|
Chris@16
|
251 }
|
Chris@16
|
252
|
Chris@16
|
253 void swap(compressed& x)
|
Chris@16
|
254 {
|
Chris@16
|
255 boost::swap(first(), x.first());
|
Chris@16
|
256 boost::swap(second(), x.second());
|
Chris@16
|
257 }
|
Chris@16
|
258
|
Chris@16
|
259 private:
|
Chris@16
|
260 // Prevent assignment just to make use of assign or
|
Chris@16
|
261 // move_assign explicit.
|
Chris@16
|
262 compressed& operator=(compressed const&);
|
Chris@16
|
263 };
|
Chris@16
|
264 }}}
|
Chris@16
|
265
|
Chris@16
|
266 #endif
|