xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/tr1/hashtable_policy.h (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj // Internal policy header for TR1 unordered_set and unordered_map -*- C++ -*-
2*38fd1498Szrj 
3*38fd1498Szrj // Copyright (C) 2010-2018 Free Software Foundation, Inc.
4*38fd1498Szrj //
5*38fd1498Szrj // This file is part of the GNU ISO C++ Library.  This library is free
6*38fd1498Szrj // software; you can redistribute it and/or modify it under the
7*38fd1498Szrj // terms of the GNU General Public License as published by the
8*38fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj // any later version.
10*38fd1498Szrj 
11*38fd1498Szrj // This library is distributed in the hope that it will be useful,
12*38fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*38fd1498Szrj // GNU General Public License for more details.
15*38fd1498Szrj 
16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
18*38fd1498Szrj // 3.1, as published by the Free Software Foundation.
19*38fd1498Szrj 
20*38fd1498Szrj // You should have received a copy of the GNU General Public License and
21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*38fd1498Szrj // <http://www.gnu.org/licenses/>.
24*38fd1498Szrj 
25*38fd1498Szrj /** @file tr1/hashtable_policy.h
26*38fd1498Szrj  *  This is an internal header file, included by other library headers.
27*38fd1498Szrj  *  Do not attempt to use it directly.
28*38fd1498Szrj  *  @headername{tr1/unordered_map, tr1/unordered_set}
29*38fd1498Szrj  */
30*38fd1498Szrj 
_GLIBCXX_VISIBILITY(default)31*38fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
32*38fd1498Szrj {
33*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
34*38fd1498Szrj 
35*38fd1498Szrj namespace tr1
36*38fd1498Szrj {
37*38fd1498Szrj namespace __detail
38*38fd1498Szrj {
39*38fd1498Szrj   // Helper function: return distance(first, last) for forward
40*38fd1498Szrj   // iterators, or 0 for input iterators.
41*38fd1498Szrj   template<class _Iterator>
42*38fd1498Szrj     inline typename std::iterator_traits<_Iterator>::difference_type
43*38fd1498Szrj     __distance_fw(_Iterator __first, _Iterator __last,
44*38fd1498Szrj 		  std::input_iterator_tag)
45*38fd1498Szrj     { return 0; }
46*38fd1498Szrj 
47*38fd1498Szrj   template<class _Iterator>
48*38fd1498Szrj     inline typename std::iterator_traits<_Iterator>::difference_type
49*38fd1498Szrj     __distance_fw(_Iterator __first, _Iterator __last,
50*38fd1498Szrj 		  std::forward_iterator_tag)
51*38fd1498Szrj     { return std::distance(__first, __last); }
52*38fd1498Szrj 
53*38fd1498Szrj   template<class _Iterator>
54*38fd1498Szrj     inline typename std::iterator_traits<_Iterator>::difference_type
55*38fd1498Szrj     __distance_fw(_Iterator __first, _Iterator __last)
56*38fd1498Szrj     {
57*38fd1498Szrj       typedef typename std::iterator_traits<_Iterator>::iterator_category _Tag;
58*38fd1498Szrj       return __distance_fw(__first, __last, _Tag());
59*38fd1498Szrj     }
60*38fd1498Szrj 
61*38fd1498Szrj   // Auxiliary types used for all instantiations of _Hashtable: nodes
62*38fd1498Szrj   // and iterators.
63*38fd1498Szrj 
64*38fd1498Szrj   // Nodes, used to wrap elements stored in the hash table.  A policy
65*38fd1498Szrj   // template parameter of class template _Hashtable controls whether
66*38fd1498Szrj   // nodes also store a hash code. In some cases (e.g. strings) this
67*38fd1498Szrj   // may be a performance win.
68*38fd1498Szrj   template<typename _Value, bool __cache_hash_code>
69*38fd1498Szrj     struct _Hash_node;
70*38fd1498Szrj 
71*38fd1498Szrj   template<typename _Value>
72*38fd1498Szrj     struct _Hash_node<_Value, true>
73*38fd1498Szrj     {
74*38fd1498Szrj       _Value       _M_v;
75*38fd1498Szrj       std::size_t  _M_hash_code;
76*38fd1498Szrj       _Hash_node*  _M_next;
77*38fd1498Szrj     };
78*38fd1498Szrj 
79*38fd1498Szrj   template<typename _Value>
80*38fd1498Szrj     struct _Hash_node<_Value, false>
81*38fd1498Szrj     {
82*38fd1498Szrj       _Value       _M_v;
83*38fd1498Szrj       _Hash_node*  _M_next;
84*38fd1498Szrj     };
85*38fd1498Szrj 
86*38fd1498Szrj   // Local iterators, used to iterate within a bucket but not between
87*38fd1498Szrj   // buckets.
88*38fd1498Szrj   template<typename _Value, bool __cache>
89*38fd1498Szrj     struct _Node_iterator_base
90*38fd1498Szrj     {
91*38fd1498Szrj       _Node_iterator_base(_Hash_node<_Value, __cache>* __p)
92*38fd1498Szrj       : _M_cur(__p) { }
93*38fd1498Szrj 
94*38fd1498Szrj       void
95*38fd1498Szrj       _M_incr()
96*38fd1498Szrj       { _M_cur = _M_cur->_M_next; }
97*38fd1498Szrj 
98*38fd1498Szrj       _Hash_node<_Value, __cache>*  _M_cur;
99*38fd1498Szrj     };
100*38fd1498Szrj 
101*38fd1498Szrj   template<typename _Value, bool __cache>
102*38fd1498Szrj     inline bool
103*38fd1498Szrj     operator==(const _Node_iterator_base<_Value, __cache>& __x,
104*38fd1498Szrj 	       const _Node_iterator_base<_Value, __cache>& __y)
105*38fd1498Szrj     { return __x._M_cur == __y._M_cur; }
106*38fd1498Szrj 
107*38fd1498Szrj   template<typename _Value, bool __cache>
108*38fd1498Szrj     inline bool
109*38fd1498Szrj     operator!=(const _Node_iterator_base<_Value, __cache>& __x,
110*38fd1498Szrj 	       const _Node_iterator_base<_Value, __cache>& __y)
111*38fd1498Szrj     { return __x._M_cur != __y._M_cur; }
112*38fd1498Szrj 
113*38fd1498Szrj   template<typename _Value, bool __constant_iterators, bool __cache>
114*38fd1498Szrj     struct _Node_iterator
115*38fd1498Szrj     : public _Node_iterator_base<_Value, __cache>
116*38fd1498Szrj     {
117*38fd1498Szrj       typedef _Value                                   value_type;
118*38fd1498Szrj       typedef typename
119*38fd1498Szrj       __gnu_cxx::__conditional_type<__constant_iterators,
120*38fd1498Szrj 				    const _Value*, _Value*>::__type
121*38fd1498Szrj                                                        pointer;
122*38fd1498Szrj       typedef typename
123*38fd1498Szrj       __gnu_cxx::__conditional_type<__constant_iterators,
124*38fd1498Szrj 				    const _Value&, _Value&>::__type
125*38fd1498Szrj                                                        reference;
126*38fd1498Szrj       typedef std::ptrdiff_t                           difference_type;
127*38fd1498Szrj       typedef std::forward_iterator_tag                iterator_category;
128*38fd1498Szrj 
129*38fd1498Szrj       _Node_iterator()
130*38fd1498Szrj       : _Node_iterator_base<_Value, __cache>(0) { }
131*38fd1498Szrj 
132*38fd1498Szrj       explicit
133*38fd1498Szrj       _Node_iterator(_Hash_node<_Value, __cache>* __p)
134*38fd1498Szrj       : _Node_iterator_base<_Value, __cache>(__p) { }
135*38fd1498Szrj 
136*38fd1498Szrj       reference
137*38fd1498Szrj       operator*() const
138*38fd1498Szrj       { return this->_M_cur->_M_v; }
139*38fd1498Szrj 
140*38fd1498Szrj       pointer
141*38fd1498Szrj       operator->() const
142*38fd1498Szrj       { return std::__addressof(this->_M_cur->_M_v); }
143*38fd1498Szrj 
144*38fd1498Szrj       _Node_iterator&
145*38fd1498Szrj       operator++()
146*38fd1498Szrj       {
147*38fd1498Szrj 	this->_M_incr();
148*38fd1498Szrj 	return *this;
149*38fd1498Szrj       }
150*38fd1498Szrj 
151*38fd1498Szrj       _Node_iterator
152*38fd1498Szrj       operator++(int)
153*38fd1498Szrj       {
154*38fd1498Szrj 	_Node_iterator __tmp(*this);
155*38fd1498Szrj 	this->_M_incr();
156*38fd1498Szrj 	return __tmp;
157*38fd1498Szrj       }
158*38fd1498Szrj     };
159*38fd1498Szrj 
160*38fd1498Szrj   template<typename _Value, bool __constant_iterators, bool __cache>
161*38fd1498Szrj     struct _Node_const_iterator
162*38fd1498Szrj     : public _Node_iterator_base<_Value, __cache>
163*38fd1498Szrj     {
164*38fd1498Szrj       typedef _Value                                   value_type;
165*38fd1498Szrj       typedef const _Value*                            pointer;
166*38fd1498Szrj       typedef const _Value&                            reference;
167*38fd1498Szrj       typedef std::ptrdiff_t                           difference_type;
168*38fd1498Szrj       typedef std::forward_iterator_tag                iterator_category;
169*38fd1498Szrj 
170*38fd1498Szrj       _Node_const_iterator()
171*38fd1498Szrj       : _Node_iterator_base<_Value, __cache>(0) { }
172*38fd1498Szrj 
173*38fd1498Szrj       explicit
174*38fd1498Szrj       _Node_const_iterator(_Hash_node<_Value, __cache>* __p)
175*38fd1498Szrj       : _Node_iterator_base<_Value, __cache>(__p) { }
176*38fd1498Szrj 
177*38fd1498Szrj       _Node_const_iterator(const _Node_iterator<_Value, __constant_iterators,
178*38fd1498Szrj 			   __cache>& __x)
179*38fd1498Szrj       : _Node_iterator_base<_Value, __cache>(__x._M_cur) { }
180*38fd1498Szrj 
181*38fd1498Szrj       reference
182*38fd1498Szrj       operator*() const
183*38fd1498Szrj       { return this->_M_cur->_M_v; }
184*38fd1498Szrj 
185*38fd1498Szrj       pointer
186*38fd1498Szrj       operator->() const
187*38fd1498Szrj       { return std::__addressof(this->_M_cur->_M_v); }
188*38fd1498Szrj 
189*38fd1498Szrj       _Node_const_iterator&
190*38fd1498Szrj       operator++()
191*38fd1498Szrj       {
192*38fd1498Szrj 	this->_M_incr();
193*38fd1498Szrj 	return *this;
194*38fd1498Szrj       }
195*38fd1498Szrj 
196*38fd1498Szrj       _Node_const_iterator
197*38fd1498Szrj       operator++(int)
198*38fd1498Szrj       {
199*38fd1498Szrj 	_Node_const_iterator __tmp(*this);
200*38fd1498Szrj 	this->_M_incr();
201*38fd1498Szrj 	return __tmp;
202*38fd1498Szrj       }
203*38fd1498Szrj     };
204*38fd1498Szrj 
205*38fd1498Szrj   template<typename _Value, bool __cache>
206*38fd1498Szrj     struct _Hashtable_iterator_base
207*38fd1498Szrj     {
208*38fd1498Szrj       _Hashtable_iterator_base(_Hash_node<_Value, __cache>* __node,
209*38fd1498Szrj 			       _Hash_node<_Value, __cache>** __bucket)
210*38fd1498Szrj       : _M_cur_node(__node), _M_cur_bucket(__bucket) { }
211*38fd1498Szrj 
212*38fd1498Szrj       void
213*38fd1498Szrj       _M_incr()
214*38fd1498Szrj       {
215*38fd1498Szrj 	_M_cur_node = _M_cur_node->_M_next;
216*38fd1498Szrj 	if (!_M_cur_node)
217*38fd1498Szrj 	  _M_incr_bucket();
218*38fd1498Szrj       }
219*38fd1498Szrj 
220*38fd1498Szrj       void
221*38fd1498Szrj       _M_incr_bucket();
222*38fd1498Szrj 
223*38fd1498Szrj       _Hash_node<_Value, __cache>*   _M_cur_node;
224*38fd1498Szrj       _Hash_node<_Value, __cache>**  _M_cur_bucket;
225*38fd1498Szrj     };
226*38fd1498Szrj 
227*38fd1498Szrj   // Global iterators, used for arbitrary iteration within a hash
228*38fd1498Szrj   // table.  Larger and more expensive than local iterators.
229*38fd1498Szrj   template<typename _Value, bool __cache>
230*38fd1498Szrj     void
231*38fd1498Szrj     _Hashtable_iterator_base<_Value, __cache>::
232*38fd1498Szrj     _M_incr_bucket()
233*38fd1498Szrj     {
234*38fd1498Szrj       ++_M_cur_bucket;
235*38fd1498Szrj 
236*38fd1498Szrj       // This loop requires the bucket array to have a non-null sentinel.
237*38fd1498Szrj       while (!*_M_cur_bucket)
238*38fd1498Szrj 	++_M_cur_bucket;
239*38fd1498Szrj       _M_cur_node = *_M_cur_bucket;
240*38fd1498Szrj     }
241*38fd1498Szrj 
242*38fd1498Szrj   template<typename _Value, bool __cache>
243*38fd1498Szrj     inline bool
244*38fd1498Szrj     operator==(const _Hashtable_iterator_base<_Value, __cache>& __x,
245*38fd1498Szrj 	       const _Hashtable_iterator_base<_Value, __cache>& __y)
246*38fd1498Szrj     { return __x._M_cur_node == __y._M_cur_node; }
247*38fd1498Szrj 
248*38fd1498Szrj   template<typename _Value, bool __cache>
249*38fd1498Szrj     inline bool
250*38fd1498Szrj     operator!=(const _Hashtable_iterator_base<_Value, __cache>& __x,
251*38fd1498Szrj 	       const _Hashtable_iterator_base<_Value, __cache>& __y)
252*38fd1498Szrj     { return __x._M_cur_node != __y._M_cur_node; }
253*38fd1498Szrj 
254*38fd1498Szrj   template<typename _Value, bool __constant_iterators, bool __cache>
255*38fd1498Szrj     struct _Hashtable_iterator
256*38fd1498Szrj     : public _Hashtable_iterator_base<_Value, __cache>
257*38fd1498Szrj     {
258*38fd1498Szrj       typedef _Value                                   value_type;
259*38fd1498Szrj       typedef typename
260*38fd1498Szrj       __gnu_cxx::__conditional_type<__constant_iterators,
261*38fd1498Szrj 				    const _Value*, _Value*>::__type
262*38fd1498Szrj                                                        pointer;
263*38fd1498Szrj       typedef typename
264*38fd1498Szrj       __gnu_cxx::__conditional_type<__constant_iterators,
265*38fd1498Szrj 				    const _Value&, _Value&>::__type
266*38fd1498Szrj                                                        reference;
267*38fd1498Szrj       typedef std::ptrdiff_t                           difference_type;
268*38fd1498Szrj       typedef std::forward_iterator_tag                iterator_category;
269*38fd1498Szrj 
270*38fd1498Szrj       _Hashtable_iterator()
271*38fd1498Szrj       : _Hashtable_iterator_base<_Value, __cache>(0, 0) { }
272*38fd1498Szrj 
273*38fd1498Szrj       _Hashtable_iterator(_Hash_node<_Value, __cache>* __p,
274*38fd1498Szrj 			  _Hash_node<_Value, __cache>** __b)
275*38fd1498Szrj       : _Hashtable_iterator_base<_Value, __cache>(__p, __b) { }
276*38fd1498Szrj 
277*38fd1498Szrj       explicit
278*38fd1498Szrj       _Hashtable_iterator(_Hash_node<_Value, __cache>** __b)
279*38fd1498Szrj       : _Hashtable_iterator_base<_Value, __cache>(*__b, __b) { }
280*38fd1498Szrj 
281*38fd1498Szrj       reference
282*38fd1498Szrj       operator*() const
283*38fd1498Szrj       { return this->_M_cur_node->_M_v; }
284*38fd1498Szrj 
285*38fd1498Szrj       pointer
286*38fd1498Szrj       operator->() const
287*38fd1498Szrj       { return std::__addressof(this->_M_cur_node->_M_v); }
288*38fd1498Szrj 
289*38fd1498Szrj       _Hashtable_iterator&
290*38fd1498Szrj       operator++()
291*38fd1498Szrj       {
292*38fd1498Szrj 	this->_M_incr();
293*38fd1498Szrj 	return *this;
294*38fd1498Szrj       }
295*38fd1498Szrj 
296*38fd1498Szrj       _Hashtable_iterator
297*38fd1498Szrj       operator++(int)
298*38fd1498Szrj       {
299*38fd1498Szrj 	_Hashtable_iterator __tmp(*this);
300*38fd1498Szrj 	this->_M_incr();
301*38fd1498Szrj 	return __tmp;
302*38fd1498Szrj       }
303*38fd1498Szrj     };
304*38fd1498Szrj 
305*38fd1498Szrj   template<typename _Value, bool __constant_iterators, bool __cache>
306*38fd1498Szrj     struct _Hashtable_const_iterator
307*38fd1498Szrj     : public _Hashtable_iterator_base<_Value, __cache>
308*38fd1498Szrj     {
309*38fd1498Szrj       typedef _Value                                   value_type;
310*38fd1498Szrj       typedef const _Value*                            pointer;
311*38fd1498Szrj       typedef const _Value&                            reference;
312*38fd1498Szrj       typedef std::ptrdiff_t                           difference_type;
313*38fd1498Szrj       typedef std::forward_iterator_tag                iterator_category;
314*38fd1498Szrj 
315*38fd1498Szrj       _Hashtable_const_iterator()
316*38fd1498Szrj       : _Hashtable_iterator_base<_Value, __cache>(0, 0) { }
317*38fd1498Szrj 
318*38fd1498Szrj       _Hashtable_const_iterator(_Hash_node<_Value, __cache>* __p,
319*38fd1498Szrj 				_Hash_node<_Value, __cache>** __b)
320*38fd1498Szrj       : _Hashtable_iterator_base<_Value, __cache>(__p, __b) { }
321*38fd1498Szrj 
322*38fd1498Szrj       explicit
323*38fd1498Szrj       _Hashtable_const_iterator(_Hash_node<_Value, __cache>** __b)
324*38fd1498Szrj       : _Hashtable_iterator_base<_Value, __cache>(*__b, __b) { }
325*38fd1498Szrj 
326*38fd1498Szrj       _Hashtable_const_iterator(const _Hashtable_iterator<_Value,
327*38fd1498Szrj 				__constant_iterators, __cache>& __x)
328*38fd1498Szrj       : _Hashtable_iterator_base<_Value, __cache>(__x._M_cur_node,
329*38fd1498Szrj 						  __x._M_cur_bucket) { }
330*38fd1498Szrj 
331*38fd1498Szrj       reference
332*38fd1498Szrj       operator*() const
333*38fd1498Szrj       { return this->_M_cur_node->_M_v; }
334*38fd1498Szrj 
335*38fd1498Szrj       pointer
336*38fd1498Szrj       operator->() const
337*38fd1498Szrj       { return std::__addressof(this->_M_cur_node->_M_v); }
338*38fd1498Szrj 
339*38fd1498Szrj       _Hashtable_const_iterator&
340*38fd1498Szrj       operator++()
341*38fd1498Szrj       {
342*38fd1498Szrj 	this->_M_incr();
343*38fd1498Szrj 	return *this;
344*38fd1498Szrj       }
345*38fd1498Szrj 
346*38fd1498Szrj       _Hashtable_const_iterator
347*38fd1498Szrj       operator++(int)
348*38fd1498Szrj       {
349*38fd1498Szrj 	_Hashtable_const_iterator __tmp(*this);
350*38fd1498Szrj 	this->_M_incr();
351*38fd1498Szrj 	return __tmp;
352*38fd1498Szrj       }
353*38fd1498Szrj     };
354*38fd1498Szrj 
355*38fd1498Szrj 
356*38fd1498Szrj   // Many of class template _Hashtable's template parameters are policy
357*38fd1498Szrj   // classes.  These are defaults for the policies.
358*38fd1498Szrj 
359*38fd1498Szrj   // Default range hashing function: use division to fold a large number
360*38fd1498Szrj   // into the range [0, N).
361*38fd1498Szrj   struct _Mod_range_hashing
362*38fd1498Szrj   {
363*38fd1498Szrj     typedef std::size_t first_argument_type;
364*38fd1498Szrj     typedef std::size_t second_argument_type;
365*38fd1498Szrj     typedef std::size_t result_type;
366*38fd1498Szrj 
367*38fd1498Szrj     result_type
368*38fd1498Szrj     operator()(first_argument_type __num, second_argument_type __den) const
369*38fd1498Szrj     { return __num % __den; }
370*38fd1498Szrj   };
371*38fd1498Szrj 
372*38fd1498Szrj   // Default ranged hash function H.  In principle it should be a
373*38fd1498Szrj   // function object composed from objects of type H1 and H2 such that
374*38fd1498Szrj   // h(k, N) = h2(h1(k), N), but that would mean making extra copies of
375*38fd1498Szrj   // h1 and h2.  So instead we'll just use a tag to tell class template
376*38fd1498Szrj   // hashtable to do that composition.
377*38fd1498Szrj   struct _Default_ranged_hash { };
378*38fd1498Szrj 
379*38fd1498Szrj   // Default value for rehash policy.  Bucket size is (usually) the
380*38fd1498Szrj   // smallest prime that keeps the load factor small enough.
381*38fd1498Szrj   struct _Prime_rehash_policy
382*38fd1498Szrj   {
383*38fd1498Szrj     _Prime_rehash_policy(float __z = 1.0)
384*38fd1498Szrj     : _M_max_load_factor(__z), _M_growth_factor(2.f), _M_next_resize(0) { }
385*38fd1498Szrj 
386*38fd1498Szrj     float
387*38fd1498Szrj     max_load_factor() const
388*38fd1498Szrj     { return _M_max_load_factor; }
389*38fd1498Szrj 
390*38fd1498Szrj     // Return a bucket size no smaller than n.
391*38fd1498Szrj     std::size_t
392*38fd1498Szrj     _M_next_bkt(std::size_t __n) const;
393*38fd1498Szrj 
394*38fd1498Szrj     // Return a bucket count appropriate for n elements
395*38fd1498Szrj     std::size_t
396*38fd1498Szrj     _M_bkt_for_elements(std::size_t __n) const;
397*38fd1498Szrj 
398*38fd1498Szrj     // __n_bkt is current bucket count, __n_elt is current element count,
399*38fd1498Szrj     // and __n_ins is number of elements to be inserted.  Do we need to
400*38fd1498Szrj     // increase bucket count?  If so, return make_pair(true, n), where n
401*38fd1498Szrj     // is the new bucket count.  If not, return make_pair(false, 0).
402*38fd1498Szrj     std::pair<bool, std::size_t>
403*38fd1498Szrj     _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
404*38fd1498Szrj 		   std::size_t __n_ins) const;
405*38fd1498Szrj 
406*38fd1498Szrj     enum { _S_n_primes = sizeof(unsigned long) != 8 ? 256 : 256 + 48 };
407*38fd1498Szrj 
408*38fd1498Szrj     float                _M_max_load_factor;
409*38fd1498Szrj     float                _M_growth_factor;
410*38fd1498Szrj     mutable std::size_t  _M_next_resize;
411*38fd1498Szrj   };
412*38fd1498Szrj 
413*38fd1498Szrj   extern const unsigned long __prime_list[];
414*38fd1498Szrj 
415*38fd1498Szrj   // XXX This is a hack.  There's no good reason for any of
416*38fd1498Szrj   // _Prime_rehash_policy's member functions to be inline.
417*38fd1498Szrj 
418*38fd1498Szrj   // Return a prime no smaller than n.
419*38fd1498Szrj   inline std::size_t
420*38fd1498Szrj   _Prime_rehash_policy::
421*38fd1498Szrj   _M_next_bkt(std::size_t __n) const
422*38fd1498Szrj   {
423*38fd1498Szrj     // Don't include the last prime in the search, so that anything
424*38fd1498Szrj     // higher than the second-to-last prime returns a past-the-end
425*38fd1498Szrj     // iterator that can be dereferenced to get the last prime.
426*38fd1498Szrj     const unsigned long* __p
427*38fd1498Szrj       = std::lower_bound(__prime_list, __prime_list + _S_n_primes - 1, __n);
428*38fd1498Szrj     _M_next_resize =
429*38fd1498Szrj       static_cast<std::size_t>(__builtin_ceil(*__p * _M_max_load_factor));
430*38fd1498Szrj     return *__p;
431*38fd1498Szrj   }
432*38fd1498Szrj 
433*38fd1498Szrj   // Return the smallest prime p such that alpha p >= n, where alpha
434*38fd1498Szrj   // is the load factor.
435*38fd1498Szrj   inline std::size_t
436*38fd1498Szrj   _Prime_rehash_policy::
437*38fd1498Szrj   _M_bkt_for_elements(std::size_t __n) const
438*38fd1498Szrj   {
439*38fd1498Szrj     const float __min_bkts = __n / _M_max_load_factor;
440*38fd1498Szrj     return _M_next_bkt(__builtin_ceil(__min_bkts));
441*38fd1498Szrj   }
442*38fd1498Szrj 
443*38fd1498Szrj   // Finds the smallest prime p such that alpha p > __n_elt + __n_ins.
444*38fd1498Szrj   // If p > __n_bkt, return make_pair(true, p); otherwise return
445*38fd1498Szrj   // make_pair(false, 0).  In principle this isn't very different from
446*38fd1498Szrj   // _M_bkt_for_elements.
447*38fd1498Szrj 
448*38fd1498Szrj   // The only tricky part is that we're caching the element count at
449*38fd1498Szrj   // which we need to rehash, so we don't have to do a floating-point
450*38fd1498Szrj   // multiply for every insertion.
451*38fd1498Szrj 
452*38fd1498Szrj   inline std::pair<bool, std::size_t>
453*38fd1498Szrj   _Prime_rehash_policy::
454*38fd1498Szrj   _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
455*38fd1498Szrj 		 std::size_t __n_ins) const
456*38fd1498Szrj   {
457*38fd1498Szrj     if (__n_elt + __n_ins > _M_next_resize)
458*38fd1498Szrj       {
459*38fd1498Szrj 	float __min_bkts = ((float(__n_ins) + float(__n_elt))
460*38fd1498Szrj 			    / _M_max_load_factor);
461*38fd1498Szrj 	if (__min_bkts > __n_bkt)
462*38fd1498Szrj 	  {
463*38fd1498Szrj 	    __min_bkts = std::max(__min_bkts, _M_growth_factor * __n_bkt);
464*38fd1498Szrj 	    return std::make_pair(true,
465*38fd1498Szrj 				  _M_next_bkt(__builtin_ceil(__min_bkts)));
466*38fd1498Szrj 	  }
467*38fd1498Szrj 	else
468*38fd1498Szrj 	  {
469*38fd1498Szrj 	    _M_next_resize = static_cast<std::size_t>
470*38fd1498Szrj 	      (__builtin_ceil(__n_bkt * _M_max_load_factor));
471*38fd1498Szrj 	    return std::make_pair(false, 0);
472*38fd1498Szrj 	  }
473*38fd1498Szrj       }
474*38fd1498Szrj     else
475*38fd1498Szrj       return std::make_pair(false, 0);
476*38fd1498Szrj   }
477*38fd1498Szrj 
478*38fd1498Szrj   // Base classes for std::tr1::_Hashtable.  We define these base
479*38fd1498Szrj   // classes because in some cases we want to do different things
480*38fd1498Szrj   // depending on the value of a policy class.  In some cases the
481*38fd1498Szrj   // policy class affects which member functions and nested typedefs
482*38fd1498Szrj   // are defined; we handle that by specializing base class templates.
483*38fd1498Szrj   // Several of the base class templates need to access other members
484*38fd1498Szrj   // of class template _Hashtable, so we use the "curiously recurring
485*38fd1498Szrj   // template pattern" for them.
486*38fd1498Szrj 
487*38fd1498Szrj   // class template _Map_base.  If the hashtable has a value type of the
488*38fd1498Szrj   // form pair<T1, T2> and a key extraction policy that returns the
489*38fd1498Szrj   // first part of the pair, the hashtable gets a mapped_type typedef.
490*38fd1498Szrj   // If it satisfies those criteria and also has unique keys, then it
491*38fd1498Szrj   // also gets an operator[].
492*38fd1498Szrj   template<typename _Key, typename _Value, typename _Ex, bool __unique,
493*38fd1498Szrj 	   typename _Hashtable>
494*38fd1498Szrj     struct _Map_base { };
495*38fd1498Szrj 
496*38fd1498Szrj   template<typename _Key, typename _Pair, typename _Hashtable>
497*38fd1498Szrj     struct _Map_base<_Key, _Pair, std::_Select1st<_Pair>, false, _Hashtable>
498*38fd1498Szrj     {
499*38fd1498Szrj       typedef typename _Pair::second_type mapped_type;
500*38fd1498Szrj     };
501*38fd1498Szrj 
502*38fd1498Szrj   template<typename _Key, typename _Pair, typename _Hashtable>
503*38fd1498Szrj     struct _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>
504*38fd1498Szrj     {
505*38fd1498Szrj       typedef typename _Pair::second_type mapped_type;
506*38fd1498Szrj 
507*38fd1498Szrj       mapped_type&
508*38fd1498Szrj       operator[](const _Key& __k);
509*38fd1498Szrj     };
510*38fd1498Szrj 
511*38fd1498Szrj   template<typename _Key, typename _Pair, typename _Hashtable>
512*38fd1498Szrj     typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
513*38fd1498Szrj 		       true, _Hashtable>::mapped_type&
514*38fd1498Szrj     _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
515*38fd1498Szrj     operator[](const _Key& __k)
516*38fd1498Szrj     {
517*38fd1498Szrj       _Hashtable* __h = static_cast<_Hashtable*>(this);
518*38fd1498Szrj       typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
519*38fd1498Szrj       std::size_t __n = __h->_M_bucket_index(__k, __code,
520*38fd1498Szrj 					     __h->_M_bucket_count);
521*38fd1498Szrj 
522*38fd1498Szrj       typename _Hashtable::_Node* __p =
523*38fd1498Szrj 	__h->_M_find_node(__h->_M_buckets[__n], __k, __code);
524*38fd1498Szrj       if (!__p)
525*38fd1498Szrj 	return __h->_M_insert_bucket(std::make_pair(__k, mapped_type()),
526*38fd1498Szrj 				     __n, __code)->second;
527*38fd1498Szrj       return (__p->_M_v).second;
528*38fd1498Szrj     }
529*38fd1498Szrj 
530*38fd1498Szrj   // class template _Rehash_base.  Give hashtable the max_load_factor
531*38fd1498Szrj   // functions iff the rehash policy is _Prime_rehash_policy.
532*38fd1498Szrj   template<typename _RehashPolicy, typename _Hashtable>
533*38fd1498Szrj     struct _Rehash_base { };
534*38fd1498Szrj 
535*38fd1498Szrj   template<typename _Hashtable>
536*38fd1498Szrj     struct _Rehash_base<_Prime_rehash_policy, _Hashtable>
537*38fd1498Szrj     {
538*38fd1498Szrj       float
539*38fd1498Szrj       max_load_factor() const
540*38fd1498Szrj       {
541*38fd1498Szrj 	const _Hashtable* __this = static_cast<const _Hashtable*>(this);
542*38fd1498Szrj 	return __this->__rehash_policy().max_load_factor();
543*38fd1498Szrj       }
544*38fd1498Szrj 
545*38fd1498Szrj       void
546*38fd1498Szrj       max_load_factor(float __z)
547*38fd1498Szrj       {
548*38fd1498Szrj 	_Hashtable* __this = static_cast<_Hashtable*>(this);
549*38fd1498Szrj 	__this->__rehash_policy(_Prime_rehash_policy(__z));
550*38fd1498Szrj       }
551*38fd1498Szrj     };
552*38fd1498Szrj 
553*38fd1498Szrj   // Class template _Hash_code_base.  Encapsulates two policy issues that
554*38fd1498Szrj   // aren't quite orthogonal.
555*38fd1498Szrj   //   (1) the difference between using a ranged hash function and using
556*38fd1498Szrj   //       the combination of a hash function and a range-hashing function.
557*38fd1498Szrj   //       In the former case we don't have such things as hash codes, so
558*38fd1498Szrj   //       we have a dummy type as placeholder.
559*38fd1498Szrj   //   (2) Whether or not we cache hash codes.  Caching hash codes is
560*38fd1498Szrj   //       meaningless if we have a ranged hash function.
561*38fd1498Szrj   // We also put the key extraction and equality comparison function
562*38fd1498Szrj   // objects here, for convenience.
563*38fd1498Szrj 
564*38fd1498Szrj   // Primary template: unused except as a hook for specializations.
565*38fd1498Szrj   template<typename _Key, typename _Value,
566*38fd1498Szrj 	   typename _ExtractKey, typename _Equal,
567*38fd1498Szrj 	   typename _H1, typename _H2, typename _Hash,
568*38fd1498Szrj 	   bool __cache_hash_code>
569*38fd1498Szrj     struct _Hash_code_base;
570*38fd1498Szrj 
571*38fd1498Szrj   // Specialization: ranged hash function, no caching hash codes.  H1
572*38fd1498Szrj   // and H2 are provided but ignored.  We define a dummy hash code type.
573*38fd1498Szrj   template<typename _Key, typename _Value,
574*38fd1498Szrj 	   typename _ExtractKey, typename _Equal,
575*38fd1498Szrj 	   typename _H1, typename _H2, typename _Hash>
576*38fd1498Szrj     struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
577*38fd1498Szrj 			   _Hash, false>
578*38fd1498Szrj     {
579*38fd1498Szrj     protected:
580*38fd1498Szrj       _Hash_code_base(const _ExtractKey& __ex, const _Equal& __eq,
581*38fd1498Szrj 		      const _H1&, const _H2&, const _Hash& __h)
582*38fd1498Szrj       : _M_extract(__ex), _M_eq(__eq), _M_ranged_hash(__h) { }
583*38fd1498Szrj 
584*38fd1498Szrj       typedef void* _Hash_code_type;
585*38fd1498Szrj 
586*38fd1498Szrj       _Hash_code_type
587*38fd1498Szrj       _M_hash_code(const _Key& __key) const
588*38fd1498Szrj       { return 0; }
589*38fd1498Szrj 
590*38fd1498Szrj       std::size_t
591*38fd1498Szrj       _M_bucket_index(const _Key& __k, _Hash_code_type,
592*38fd1498Szrj 		      std::size_t __n) const
593*38fd1498Szrj       { return _M_ranged_hash(__k, __n); }
594*38fd1498Szrj 
595*38fd1498Szrj       std::size_t
596*38fd1498Szrj       _M_bucket_index(const _Hash_node<_Value, false>* __p,
597*38fd1498Szrj 		      std::size_t __n) const
598*38fd1498Szrj       { return _M_ranged_hash(_M_extract(__p->_M_v), __n); }
599*38fd1498Szrj 
600*38fd1498Szrj       bool
601*38fd1498Szrj       _M_compare(const _Key& __k, _Hash_code_type,
602*38fd1498Szrj 		 _Hash_node<_Value, false>* __n) const
603*38fd1498Szrj       { return _M_eq(__k, _M_extract(__n->_M_v)); }
604*38fd1498Szrj 
605*38fd1498Szrj       void
606*38fd1498Szrj       _M_store_code(_Hash_node<_Value, false>*, _Hash_code_type) const
607*38fd1498Szrj       { }
608*38fd1498Szrj 
609*38fd1498Szrj       void
610*38fd1498Szrj       _M_copy_code(_Hash_node<_Value, false>*,
611*38fd1498Szrj 		   const _Hash_node<_Value, false>*) const
612*38fd1498Szrj       { }
613*38fd1498Szrj 
614*38fd1498Szrj       void
615*38fd1498Szrj       _M_swap(_Hash_code_base& __x)
616*38fd1498Szrj       {
617*38fd1498Szrj 	std::swap(_M_extract, __x._M_extract);
618*38fd1498Szrj 	std::swap(_M_eq, __x._M_eq);
619*38fd1498Szrj 	std::swap(_M_ranged_hash, __x._M_ranged_hash);
620*38fd1498Szrj       }
621*38fd1498Szrj 
622*38fd1498Szrj     protected:
623*38fd1498Szrj       _ExtractKey  _M_extract;
624*38fd1498Szrj       _Equal       _M_eq;
625*38fd1498Szrj       _Hash        _M_ranged_hash;
626*38fd1498Szrj     };
627*38fd1498Szrj 
628*38fd1498Szrj 
629*38fd1498Szrj   // No specialization for ranged hash function while caching hash codes.
630*38fd1498Szrj   // That combination is meaningless, and trying to do it is an error.
631*38fd1498Szrj 
632*38fd1498Szrj 
633*38fd1498Szrj   // Specialization: ranged hash function, cache hash codes.  This
634*38fd1498Szrj   // combination is meaningless, so we provide only a declaration
635*38fd1498Szrj   // and no definition.
636*38fd1498Szrj   template<typename _Key, typename _Value,
637*38fd1498Szrj 	   typename _ExtractKey, typename _Equal,
638*38fd1498Szrj 	   typename _H1, typename _H2, typename _Hash>
639*38fd1498Szrj     struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
640*38fd1498Szrj 			   _Hash, true>;
641*38fd1498Szrj 
642*38fd1498Szrj   // Specialization: hash function and range-hashing function, no
643*38fd1498Szrj   // caching of hash codes.  H is provided but ignored.  Provides
644*38fd1498Szrj   // typedef and accessor required by TR1.
645*38fd1498Szrj   template<typename _Key, typename _Value,
646*38fd1498Szrj 	   typename _ExtractKey, typename _Equal,
647*38fd1498Szrj 	   typename _H1, typename _H2>
648*38fd1498Szrj     struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
649*38fd1498Szrj 			   _Default_ranged_hash, false>
650*38fd1498Szrj     {
651*38fd1498Szrj       typedef _H1 hasher;
652*38fd1498Szrj 
653*38fd1498Szrj       hasher
654*38fd1498Szrj       hash_function() const
655*38fd1498Szrj       { return _M_h1; }
656*38fd1498Szrj 
657*38fd1498Szrj     protected:
658*38fd1498Szrj       _Hash_code_base(const _ExtractKey& __ex, const _Equal& __eq,
659*38fd1498Szrj 		      const _H1& __h1, const _H2& __h2,
660*38fd1498Szrj 		      const _Default_ranged_hash&)
661*38fd1498Szrj       : _M_extract(__ex), _M_eq(__eq), _M_h1(__h1), _M_h2(__h2) { }
662*38fd1498Szrj 
663*38fd1498Szrj       typedef std::size_t _Hash_code_type;
664*38fd1498Szrj 
665*38fd1498Szrj       _Hash_code_type
666*38fd1498Szrj       _M_hash_code(const _Key& __k) const
667*38fd1498Szrj       { return _M_h1(__k); }
668*38fd1498Szrj 
669*38fd1498Szrj       std::size_t
670*38fd1498Szrj       _M_bucket_index(const _Key&, _Hash_code_type __c,
671*38fd1498Szrj 		      std::size_t __n) const
672*38fd1498Szrj       { return _M_h2(__c, __n); }
673*38fd1498Szrj 
674*38fd1498Szrj       std::size_t
675*38fd1498Szrj       _M_bucket_index(const _Hash_node<_Value, false>* __p,
676*38fd1498Szrj 		      std::size_t __n) const
677*38fd1498Szrj       { return _M_h2(_M_h1(_M_extract(__p->_M_v)), __n); }
678*38fd1498Szrj 
679*38fd1498Szrj       bool
680*38fd1498Szrj       _M_compare(const _Key& __k, _Hash_code_type,
681*38fd1498Szrj 		 _Hash_node<_Value, false>* __n) const
682*38fd1498Szrj       { return _M_eq(__k, _M_extract(__n->_M_v)); }
683*38fd1498Szrj 
684*38fd1498Szrj       void
685*38fd1498Szrj       _M_store_code(_Hash_node<_Value, false>*, _Hash_code_type) const
686*38fd1498Szrj       { }
687*38fd1498Szrj 
688*38fd1498Szrj       void
689*38fd1498Szrj       _M_copy_code(_Hash_node<_Value, false>*,
690*38fd1498Szrj 		   const _Hash_node<_Value, false>*) const
691*38fd1498Szrj       { }
692*38fd1498Szrj 
693*38fd1498Szrj       void
694*38fd1498Szrj       _M_swap(_Hash_code_base& __x)
695*38fd1498Szrj       {
696*38fd1498Szrj 	std::swap(_M_extract, __x._M_extract);
697*38fd1498Szrj 	std::swap(_M_eq, __x._M_eq);
698*38fd1498Szrj 	std::swap(_M_h1, __x._M_h1);
699*38fd1498Szrj 	std::swap(_M_h2, __x._M_h2);
700*38fd1498Szrj       }
701*38fd1498Szrj 
702*38fd1498Szrj     protected:
703*38fd1498Szrj       _ExtractKey  _M_extract;
704*38fd1498Szrj       _Equal       _M_eq;
705*38fd1498Szrj       _H1          _M_h1;
706*38fd1498Szrj       _H2          _M_h2;
707*38fd1498Szrj     };
708*38fd1498Szrj 
709*38fd1498Szrj   // Specialization: hash function and range-hashing function,
710*38fd1498Szrj   // caching hash codes.  H is provided but ignored.  Provides
711*38fd1498Szrj   // typedef and accessor required by TR1.
712*38fd1498Szrj   template<typename _Key, typename _Value,
713*38fd1498Szrj 	   typename _ExtractKey, typename _Equal,
714*38fd1498Szrj 	   typename _H1, typename _H2>
715*38fd1498Szrj     struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
716*38fd1498Szrj 			   _Default_ranged_hash, true>
717*38fd1498Szrj     {
718*38fd1498Szrj       typedef _H1 hasher;
719*38fd1498Szrj 
720*38fd1498Szrj       hasher
721*38fd1498Szrj       hash_function() const
722*38fd1498Szrj       { return _M_h1; }
723*38fd1498Szrj 
724*38fd1498Szrj     protected:
725*38fd1498Szrj       _Hash_code_base(const _ExtractKey& __ex, const _Equal& __eq,
726*38fd1498Szrj 		      const _H1& __h1, const _H2& __h2,
727*38fd1498Szrj 		      const _Default_ranged_hash&)
728*38fd1498Szrj       : _M_extract(__ex), _M_eq(__eq), _M_h1(__h1), _M_h2(__h2) { }
729*38fd1498Szrj 
730*38fd1498Szrj       typedef std::size_t _Hash_code_type;
731*38fd1498Szrj 
732*38fd1498Szrj       _Hash_code_type
733*38fd1498Szrj       _M_hash_code(const _Key& __k) const
734*38fd1498Szrj       { return _M_h1(__k); }
735*38fd1498Szrj 
736*38fd1498Szrj       std::size_t
737*38fd1498Szrj       _M_bucket_index(const _Key&, _Hash_code_type __c,
738*38fd1498Szrj 		      std::size_t __n) const
739*38fd1498Szrj       { return _M_h2(__c, __n); }
740*38fd1498Szrj 
741*38fd1498Szrj       std::size_t
742*38fd1498Szrj       _M_bucket_index(const _Hash_node<_Value, true>* __p,
743*38fd1498Szrj 		      std::size_t __n) const
744*38fd1498Szrj       { return _M_h2(__p->_M_hash_code, __n); }
745*38fd1498Szrj 
746*38fd1498Szrj       bool
747*38fd1498Szrj       _M_compare(const _Key& __k, _Hash_code_type __c,
748*38fd1498Szrj 		 _Hash_node<_Value, true>* __n) const
749*38fd1498Szrj       { return __c == __n->_M_hash_code && _M_eq(__k, _M_extract(__n->_M_v)); }
750*38fd1498Szrj 
751*38fd1498Szrj       void
752*38fd1498Szrj       _M_store_code(_Hash_node<_Value, true>* __n, _Hash_code_type __c) const
753*38fd1498Szrj       { __n->_M_hash_code = __c; }
754*38fd1498Szrj 
755*38fd1498Szrj       void
756*38fd1498Szrj       _M_copy_code(_Hash_node<_Value, true>* __to,
757*38fd1498Szrj 		   const _Hash_node<_Value, true>* __from) const
758*38fd1498Szrj       { __to->_M_hash_code = __from->_M_hash_code; }
759*38fd1498Szrj 
760*38fd1498Szrj       void
761*38fd1498Szrj       _M_swap(_Hash_code_base& __x)
762*38fd1498Szrj       {
763*38fd1498Szrj 	std::swap(_M_extract, __x._M_extract);
764*38fd1498Szrj 	std::swap(_M_eq, __x._M_eq);
765*38fd1498Szrj 	std::swap(_M_h1, __x._M_h1);
766*38fd1498Szrj 	std::swap(_M_h2, __x._M_h2);
767*38fd1498Szrj       }
768*38fd1498Szrj 
769*38fd1498Szrj     protected:
770*38fd1498Szrj       _ExtractKey  _M_extract;
771*38fd1498Szrj       _Equal       _M_eq;
772*38fd1498Szrj       _H1          _M_h1;
773*38fd1498Szrj       _H2          _M_h2;
774*38fd1498Szrj     };
775*38fd1498Szrj } // namespace __detail
776*38fd1498Szrj }
777*38fd1498Szrj 
778*38fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
779*38fd1498Szrj }
780