1 // -*- C++ -*-
2 
3 // Copyright (C) 2005, 2006, 2009, 2011, 2012 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the terms
7 // of the GNU General Public License as published by the Free Software
8 // Foundation; either version 3, or (at your option) any later
9 // version.
10 
11 // This library is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
26 
27 // Permission to use, copy, modify, sell, and distribute this software
28 // is hereby granted without fee, provided that the above copyright
29 // notice appears in all copies, and that both that copyright notice
30 // and this permission notice appear in supporting documentation. None
31 // of the above authors, nor IBM Haifa Research Laboratories, make any
32 // representation about the suitability of this software for any
33 // purpose. It is provided "as is" without express or implied
34 // warranty.
35 
36 /**
37  * @file pat_trie_/pat_trie_base.hpp
38  * Contains the base class for a patricia tree.
39  */
40 
41 #ifndef PB_DS_PAT_TRIE_BASE
42 #define PB_DS_PAT_TRIE_BASE
43 
44 #include <debug/debug.h>
45 
46 namespace __gnu_pbds
47 {
48   namespace detail
49   {
50     /// Base type for PATRICIA trees.
51     struct pat_trie_base
52     {
53       /**
54        *  @brief  Three types of nodes.
55        *
56        *  i_node is used by _Inode, leaf_node by _Leaf, and head_node by _Head.
57        */
58       enum node_type
59 	{
60 	  i_node,
61 	  leaf_node,
62 	  head_node
63 	};
64 
65       /// Metadata base primary template.
66       template<typename Metadata, typename _Alloc>
67 	struct _Metadata
68 	{
69 	  typedef Metadata     					metadata_type;
70 	  typedef _Alloc     					allocator_type;
71 	  typedef typename _Alloc::template rebind<Metadata>	__rebind_m;
72 	  typedef typename __rebind_m::other::const_reference  const_reference;
73 
74 	  const_reference
75 	  get_metadata() const
76 	  { return m_metadata; }
77 
78 	  metadata_type 					m_metadata;
79 	};
80 
81       /// Specialization for null metadata.
82       template<typename _Alloc>
83 	struct _Metadata<null_type, _Alloc>
84 	{
85 	  typedef null_type 					metadata_type;
86 	  typedef _Alloc     					allocator_type;
87 	};
88 
89 
90       /// Node base.
91       template<typename _ATraits, typename Metadata>
92       struct _Node_base
93       : public Metadata
94       {
95       private:
96 	typedef typename Metadata::allocator_type		_Alloc;
97 
98       public:
99 	typedef _Alloc						allocator_type;
100 	typedef _ATraits					access_traits;
101 	typedef typename _ATraits::type_traits			type_traits;
102 	typedef typename _Alloc::template rebind<_Node_base>	__rebind_n;
103 	typedef typename __rebind_n::other::pointer 		node_pointer;
104 
105 	node_pointer 						m_p_parent;
106 	const node_type 	       				m_type;
107 
108 	_Node_base(node_type type) : m_type(type)
109 	{ }
110 
111 	typedef typename _Alloc::template rebind<_ATraits>    __rebind_at;
112 	typedef typename __rebind_at::other::const_pointer    a_const_pointer;
113 	typedef typename _ATraits::const_iterator	      a_const_iterator;
114 
115 #ifdef _GLIBCXX_DEBUG
116 	typedef std::pair<a_const_iterator, a_const_iterator> node_debug_info;
117 
118 	void
119 	assert_valid(a_const_pointer p_traits,
120 		     const char* __file, int __line) const
121 	{ assert_valid_imp(p_traits, __file, __line); }
122 
123 	virtual node_debug_info
124 	assert_valid_imp(a_const_pointer, const char*, int) const = 0;
125 #endif
126       };
127 
128 
129     /// Head node for PATRICIA tree.
130     template<typename _ATraits, typename Metadata>
131     struct _Head
132     : public _Node_base<_ATraits, Metadata>
133     {
134       typedef _Node_base<_ATraits, Metadata> 			base_type;
135       typedef typename base_type::type_traits			type_traits;
136       typedef typename base_type::node_pointer			node_pointer;
137 
138       node_pointer						m_p_min;
139       node_pointer						m_p_max;
140 
141       _Head() : base_type(head_node) { }
142 
143 #ifdef _GLIBCXX_DEBUG
144       typedef typename base_type::node_debug_info      	       node_debug_info;
145       typedef typename base_type::a_const_pointer 	       a_const_pointer;
146 
147       virtual node_debug_info
148       assert_valid_imp(a_const_pointer, const char* __file, int __line) const
149       {
150 	_GLIBCXX_DEBUG_VERIFY_AT(false,
151 				 _M_message("Assertion from %1;:%2;")
152 				 ._M_string(__FILE__)._M_integer(__LINE__),
153 				 __file, __line);
154 	return node_debug_info();
155       }
156 #endif
157     };
158 
159 
160     /// Leaf node for PATRICIA tree.
161     template<typename _ATraits, typename Metadata>
162     struct _Leaf
163     : public _Node_base<_ATraits, Metadata>
164     {
165       typedef _Node_base<_ATraits, Metadata> 	   	    	base_type;
166       typedef typename base_type::type_traits			type_traits;
167       typedef typename type_traits::value_type			value_type;
168       typedef typename type_traits::reference			reference;
169       typedef typename type_traits::const_reference    		const_reference;
170 
171     private:
172       value_type						m_value;
173 
174       _Leaf(const _Leaf&);
175 
176     public:
177       _Leaf(const_reference other)
178       : base_type(leaf_node), m_value(other) { }
179 
180       reference
181       value()
182       { return m_value; }
183 
184       const_reference
185       value() const
186       { return m_value; }
187 
188 #ifdef _GLIBCXX_DEBUG
189       typedef typename base_type::node_debug_info      		node_debug_info;
190       typedef typename base_type::a_const_pointer      		a_const_pointer;
191 
192       virtual node_debug_info
193       assert_valid_imp(a_const_pointer p_traits,
194 		       const char* __file, int __line) const
195       {
196 	PB_DS_DEBUG_VERIFY(base_type::m_type == leaf_node);
197 	node_debug_info ret;
198 	const_reference r_val = value();
199 	return std::make_pair(p_traits->begin(p_traits->extract_key(r_val)),
200 			      p_traits->end(p_traits->extract_key(r_val)));
201       }
202 
203       virtual
204       ~_Leaf() { }
205 #endif
206     };
207 
208 
209     /// Internal node type, PATRICIA tree.
210     template<typename _ATraits, typename Metadata>
211     struct _Inode
212     : public _Node_base<_ATraits, Metadata>
213     {
214       typedef _Node_base<_ATraits, Metadata> 			base_type;
215       typedef typename base_type::type_traits			type_traits;
216       typedef typename base_type::access_traits	       		access_traits;
217       typedef typename type_traits::value_type 			value_type;
218       typedef typename base_type::allocator_type		_Alloc;
219       typedef _Alloc						allocator_type;
220       typedef typename _Alloc::size_type 			size_type;
221 
222     private:
223       typedef typename base_type::a_const_pointer      	       a_const_pointer;
224       typedef typename base_type::a_const_iterator     	      a_const_iterator;
225 
226       typedef typename base_type::node_pointer			node_pointer;
227       typedef typename _Alloc::template rebind<base_type>	__rebind_n;
228       typedef typename __rebind_n::other::const_pointer      node_const_pointer;
229 
230       typedef _Leaf<_ATraits, Metadata>	 			leaf;
231       typedef typename _Alloc::template rebind<leaf>::other 	__rebind_l;
232       typedef typename __rebind_l::pointer 			leaf_pointer;
233       typedef typename __rebind_l::const_pointer 	    leaf_const_pointer;
234 
235       typedef typename _Alloc::template rebind<_Inode>::other 	__rebind_in;
236       typedef typename __rebind_in::pointer 			inode_pointer;
237       typedef typename __rebind_in::const_pointer 	    inode_const_pointer;
238 
239       inline size_type
240       get_pref_pos(a_const_iterator, a_const_iterator, a_const_pointer) const;
241 
242     public:
243       typedef typename _Alloc::template rebind<node_pointer>::other __rebind_np;
244       typedef typename __rebind_np::pointer 		node_pointer_pointer;
245       typedef typename __rebind_np::reference 		node_pointer_reference;
246 
247       enum
248 	{
249 	  arr_size = _ATraits::max_size + 1
250 	};
251       PB_DS_STATIC_ASSERT(min_arr_size, arr_size >= 2);
252 
253 
254       /// Constant child iterator.
255       struct const_iterator
256       {
257 	node_pointer_pointer 				m_p_p_cur;
258 	node_pointer_pointer 				m_p_p_end;
259 
260 	typedef std::forward_iterator_tag 		iterator_category;
261 	typedef typename _Alloc::difference_type 	difference_type;
262 	typedef node_pointer 				value_type;
263 	typedef node_pointer_pointer 			pointer;
264 	typedef node_pointer_reference 			reference;
265 
266 	const_iterator(node_pointer_pointer p_p_cur = 0,
267 		       node_pointer_pointer p_p_end = 0)
268 	: m_p_p_cur(p_p_cur), m_p_p_end(p_p_end)
269 	{ }
270 
271 	bool
272 	operator==(const const_iterator& other) const
273 	{ return m_p_p_cur == other.m_p_p_cur; }
274 
275 	bool
276 	operator!=(const const_iterator& other) const
277 	{ return m_p_p_cur != other.m_p_p_cur; }
278 
279 	const_iterator&
280 	operator++()
281 	{
282 	  do
283 	    ++m_p_p_cur;
284 	  while (m_p_p_cur != m_p_p_end && *m_p_p_cur == 0);
285 	  return *this;
286 	}
287 
288 	const_iterator
289 	operator++(int)
290 	{
291 	  const_iterator ret_it(*this);
292 	  operator++();
293 	  return ret_it;
294 	}
295 
296 	const node_pointer_pointer
297 	operator->() const
298 	{
299 	  _GLIBCXX_DEBUG_ONLY(assert_referencible();)
300 	  return m_p_p_cur;
301 	}
302 
303 	node_const_pointer
304 	operator*() const
305 	{
306 	  _GLIBCXX_DEBUG_ONLY(assert_referencible();)
307 	  return *m_p_p_cur;
308 	}
309 
310       protected:
311 #ifdef _GLIBCXX_DEBUG
312 	void
313 	assert_referencible() const
314 	{ _GLIBCXX_DEBUG_ASSERT(m_p_p_cur != m_p_p_end && *m_p_p_cur != 0); }
315 #endif
316       };
317 
318 
319       /// Child iterator.
320       struct iterator : public const_iterator
321       {
322       public:
323 	typedef std::forward_iterator_tag 		iterator_category;
324 	typedef typename _Alloc::difference_type 	difference_type;
325 	typedef node_pointer 				value_type;
326 	typedef node_pointer_pointer 			pointer;
327 	typedef node_pointer_reference 			reference;
328 
329 	inline
330 	iterator(node_pointer_pointer p_p_cur = 0,
331 		 node_pointer_pointer p_p_end = 0)
332 	: const_iterator(p_p_cur, p_p_end) { }
333 
334 	bool
335 	operator==(const iterator& other) const
336 	{ return const_iterator::m_p_p_cur == other.m_p_p_cur; }
337 
338 	bool
339 	operator!=(const iterator& other) const
340 	{ return const_iterator::m_p_p_cur != other.m_p_p_cur; }
341 
342 	iterator&
343 	operator++()
344 	{
345 	  const_iterator::operator++();
346 	  return *this;
347 	}
348 
349 	iterator
350 	operator++(int)
351 	{
352 	  iterator ret_it(*this);
353 	  operator++();
354 	  return ret_it;
355 	}
356 
357 	node_pointer_pointer
358 	operator->()
359 	{
360 	  _GLIBCXX_DEBUG_ONLY(const_iterator::assert_referencible();)
361 	  return const_iterator::m_p_p_cur;
362 	}
363 
364 	node_pointer
365 	operator*()
366 	{
367 	  _GLIBCXX_DEBUG_ONLY(const_iterator::assert_referencible();)
368 	  return *const_iterator::m_p_p_cur;
369 	}
370       };
371 
372 
373       _Inode(size_type, const a_const_iterator);
374 
375       void
376       update_prefixes(a_const_pointer);
377 
378       const_iterator
379       begin() const;
380 
381       iterator
382       begin();
383 
384       const_iterator
385       end() const;
386 
387       iterator
388       end();
389 
390       inline node_pointer
391       get_child_node(a_const_iterator, a_const_iterator, a_const_pointer);
392 
393       inline node_const_pointer
394       get_child_node(a_const_iterator, a_const_iterator, a_const_pointer) const;
395 
396       inline iterator
397       get_child_it(a_const_iterator, a_const_iterator, a_const_pointer);
398 
399       inline node_pointer
400       get_lower_bound_child_node(a_const_iterator, a_const_iterator,
401 				 size_type, a_const_pointer);
402 
403       inline node_pointer
404       add_child(node_pointer, a_const_iterator, a_const_iterator,
405 		a_const_pointer);
406 
407       inline node_const_pointer
408       get_join_child(node_const_pointer, a_const_pointer) const;
409 
410       inline node_pointer
411       get_join_child(node_pointer, a_const_pointer);
412 
413       void
414       remove_child(node_pointer);
415 
416       void
417       remove_child(iterator);
418 
419       void
420       replace_child(node_pointer, a_const_iterator, a_const_iterator,
421 		    a_const_pointer);
422 
423       inline a_const_iterator
424       pref_b_it() const;
425 
426       inline a_const_iterator
427       pref_e_it() const;
428 
429       bool
430       should_be_mine(a_const_iterator, a_const_iterator, size_type,
431 		     a_const_pointer) const;
432 
433       leaf_pointer
434       leftmost_descendant();
435 
436       leaf_const_pointer
437       leftmost_descendant() const;
438 
439       leaf_pointer
440       rightmost_descendant();
441 
442       leaf_const_pointer
443       rightmost_descendant() const;
444 
445 #ifdef _GLIBCXX_DEBUG
446       typedef typename base_type::node_debug_info 	       node_debug_info;
447 
448       virtual node_debug_info
449       assert_valid_imp(a_const_pointer, const char*, int) const;
450 #endif
451 
452       size_type
453       get_e_ind() const
454       { return m_e_ind; }
455 
456     private:
457       _Inode(const _Inode&);
458 
459       size_type
460       get_begin_pos() const;
461 
462       static __rebind_l			s_leaf_alloc;
463       static __rebind_in 		s_inode_alloc;
464 
465       const size_type 			m_e_ind;
466       a_const_iterator 			m_pref_b_it;
467       a_const_iterator 			m_pref_e_it;
468       node_pointer 			m_a_p_children[arr_size];
469     };
470 
471 #define PB_DS_CONST_IT_C_DEC \
472     _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
473 
474 #define PB_DS_CONST_ODIR_IT_C_DEC \
475     _CIter<Node, Leaf, Head, Inode, !Is_Forward_Iterator>
476 
477 #define PB_DS_IT_C_DEC \
478     _Iter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
479 
480 #define PB_DS_ODIR_IT_C_DEC \
481     _Iter<Node, Leaf, Head, Inode, !Is_Forward_Iterator>
482 
483 
484     /// Const iterator.
485     template<typename Node, typename Leaf, typename Head, typename Inode,
486 	     bool Is_Forward_Iterator>
487     class _CIter
488     {
489     public:
490       // These types are all the same for the first four template arguments.
491       typedef typename Node::allocator_type		allocator_type;
492       typedef typename Node::type_traits		type_traits;
493 
494       typedef std::bidirectional_iterator_tag 		iterator_category;
495       typedef typename allocator_type::difference_type	difference_type;
496       typedef typename type_traits::value_type		value_type;
497       typedef typename type_traits::pointer 		pointer;
498       typedef typename type_traits::reference 		reference;
499       typedef typename type_traits::const_pointer 	const_pointer;
500       typedef typename type_traits::const_reference 	const_reference;
501 
502       typedef allocator_type				_Alloc;
503       typedef typename _Alloc::template rebind<Node>	__rebind_n;
504       typedef typename __rebind_n::other::pointer	node_pointer;
505       typedef typename _Alloc::template rebind<Leaf>	__rebind_l;
506       typedef typename __rebind_l::other::pointer	leaf_pointer;
507       typedef typename __rebind_l::other::const_pointer	leaf_const_pointer;
508       typedef typename _Alloc::template rebind<Head>	__rebind_h;
509       typedef typename __rebind_h::other::pointer	head_pointer;
510 
511       typedef typename _Alloc::template rebind<Inode> __rebind_in;
512       typedef typename __rebind_in::other::pointer 	inode_pointer;
513       typedef typename Inode::iterator			inode_iterator;
514 
515       node_pointer 					m_p_nd;
516 
517       _CIter(node_pointer p_nd = 0) : m_p_nd(p_nd)
518       { }
519 
520       _CIter(const PB_DS_CONST_ODIR_IT_C_DEC& other)
521       : m_p_nd(other.m_p_nd)
522       { }
523 
524       _CIter&
525       operator=(const _CIter& other)
526       {
527 	m_p_nd = other.m_p_nd;
528 	return *this;
529       }
530 
531       _CIter&
532       operator=(const PB_DS_CONST_ODIR_IT_C_DEC& other)
533       {
534 	m_p_nd = other.m_p_nd;
535 	return *this;
536       }
537 
538       const_pointer
539       operator->() const
540       {
541 	_GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == leaf_node);
542 	return &static_cast<leaf_pointer>(m_p_nd)->value();
543       }
544 
545       const_reference
546       operator*() const
547       {
548 	_GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == leaf_node);
549 	return static_cast<leaf_pointer>(m_p_nd)->value();
550       }
551 
552       bool
553       operator==(const _CIter& other) const
554       { return m_p_nd == other.m_p_nd; }
555 
556       bool
557       operator==(const PB_DS_CONST_ODIR_IT_C_DEC& other) const
558       { return m_p_nd == other.m_p_nd; }
559 
560       bool
561       operator!=(const _CIter& other) const
562       { return m_p_nd != other.m_p_nd; }
563 
564       bool
565       operator!=(const PB_DS_CONST_ODIR_IT_C_DEC& other) const
566       { return m_p_nd != other.m_p_nd; }
567 
568       _CIter&
569       operator++()
570       {
571 	inc(integral_constant<int, Is_Forward_Iterator>());
572 	return *this;
573       }
574 
575       _CIter
576       operator++(int)
577       {
578 	_CIter ret_it(m_p_nd);
579 	operator++();
580 	return ret_it;
581       }
582 
583       _CIter&
584       operator--()
585       {
586 	dec(integral_constant<int, Is_Forward_Iterator>());
587 	return *this;
588       }
589 
590       _CIter
591       operator--(int)
592       {
593 	_CIter ret_it(m_p_nd);
594 	operator--();
595 	return ret_it;
596       }
597 
598     protected:
599       void
600       inc(false_type)
601       { dec(true_type()); }
602 
603       void
604       inc(true_type)
605       {
606 	if (m_p_nd->m_type == head_node)
607 	  {
608 	    m_p_nd = static_cast<head_pointer>(m_p_nd)->m_p_min;
609 	    return;
610 	  }
611 
612 	node_pointer p_y = m_p_nd->m_p_parent;
613 	while (p_y->m_type != head_node && get_larger_sibling(m_p_nd) == 0)
614 	  {
615 	    m_p_nd = p_y;
616 	    p_y = p_y->m_p_parent;
617 	  }
618 
619 	if (p_y->m_type == head_node)
620 	  {
621 	    m_p_nd = p_y;
622 	    return;
623 	  }
624 	m_p_nd = leftmost_descendant(get_larger_sibling(m_p_nd));
625       }
626 
627       void
628       dec(false_type)
629       { inc(true_type()); }
630 
631       void
632       dec(true_type)
633       {
634 	if (m_p_nd->m_type == head_node)
635 	  {
636 	    m_p_nd = static_cast<head_pointer>(m_p_nd)->m_p_max;
637 	    return;
638 	  }
639 
640 	node_pointer p_y = m_p_nd->m_p_parent;
641 	while (p_y->m_type != head_node && get_smaller_sibling(m_p_nd) == 0)
642 	  {
643 	    m_p_nd = p_y;
644 	    p_y = p_y->m_p_parent;
645 	  }
646 
647 	if (p_y->m_type == head_node)
648 	  {
649 	    m_p_nd = p_y;
650 	    return;
651 	  }
652 	m_p_nd = rightmost_descendant(get_smaller_sibling(m_p_nd));
653       }
654 
655       static node_pointer
656       get_larger_sibling(node_pointer p_nd)
657       {
658 	inode_pointer p_parent = static_cast<inode_pointer>(p_nd->m_p_parent);
659 
660 	inode_iterator it = p_parent->begin();
661 	while (*it != p_nd)
662 	  ++it;
663 
664 	inode_iterator next_it = it;
665 	++next_it;
666 	return (next_it == p_parent->end())? 0 : *next_it;
667       }
668 
669       static node_pointer
670       get_smaller_sibling(node_pointer p_nd)
671       {
672 	inode_pointer p_parent = static_cast<inode_pointer>(p_nd->m_p_parent);
673 
674 	inode_iterator it = p_parent->begin();
675 	if (*it == p_nd)
676 	  return 0;
677 
678 	inode_iterator prev_it;
679 	do
680 	  {
681 	    prev_it = it;
682 	    ++it;
683 	    if (*it == p_nd)
684 	      return *prev_it;
685 	  }
686 	while (true);
687 
688 	_GLIBCXX_DEBUG_ASSERT(false);
689 	return 0;
690       }
691 
692       static leaf_pointer
693       leftmost_descendant(node_pointer p_nd)
694       {
695 	if (p_nd->m_type == leaf_node)
696 	  return static_cast<leaf_pointer>(p_nd);
697 	return static_cast<inode_pointer>(p_nd)->leftmost_descendant();
698       }
699 
700       static leaf_pointer
701       rightmost_descendant(node_pointer p_nd)
702       {
703 	if (p_nd->m_type == leaf_node)
704 	  return static_cast<leaf_pointer>(p_nd);
705 	return static_cast<inode_pointer>(p_nd)->rightmost_descendant();
706       }
707     };
708 
709 
710     /// Iterator.
711     template<typename Node, typename Leaf, typename Head, typename Inode,
712 	     bool Is_Forward_Iterator>
713     class _Iter
714     : public _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
715     {
716     public:
717       typedef _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
718       							base_type;
719       typedef typename base_type::allocator_type	allocator_type;
720       typedef typename base_type::type_traits		type_traits;
721       typedef typename type_traits::value_type		value_type;
722       typedef typename type_traits::pointer 		pointer;
723       typedef typename type_traits::reference 		reference;
724 
725       typedef typename base_type::node_pointer		node_pointer;
726       typedef typename base_type::leaf_pointer		leaf_pointer;
727       typedef typename base_type::leaf_const_pointer	leaf_const_pointer;
728       typedef typename base_type::head_pointer		head_pointer;
729       typedef typename base_type::inode_pointer 	inode_pointer;
730 
731       _Iter(node_pointer p_nd = 0)
732       : base_type(p_nd) { }
733 
734       _Iter(const PB_DS_ODIR_IT_C_DEC& other)
735       : base_type(other.m_p_nd) { }
736 
737       _Iter&
738       operator=(const _Iter& other)
739       {
740 	base_type::m_p_nd = other.m_p_nd;
741 	return *this;
742       }
743 
744       _Iter&
745       operator=(const PB_DS_ODIR_IT_C_DEC& other)
746       {
747 	base_type::m_p_nd = other.m_p_nd;
748 	return *this;
749       }
750 
751       pointer
752       operator->() const
753       {
754 	_GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == leaf_node);
755 	return &static_cast<leaf_pointer>(base_type::m_p_nd)->value();
756       }
757 
758       reference
759       operator*() const
760       {
761 	_GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == leaf_node);
762 	return static_cast<leaf_pointer>(base_type::m_p_nd)->value();
763       }
764 
765       _Iter&
766       operator++()
767       {
768 	base_type::operator++();
769 	return *this;
770       }
771 
772       _Iter
773       operator++(int)
774       {
775 	_Iter ret(base_type::m_p_nd);
776 	operator++();
777 	return ret;
778       }
779 
780       _Iter&
781       operator--()
782       {
783 	base_type::operator--();
784 	return *this;
785       }
786 
787       _Iter
788       operator--(int)
789       {
790 	_Iter ret(base_type::m_p_nd);
791 	operator--();
792 	return ret;
793       }
794     };
795 
796 #undef PB_DS_CONST_ODIR_IT_C_DEC
797 #undef PB_DS_ODIR_IT_C_DEC
798 
799 
800 #define PB_DS_PAT_TRIE_NODE_CONST_ITERATOR_C_DEC \
801     _Node_citer<Node, Leaf, Head, Inode, _CIterator, Iterator, _ATraits, _Alloc>
802 
803 #define PB_DS_PAT_TRIE_NODE_ITERATOR_C_DEC \
804     _Node_iter<Node, Leaf, Head, Inode, _CIterator, Iterator, _ATraits, _Alloc>
805 
806     /// Node const iterator.
807     template<typename Node,
808 	     typename Leaf,
809 	     typename Head,
810 	     typename Inode,
811 	     typename _CIterator,
812 	     typename Iterator,
813 	     typename _Alloc>
814     class _Node_citer
815     {
816     protected:
817       typedef typename _Alloc::template rebind<Node>	__rebind_n;
818       typedef typename __rebind_n::other::pointer	node_pointer;
819 
820       typedef typename _Alloc::template rebind<Leaf>	__rebind_l;
821       typedef typename __rebind_l::other::pointer	leaf_pointer;
822       typedef typename __rebind_l::other::const_pointer	leaf_const_pointer;
823 
824       typedef typename _Alloc::template rebind<Inode> 	__rebind_in;
825       typedef typename __rebind_in::other::pointer 	inode_pointer;
826       typedef typename __rebind_in::other::const_pointer inode_const_pointer;
827 
828       typedef typename Node::a_const_pointer		a_const_pointer;
829       typedef typename Node::a_const_iterator		a_const_iterator;
830 
831     private:
832       a_const_iterator
833       pref_begin() const
834       {
835 	if (m_p_nd->m_type == leaf_node)
836 	  {
837 	    leaf_const_pointer lcp = static_cast<leaf_const_pointer>(m_p_nd);
838 	    return m_p_traits->begin(m_p_traits->extract_key(lcp->value()));
839 	  }
840 	_GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
841 	return static_cast<inode_const_pointer>(m_p_nd)->pref_b_it();
842       }
843 
844       a_const_iterator
845       pref_end() const
846       {
847 	if (m_p_nd->m_type == leaf_node)
848 	  {
849 	    leaf_const_pointer lcp = static_cast<leaf_const_pointer>(m_p_nd);
850 	    return m_p_traits->end(m_p_traits->extract_key(lcp->value()));
851 	  }
852 	_GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
853 	return static_cast<inode_const_pointer>(m_p_nd)->pref_e_it();
854       }
855 
856     public:
857       typedef trivial_iterator_tag 			iterator_category;
858       typedef trivial_iterator_difference_type 		difference_type;
859       typedef typename _Alloc::size_type 		size_type;
860 
861       typedef _CIterator 		       		value_type;
862       typedef value_type 				reference;
863       typedef value_type 				const_reference;
864 
865       /// Metadata type.
866       typedef typename Node::metadata_type 		metadata_type;
867 
868       /// Const metadata reference type.
869       typedef typename _Alloc::template rebind<metadata_type> __rebind_m;
870       typedef typename __rebind_m::other 		__rebind_ma;
871       typedef typename __rebind_ma::const_reference    metadata_const_reference;
872 
873       inline
874       _Node_citer(node_pointer p_nd = 0, a_const_pointer p_traits = 0)
875       : m_p_nd(const_cast<node_pointer>(p_nd)), m_p_traits(p_traits)
876       { }
877 
878       /// Subtree valid prefix.
879       std::pair<a_const_iterator, a_const_iterator>
880       valid_prefix() const
881       { return std::make_pair(pref_begin(), pref_end()); }
882 
883       /// Const access; returns the __const iterator* associated with
884       /// the current leaf.
885       const_reference
886       operator*() const
887       {
888 	_GLIBCXX_DEBUG_ASSERT(num_children() == 0);
889 	return _CIterator(m_p_nd);
890       }
891 
892       /// Metadata access.
893       metadata_const_reference
894       get_metadata() const
895       { return m_p_nd->get_metadata(); }
896 
897       /// Returns the number of children in the corresponding node.
898       size_type
899       num_children() const
900       {
901 	if (m_p_nd->m_type == leaf_node)
902 	  return 0;
903 	_GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
904 	inode_pointer inp = static_cast<inode_pointer>(m_p_nd);
905 	return std::distance(inp->begin(), inp->end());
906       }
907 
908       /// Returns a __const node __iterator to the corresponding node's
909       /// i-th child.
910       _Node_citer
911       get_child(size_type i) const
912       {
913 	_GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
914 	inode_pointer inp = static_cast<inode_pointer>(m_p_nd);
915 	typename Inode::iterator it = inp->begin();
916 	std::advance(it, i);
917 	return _Node_citer(*it, m_p_traits);
918       }
919 
920       /// Compares content to a different iterator object.
921       bool
922       operator==(const _Node_citer& other) const
923       { return m_p_nd == other.m_p_nd; }
924 
925       /// Compares content (negatively) to a different iterator object.
926       bool
927       operator!=(const _Node_citer& other) const
928       { return m_p_nd != other.m_p_nd; }
929 
930       node_pointer 			m_p_nd;
931       a_const_pointer 			m_p_traits;
932     };
933 
934 
935     /// Node iterator.
936     template<typename Node,
937 	     typename Leaf,
938 	     typename Head,
939 	     typename Inode,
940 	     typename _CIterator,
941 	     typename Iterator,
942 	     typename _Alloc>
943     class _Node_iter
944     : public _Node_citer<Node, Leaf, Head, Inode, _CIterator, Iterator, _Alloc>
945     {
946     private:
947       typedef _Node_citer<Node, Leaf, Head, Inode,
948 			  _CIterator, Iterator, _Alloc>	base_type;
949       typedef typename _Alloc::template rebind<Node>	__rebind_n;
950       typedef typename __rebind_n::other::pointer	node_pointer;
951       typedef typename base_type::inode_pointer 	inode_pointer;
952       typedef typename base_type::a_const_pointer 	a_const_pointer;
953       typedef Iterator 					iterator;
954 
955     public:
956       typedef typename base_type::size_type 		size_type;
957 
958       typedef Iterator 					value_type;
959       typedef value_type 				reference;
960       typedef value_type 				const_reference;
961 
962       _Node_iter(node_pointer p_nd = 0, a_const_pointer p_traits = 0)
963       : base_type(p_nd, p_traits)
964       { }
965 
966       /// Access; returns the iterator*  associated with the current leaf.
967       reference
968       operator*() const
969       {
970 	_GLIBCXX_DEBUG_ASSERT(base_type::num_children() == 0);
971 	return iterator(base_type::m_p_nd);
972       }
973 
974       /// Returns a node __iterator to the corresponding node's i-th child.
975       _Node_iter
976       get_child(size_type i) const
977       {
978 	_GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == i_node);
979 
980 	typename Inode::iterator it =
981 	  static_cast<inode_pointer>(base_type::m_p_nd)->begin();
982 
983 	std::advance(it, i);
984 	return _Node_iter(*it, base_type::m_p_traits);
985       }
986     };
987     };
988 
989 
990 #define PB_DS_CLASS_T_DEC \
991     template<typename _ATraits, typename Metadata>
992 
993 #define PB_DS_CLASS_C_DEC \
994     pat_trie_base::_Inode<_ATraits, Metadata>
995 
996     PB_DS_CLASS_T_DEC
997     typename PB_DS_CLASS_C_DEC::__rebind_l
998     PB_DS_CLASS_C_DEC::s_leaf_alloc;
999 
1000     PB_DS_CLASS_T_DEC
1001     typename PB_DS_CLASS_C_DEC::__rebind_in
1002     PB_DS_CLASS_C_DEC::s_inode_alloc;
1003 
1004     PB_DS_CLASS_T_DEC
1005     inline typename PB_DS_CLASS_C_DEC::size_type
1006     PB_DS_CLASS_C_DEC::
1007     get_pref_pos(a_const_iterator b_it, a_const_iterator e_it,
1008 		 a_const_pointer p_traits) const
1009     {
1010       if (static_cast<std::size_t>(std::distance(b_it, e_it)) <= m_e_ind)
1011 	return 0;
1012       std::advance(b_it, m_e_ind);
1013       return 1 + p_traits->e_pos(*b_it);
1014     }
1015 
1016     PB_DS_CLASS_T_DEC
1017     PB_DS_CLASS_C_DEC::
1018     _Inode(size_type len, const a_const_iterator it)
1019     : base_type(i_node), m_e_ind(len), m_pref_b_it(it), m_pref_e_it(it)
1020     {
1021       std::advance(m_pref_e_it, m_e_ind);
1022       std::fill(m_a_p_children, m_a_p_children + arr_size,
1023 		static_cast<node_pointer>(0));
1024     }
1025 
1026     PB_DS_CLASS_T_DEC
1027     void
1028     PB_DS_CLASS_C_DEC::
1029     update_prefixes(a_const_pointer p_traits)
1030     {
1031       node_pointer p_first = *begin();
1032       if (p_first->m_type == leaf_node)
1033 	{
1034 	  leaf_const_pointer p = static_cast<leaf_const_pointer>(p_first);
1035 	  m_pref_b_it = p_traits->begin(access_traits::extract_key(p->value()));
1036 	}
1037       else
1038 	{
1039 	  inode_pointer p = static_cast<inode_pointer>(p_first);
1040 	  _GLIBCXX_DEBUG_ASSERT(p_first->m_type == i_node);
1041 	  m_pref_b_it = p->pref_b_it();
1042 	}
1043       m_pref_e_it = m_pref_b_it;
1044       std::advance(m_pref_e_it, m_e_ind);
1045     }
1046 
1047     PB_DS_CLASS_T_DEC
1048     typename PB_DS_CLASS_C_DEC::const_iterator
1049     PB_DS_CLASS_C_DEC::
1050     begin() const
1051     {
1052       typedef node_pointer_pointer pointer_type;
1053       pointer_type p = const_cast<pointer_type>(m_a_p_children);
1054       return const_iterator(p + get_begin_pos(), p + arr_size);
1055     }
1056 
1057     PB_DS_CLASS_T_DEC
1058     typename PB_DS_CLASS_C_DEC::iterator
1059     PB_DS_CLASS_C_DEC::
1060     begin()
1061     {
1062       return iterator(m_a_p_children + get_begin_pos(),
1063 		      m_a_p_children + arr_size);
1064     }
1065 
1066     PB_DS_CLASS_T_DEC
1067     typename PB_DS_CLASS_C_DEC::const_iterator
1068     PB_DS_CLASS_C_DEC::
1069     end() const
1070     {
1071       typedef node_pointer_pointer pointer_type;
1072       pointer_type p = const_cast<pointer_type>(m_a_p_children) + arr_size;
1073       return const_iterator(p, p);
1074     }
1075 
1076     PB_DS_CLASS_T_DEC
1077     typename PB_DS_CLASS_C_DEC::iterator
1078     PB_DS_CLASS_C_DEC::
1079     end()
1080     { return iterator(m_a_p_children + arr_size, m_a_p_children + arr_size); }
1081 
1082     PB_DS_CLASS_T_DEC
1083     inline typename PB_DS_CLASS_C_DEC::node_pointer
1084     PB_DS_CLASS_C_DEC::
1085     get_child_node(a_const_iterator b_it, a_const_iterator e_it,
1086 		   a_const_pointer p_traits)
1087     {
1088       const size_type i = get_pref_pos(b_it, e_it, p_traits);
1089       _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1090       return m_a_p_children[i];
1091     }
1092 
1093     PB_DS_CLASS_T_DEC
1094     inline typename PB_DS_CLASS_C_DEC::iterator
1095     PB_DS_CLASS_C_DEC::
1096     get_child_it(a_const_iterator b_it, a_const_iterator e_it,
1097 		 a_const_pointer p_traits)
1098     {
1099       const size_type i = get_pref_pos(b_it, e_it, p_traits);
1100       _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1101       _GLIBCXX_DEBUG_ASSERT(m_a_p_children[i] != 0);
1102       return iterator(m_a_p_children + i, m_a_p_children + i);
1103     }
1104 
1105     PB_DS_CLASS_T_DEC
1106     inline typename PB_DS_CLASS_C_DEC::node_const_pointer
1107     PB_DS_CLASS_C_DEC::
1108     get_child_node(a_const_iterator b_it, a_const_iterator e_it,
1109 		   a_const_pointer p_traits) const
1110     { return const_cast<node_pointer>(get_child_node(b_it, e_it, p_traits)); }
1111 
1112     PB_DS_CLASS_T_DEC
1113     typename PB_DS_CLASS_C_DEC::node_pointer
1114     PB_DS_CLASS_C_DEC::
1115     get_lower_bound_child_node(a_const_iterator b_it, a_const_iterator e_it,
1116 			       size_type checked_ind,
1117 			       a_const_pointer p_traits)
1118     {
1119       if (!should_be_mine(b_it, e_it, checked_ind, p_traits))
1120 	{
1121 	  if (p_traits->cmp_prefixes(b_it, e_it, m_pref_b_it,
1122 				     m_pref_e_it, true))
1123 	    return leftmost_descendant();
1124 	  return rightmost_descendant();
1125 	}
1126 
1127       size_type i = get_pref_pos(b_it, e_it, p_traits);
1128       _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1129 
1130       if (m_a_p_children[i] != 0)
1131 	return m_a_p_children[i];
1132 
1133       while (++i < arr_size)
1134 	if (m_a_p_children[i] != 0)
1135 	  {
1136 	    const node_type& __nt = m_a_p_children[i]->m_type;
1137 	    node_pointer ret = m_a_p_children[i];
1138 
1139 	    if (__nt == leaf_node)
1140 	      return ret;
1141 
1142 	    _GLIBCXX_DEBUG_ASSERT(__nt == i_node);
1143 	    inode_pointer inp = static_cast<inode_pointer>(ret);
1144 	    return inp->leftmost_descendant();
1145 	  }
1146 
1147       return rightmost_descendant();
1148     }
1149 
1150     PB_DS_CLASS_T_DEC
1151     inline typename PB_DS_CLASS_C_DEC::node_pointer
1152     PB_DS_CLASS_C_DEC::
1153     add_child(node_pointer p_nd, a_const_iterator b_it, a_const_iterator e_it,
1154 	      a_const_pointer p_traits)
1155     {
1156       const size_type i = get_pref_pos(b_it, e_it, p_traits);
1157       _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1158       if (m_a_p_children[i] == 0)
1159 	{
1160 	  m_a_p_children[i] = p_nd;
1161 	  p_nd->m_p_parent = this;
1162 	  return p_nd;
1163 	}
1164       return m_a_p_children[i];
1165     }
1166 
1167     PB_DS_CLASS_T_DEC
1168     typename PB_DS_CLASS_C_DEC::node_const_pointer
1169     PB_DS_CLASS_C_DEC::
1170     get_join_child(node_const_pointer p_nd,
1171 		   a_const_pointer p_tr) const
1172     {
1173       node_pointer p = const_cast<node_pointer>(p_nd);
1174       return const_cast<inode_pointer>(this)->get_join_child(p, p_tr);
1175     }
1176 
1177     PB_DS_CLASS_T_DEC
1178     typename PB_DS_CLASS_C_DEC::node_pointer
1179     PB_DS_CLASS_C_DEC::
1180     get_join_child(node_pointer p_nd, a_const_pointer p_traits)
1181     {
1182       size_type i;
1183       a_const_iterator b_it;
1184       a_const_iterator e_it;
1185       if (p_nd->m_type == leaf_node)
1186 	{
1187 	  leaf_const_pointer p = static_cast<leaf_const_pointer>(p_nd);
1188 
1189 	  typedef typename type_traits::key_const_reference kcr;
1190 	  kcr r_key = access_traits::extract_key(p->value());
1191 	  b_it = p_traits->begin(r_key);
1192 	  e_it = p_traits->end(r_key);
1193 	}
1194       else
1195 	{
1196 	  b_it = static_cast<inode_pointer>(p_nd)->pref_b_it();
1197 	  e_it = static_cast<inode_pointer>(p_nd)->pref_e_it();
1198 	}
1199       i = get_pref_pos(b_it, e_it, p_traits);
1200       _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1201       return m_a_p_children[i];
1202     }
1203 
1204     PB_DS_CLASS_T_DEC
1205     void
1206     PB_DS_CLASS_C_DEC::
1207     remove_child(node_pointer p_nd)
1208     {
1209       size_type i = 0;
1210       for (; i < arr_size; ++i)
1211 	if (m_a_p_children[i] == p_nd)
1212 	  {
1213 	    m_a_p_children[i] = 0;
1214 	    return;
1215 	  }
1216       _GLIBCXX_DEBUG_ASSERT(i != arr_size);
1217     }
1218 
1219     PB_DS_CLASS_T_DEC
1220     void
1221     PB_DS_CLASS_C_DEC::
1222     remove_child(iterator it)
1223     { *it.m_p_p_cur = 0; }
1224 
1225     PB_DS_CLASS_T_DEC
1226     void
1227     PB_DS_CLASS_C_DEC::
1228     replace_child(node_pointer p_nd, a_const_iterator b_it,
1229 		  a_const_iterator e_it,
1230 		  a_const_pointer p_traits)
1231     {
1232       const size_type i = get_pref_pos(b_it, e_it, p_traits);
1233       _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1234       m_a_p_children[i] = p_nd;
1235       p_nd->m_p_parent = this;
1236     }
1237 
1238     PB_DS_CLASS_T_DEC
1239     inline typename PB_DS_CLASS_C_DEC::a_const_iterator
1240     PB_DS_CLASS_C_DEC::
1241     pref_b_it() const
1242     { return m_pref_b_it; }
1243 
1244     PB_DS_CLASS_T_DEC
1245     inline typename PB_DS_CLASS_C_DEC::a_const_iterator
1246     PB_DS_CLASS_C_DEC::
1247     pref_e_it() const
1248     { return m_pref_e_it; }
1249 
1250     PB_DS_CLASS_T_DEC
1251     bool
1252     PB_DS_CLASS_C_DEC::
1253     should_be_mine(a_const_iterator b_it, a_const_iterator e_it,
1254 		   size_type checked_ind,
1255 		   a_const_pointer p_traits) const
1256     {
1257       if (m_e_ind == 0)
1258 	return true;
1259 
1260       const size_type num_es = std::distance(b_it, e_it);
1261       if (num_es < m_e_ind)
1262 	return false;
1263 
1264       a_const_iterator key_b_it = b_it;
1265       std::advance(key_b_it, checked_ind);
1266       a_const_iterator key_e_it = b_it;
1267       std::advance(key_e_it, m_e_ind);
1268 
1269       a_const_iterator value_b_it = m_pref_b_it;
1270       std::advance(value_b_it, checked_ind);
1271       a_const_iterator value_e_it = m_pref_b_it;
1272       std::advance(value_e_it, m_e_ind);
1273 
1274       return p_traits->equal_prefixes(key_b_it, key_e_it, value_b_it,
1275 				      value_e_it);
1276     }
1277 
1278     PB_DS_CLASS_T_DEC
1279     typename PB_DS_CLASS_C_DEC::leaf_pointer
1280     PB_DS_CLASS_C_DEC::
1281     leftmost_descendant()
1282     {
1283       node_pointer p_pot = *begin();
1284       if (p_pot->m_type == leaf_node)
1285 	return (static_cast<leaf_pointer>(p_pot));
1286       _GLIBCXX_DEBUG_ASSERT(p_pot->m_type == i_node);
1287       return static_cast<inode_pointer>(p_pot)->leftmost_descendant();
1288     }
1289 
1290     PB_DS_CLASS_T_DEC
1291     typename PB_DS_CLASS_C_DEC::leaf_const_pointer
1292     PB_DS_CLASS_C_DEC::
1293     leftmost_descendant() const
1294     { return const_cast<inode_pointer>(this)->leftmost_descendant(); }
1295 
1296     PB_DS_CLASS_T_DEC
1297     typename PB_DS_CLASS_C_DEC::leaf_pointer
1298     PB_DS_CLASS_C_DEC::
1299     rightmost_descendant()
1300     {
1301       const size_type num_children = std::distance(begin(), end());
1302       _GLIBCXX_DEBUG_ASSERT(num_children >= 2);
1303 
1304       iterator it = begin();
1305       std::advance(it, num_children - 1);
1306       node_pointer p_pot =* it;
1307       if (p_pot->m_type == leaf_node)
1308 	return static_cast<leaf_pointer>(p_pot);
1309       _GLIBCXX_DEBUG_ASSERT(p_pot->m_type == i_node);
1310       return static_cast<inode_pointer>(p_pot)->rightmost_descendant();
1311     }
1312 
1313     PB_DS_CLASS_T_DEC
1314     typename PB_DS_CLASS_C_DEC::leaf_const_pointer
1315     PB_DS_CLASS_C_DEC::
1316     rightmost_descendant() const
1317     { return const_cast<inode_pointer>(this)->rightmost_descendant(); }
1318 
1319     PB_DS_CLASS_T_DEC
1320     typename PB_DS_CLASS_C_DEC::size_type
1321     PB_DS_CLASS_C_DEC::
1322     get_begin_pos() const
1323     {
1324       size_type i = 0;
1325       for (; i < arr_size && m_a_p_children[i] == 0; ++i)
1326 	;
1327       return i;
1328     }
1329 
1330 #ifdef _GLIBCXX_DEBUG
1331     PB_DS_CLASS_T_DEC
1332     typename PB_DS_CLASS_C_DEC::node_debug_info
1333     PB_DS_CLASS_C_DEC::
1334     assert_valid_imp(a_const_pointer p_traits,
1335 		     const char* __file, int __line) const
1336     {
1337       PB_DS_DEBUG_VERIFY(base_type::m_type == i_node);
1338       PB_DS_DEBUG_VERIFY(static_cast<size_type>(std::distance(pref_b_it(), pref_e_it())) == m_e_ind);
1339       PB_DS_DEBUG_VERIFY(std::distance(begin(), end()) >= 2);
1340 
1341       for (typename _Inode::const_iterator it = begin(); it != end(); ++it)
1342 	{
1343 	  node_const_pointer p_nd = *it;
1344 	  PB_DS_DEBUG_VERIFY(p_nd->m_p_parent == this);
1345 	  node_debug_info child_ret = p_nd->assert_valid_imp(p_traits,
1346 							     __file, __line);
1347 
1348 	  PB_DS_DEBUG_VERIFY(static_cast<size_type>(std::distance(child_ret.first, child_ret.second)) >= m_e_ind);
1349 	  PB_DS_DEBUG_VERIFY(should_be_mine(child_ret.first, child_ret.second, 0, p_traits));
1350 	  PB_DS_DEBUG_VERIFY(get_pref_pos(child_ret.first, child_ret.second, p_traits) == static_cast<size_type>(it.m_p_p_cur - m_a_p_children));
1351 	}
1352       return std::make_pair(pref_b_it(), pref_e_it());
1353     }
1354 #endif
1355 
1356 #undef PB_DS_CLASS_T_DEC
1357 #undef PB_DS_CLASS_C_DEC
1358   } // namespace detail
1359 } // namespace __gnu_pbds
1360 
1361 #endif
1362