1 // -*- C++ -*-
2 
3 // Copyright (C) 2005-2022 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 detail::rebind_traits<_Alloc, Metadata>::const_reference
72               const_reference;
73 
74             const_reference
get_metadata__gnu_pbds::detail::pat_trie_base::_Metadata75             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 detail::rebind_traits<_Alloc, _Node_base>::pointer
103             node_pointer;
104 
105           node_pointer                                                          m_p_parent;
106           const node_type                                             m_type;
107 
_Node_base__gnu_pbds::detail::pat_trie_base::_Node_base108           _Node_base(node_type type) : m_type(type)
109           { }
110 
111           typedef typename detail::rebind_traits<_Alloc, _ATraits>::const_pointer
112             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
assert_valid__gnu_pbds::detail::pat_trie_base::_Node_base119           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 
_Head__gnu_pbds::detail::pat_trie_base::_Head141       _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
assert_valid_imp__gnu_pbds::detail::pat_trie_base::_Head148       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:
_Leaf__gnu_pbds::detail::pat_trie_base::_Leaf177       _Leaf(const_reference other)
178       : base_type(leaf_node), m_value(other) { }
179 
180       reference
value__gnu_pbds::detail::pat_trie_base::_Leaf181       value()
182       { return m_value; }
183 
184       const_reference
value__gnu_pbds::detail::pat_trie_base::_Leaf185       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
assert_valid_imp__gnu_pbds::detail::pat_trie_base::_Leaf193       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
~_Leaf__gnu_pbds::detail::pat_trie_base::_Leaf204       ~_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 detail::rebind_traits<_Alloc, base_type>::const_pointer
228           node_const_pointer;
229 
230       typedef _Leaf<_ATraits, Metadata>                     leaf;
231       typedef typename detail::rebind_traits<_Alloc, leaf>  __rebind_l;
232       typedef typename __rebind_l::pointer                  leaf_pointer;
233       typedef typename __rebind_l::const_pointer  leaf_const_pointer;
234 
235       typedef detail::rebind_traits<_Alloc, _Inode>         __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 detail::rebind_traits<_Alloc, node_pointer>   __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 
const_iterator__gnu_pbds::detail::pat_trie_base::_Inode::const_iterator266           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
operator ==__gnu_pbds::detail::pat_trie_base::_Inode::const_iterator272           operator==(const const_iterator& other) const
273           { return m_p_p_cur == other.m_p_p_cur; }
274 
275           bool
operator !=__gnu_pbds::detail::pat_trie_base::_Inode::const_iterator276           operator!=(const const_iterator& other) const
277           { return m_p_p_cur != other.m_p_p_cur; }
278 
279           const_iterator&
operator ++__gnu_pbds::detail::pat_trie_base::_Inode::const_iterator280           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
operator ++__gnu_pbds::detail::pat_trie_base::_Inode::const_iterator289           operator++(int)
290           {
291             const_iterator ret_it(*this);
292             operator++();
293             return ret_it;
294           }
295 
296           const node_pointer_pointer
operator ->__gnu_pbds::detail::pat_trie_base::_Inode::const_iterator297           operator->() const
298           {
299             _GLIBCXX_DEBUG_ONLY(assert_referencible();)
300             return m_p_p_cur;
301           }
302 
303           node_const_pointer
operator *__gnu_pbds::detail::pat_trie_base::_Inode::const_iterator304           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
assert_referencible__gnu_pbds::detail::pat_trie_base::_Inode::const_iterator313           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
iterator__gnu_pbds::detail::pat_trie_base::_Inode::iterator330           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
operator ==__gnu_pbds::detail::pat_trie_base::_Inode::iterator335           operator==(const iterator& other) const
336           { return const_iterator::m_p_p_cur == other.m_p_p_cur; }
337 
338           bool
operator !=__gnu_pbds::detail::pat_trie_base::_Inode::iterator339           operator!=(const iterator& other) const
340           { return const_iterator::m_p_p_cur != other.m_p_p_cur; }
341 
342           iterator&
operator ++__gnu_pbds::detail::pat_trie_base::_Inode::iterator343           operator++()
344           {
345             const_iterator::operator++();
346             return *this;
347           }
348 
349           iterator
operator ++__gnu_pbds::detail::pat_trie_base::_Inode::iterator350           operator++(int)
351           {
352             iterator ret_it(*this);
353             operator++();
354             return ret_it;
355           }
356 
357           node_pointer_pointer
operator ->__gnu_pbds::detail::pat_trie_base::_Inode::iterator358           operator->()
359           {
360             _GLIBCXX_DEBUG_ONLY(const_iterator::assert_referencible();)
361             return const_iterator::m_p_p_cur;
362           }
363 
364           node_pointer
operator *__gnu_pbds::detail::pat_trie_base::_Inode::iterator365           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
get_e_ind__gnu_pbds::detail::pat_trie_base::_Inode453       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 rebind_traits<_Alloc, Node>::pointer node_pointer;
504       typedef typename rebind_traits<_Alloc, Leaf>::pointer leaf_pointer;
505       typedef typename rebind_traits<_Alloc, Leaf>::const_pointer     leaf_const_pointer;
506       typedef typename rebind_traits<_Alloc, Head>::pointer head_pointer;
507 
508       typedef typename rebind_traits<_Alloc, Inode>::pointer          inode_pointer;
509       typedef typename Inode::iterator                      inode_iterator;
510 
511       node_pointer                                          m_p_nd;
512 
_CIter(node_pointer p_nd=0)513       _CIter(node_pointer p_nd = 0) : m_p_nd(p_nd)
514       { }
515 
_CIter(const PB_DS_CONST_ODIR_IT_C_DEC & other)516       _CIter(const PB_DS_CONST_ODIR_IT_C_DEC& other)
517       : m_p_nd(other.m_p_nd)
518       { }
519 
520       _CIter&
operator =(const _CIter & other)521       operator=(const _CIter& other)
522       {
523           m_p_nd = other.m_p_nd;
524           return *this;
525       }
526 
527       _CIter&
operator =(const PB_DS_CONST_ODIR_IT_C_DEC & other)528       operator=(const PB_DS_CONST_ODIR_IT_C_DEC& other)
529       {
530           m_p_nd = other.m_p_nd;
531           return *this;
532       }
533 
534       const_pointer
operator ->() const535       operator->() const
536       {
537           _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == leaf_node);
538           return &static_cast<leaf_pointer>(m_p_nd)->value();
539       }
540 
541       const_reference
operator *() const542       operator*() const
543       {
544           _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == leaf_node);
545           return static_cast<leaf_pointer>(m_p_nd)->value();
546       }
547 
548       bool
operator ==(const _CIter & other) const549       operator==(const _CIter& other) const
550       { return m_p_nd == other.m_p_nd; }
551 
552       bool
operator ==(const PB_DS_CONST_ODIR_IT_C_DEC & other) const553       operator==(const PB_DS_CONST_ODIR_IT_C_DEC& other) const
554       { return m_p_nd == other.m_p_nd; }
555 
556       bool
operator !=(const _CIter & other) const557       operator!=(const _CIter& other) const
558       { return m_p_nd != other.m_p_nd; }
559 
560       bool
operator !=(const PB_DS_CONST_ODIR_IT_C_DEC & other) const561       operator!=(const PB_DS_CONST_ODIR_IT_C_DEC& other) const
562       { return m_p_nd != other.m_p_nd; }
563 
564       _CIter&
operator ++()565       operator++()
566       {
567           inc(integral_constant<int, Is_Forward_Iterator>());
568           return *this;
569       }
570 
571       _CIter
operator ++(int)572       operator++(int)
573       {
574           _CIter ret_it(m_p_nd);
575           operator++();
576           return ret_it;
577       }
578 
579       _CIter&
operator --()580       operator--()
581       {
582           dec(integral_constant<int, Is_Forward_Iterator>());
583           return *this;
584       }
585 
586       _CIter
operator --(int)587       operator--(int)
588       {
589           _CIter ret_it(m_p_nd);
590           operator--();
591           return ret_it;
592       }
593 
594     protected:
595       void
inc(false_type)596       inc(false_type)
597       { dec(true_type()); }
598 
599       void
inc(true_type)600       inc(true_type)
601       {
602           if (m_p_nd->m_type == head_node)
603             {
604               m_p_nd = static_cast<head_pointer>(m_p_nd)->m_p_min;
605               return;
606             }
607 
608           node_pointer p_y = m_p_nd->m_p_parent;
609           while (p_y->m_type != head_node && get_larger_sibling(m_p_nd) == 0)
610             {
611               m_p_nd = p_y;
612               p_y = p_y->m_p_parent;
613             }
614 
615           if (p_y->m_type == head_node)
616             {
617               m_p_nd = p_y;
618               return;
619             }
620           m_p_nd = leftmost_descendant(get_larger_sibling(m_p_nd));
621       }
622 
623       void
dec(false_type)624       dec(false_type)
625       { inc(true_type()); }
626 
627       void
dec(true_type)628       dec(true_type)
629       {
630           if (m_p_nd->m_type == head_node)
631             {
632               m_p_nd = static_cast<head_pointer>(m_p_nd)->m_p_max;
633               return;
634             }
635 
636           node_pointer p_y = m_p_nd->m_p_parent;
637           while (p_y->m_type != head_node && get_smaller_sibling(m_p_nd) == 0)
638             {
639               m_p_nd = p_y;
640               p_y = p_y->m_p_parent;
641             }
642 
643           if (p_y->m_type == head_node)
644             {
645               m_p_nd = p_y;
646               return;
647             }
648           m_p_nd = rightmost_descendant(get_smaller_sibling(m_p_nd));
649       }
650 
651       static node_pointer
get_larger_sibling(node_pointer p_nd)652       get_larger_sibling(node_pointer p_nd)
653       {
654           inode_pointer p_parent = static_cast<inode_pointer>(p_nd->m_p_parent);
655 
656           inode_iterator it = p_parent->begin();
657           while (*it != p_nd)
658             ++it;
659 
660           inode_iterator next_it = it;
661           ++next_it;
662           return (next_it == p_parent->end())? 0 : *next_it;
663       }
664 
665       static node_pointer
get_smaller_sibling(node_pointer p_nd)666       get_smaller_sibling(node_pointer p_nd)
667       {
668           inode_pointer p_parent = static_cast<inode_pointer>(p_nd->m_p_parent);
669 
670           inode_iterator it = p_parent->begin();
671           if (*it == p_nd)
672             return 0;
673 
674           inode_iterator prev_it;
675           do
676             {
677               prev_it = it;
678               ++it;
679               if (*it == p_nd)
680                 return *prev_it;
681             }
682           while (true);
683 
684           _GLIBCXX_DEBUG_ASSERT(false);
685           return 0;
686       }
687 
688       static leaf_pointer
leftmost_descendant(node_pointer p_nd)689       leftmost_descendant(node_pointer p_nd)
690       {
691           if (p_nd->m_type == leaf_node)
692             return static_cast<leaf_pointer>(p_nd);
693           return static_cast<inode_pointer>(p_nd)->leftmost_descendant();
694       }
695 
696       static leaf_pointer
rightmost_descendant(node_pointer p_nd)697       rightmost_descendant(node_pointer p_nd)
698       {
699           if (p_nd->m_type == leaf_node)
700             return static_cast<leaf_pointer>(p_nd);
701           return static_cast<inode_pointer>(p_nd)->rightmost_descendant();
702       }
703     };
704 
705 
706     /// Iterator.
707     template<typename Node, typename Leaf, typename Head, typename Inode,
708                bool Is_Forward_Iterator>
709     class _Iter
710     : public _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
711     {
712     public:
713       typedef _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
714                                                                       base_type;
715       typedef typename base_type::allocator_type  allocator_type;
716       typedef typename base_type::type_traits               type_traits;
717       typedef typename type_traits::value_type              value_type;
718       typedef typename type_traits::pointer                 pointer;
719       typedef typename type_traits::reference               reference;
720 
721       typedef typename base_type::node_pointer              node_pointer;
722       typedef typename base_type::leaf_pointer              leaf_pointer;
723       typedef typename base_type::leaf_const_pointer        leaf_const_pointer;
724       typedef typename base_type::head_pointer              head_pointer;
725       typedef typename base_type::inode_pointer   inode_pointer;
726 
_Iter(node_pointer p_nd=0)727       _Iter(node_pointer p_nd = 0)
728       : base_type(p_nd) { }
729 
_Iter(const PB_DS_ODIR_IT_C_DEC & other)730       _Iter(const PB_DS_ODIR_IT_C_DEC& other)
731       : base_type(other.m_p_nd) { }
732 
733       _Iter&
operator =(const _Iter & other)734       operator=(const _Iter& other)
735       {
736           base_type::m_p_nd = other.m_p_nd;
737           return *this;
738       }
739 
740       _Iter&
operator =(const PB_DS_ODIR_IT_C_DEC & other)741       operator=(const PB_DS_ODIR_IT_C_DEC& other)
742       {
743           base_type::m_p_nd = other.m_p_nd;
744           return *this;
745       }
746 
747       pointer
operator ->() const748       operator->() const
749       {
750           _GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == leaf_node);
751           return &static_cast<leaf_pointer>(base_type::m_p_nd)->value();
752       }
753 
754       reference
operator *() const755       operator*() const
756       {
757           _GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == leaf_node);
758           return static_cast<leaf_pointer>(base_type::m_p_nd)->value();
759       }
760 
761       _Iter&
operator ++()762       operator++()
763       {
764           base_type::operator++();
765           return *this;
766       }
767 
768       _Iter
operator ++(int)769       operator++(int)
770       {
771           _Iter ret(base_type::m_p_nd);
772           operator++();
773           return ret;
774       }
775 
776       _Iter&
operator --()777       operator--()
778       {
779           base_type::operator--();
780           return *this;
781       }
782 
783       _Iter
operator --(int)784       operator--(int)
785       {
786           _Iter ret(base_type::m_p_nd);
787           operator--();
788           return ret;
789       }
790     };
791 
792 #undef PB_DS_CONST_ODIR_IT_C_DEC
793 #undef PB_DS_ODIR_IT_C_DEC
794 
795 
796 #define PB_DS_PAT_TRIE_NODE_CONST_ITERATOR_C_DEC \
797     _Node_citer<Node, Leaf, Head, Inode, _CIterator, Iterator, _ATraits, _Alloc>
798 
799 #define PB_DS_PAT_TRIE_NODE_ITERATOR_C_DEC \
800     _Node_iter<Node, Leaf, Head, Inode, _CIterator, Iterator, _ATraits, _Alloc>
801 
802     /// Node const iterator.
803     template<typename Node,
804                typename Leaf,
805                typename Head,
806                typename Inode,
807                typename _CIterator,
808                typename Iterator,
809                typename _Alloc>
810     class _Node_citer
811     {
812     protected:
813       typedef typename rebind_traits<_Alloc, Node>::pointer node_pointer;
814 
815       typedef typename rebind_traits<_Alloc, Leaf>::pointer leaf_pointer;
816       typedef typename rebind_traits<_Alloc, Leaf>::const_pointer     leaf_const_pointer;
817 
818       typedef typename rebind_traits<_Alloc, Inode>::pointer          inode_pointer;
819       typedef typename rebind_traits<_Alloc, Inode>::const_pointer inode_const_pointer;
820 
821       typedef typename Node::a_const_pointer                a_const_pointer;
822       typedef typename Node::a_const_iterator               a_const_iterator;
823 
824     private:
825       a_const_iterator
pref_begin() const826       pref_begin() const
827       {
828           if (m_p_nd->m_type == leaf_node)
829             {
830               leaf_const_pointer lcp = static_cast<leaf_const_pointer>(m_p_nd);
831               return m_p_traits->begin(m_p_traits->extract_key(lcp->value()));
832             }
833           _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
834           return static_cast<inode_const_pointer>(m_p_nd)->pref_b_it();
835       }
836 
837       a_const_iterator
pref_end() const838       pref_end() const
839       {
840           if (m_p_nd->m_type == leaf_node)
841             {
842               leaf_const_pointer lcp = static_cast<leaf_const_pointer>(m_p_nd);
843               return m_p_traits->end(m_p_traits->extract_key(lcp->value()));
844             }
845           _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
846           return static_cast<inode_const_pointer>(m_p_nd)->pref_e_it();
847       }
848 
849     public:
850       typedef trivial_iterator_tag                          iterator_category;
851       typedef trivial_iterator_difference_type              difference_type;
852       typedef typename _Alloc::size_type                    size_type;
853 
854       typedef _CIterator                                    value_type;
855       typedef value_type                                    reference;
856       typedef value_type                                    const_reference;
857 
858       /// Metadata type.
859       typedef typename Node::metadata_type                  metadata_type;
860 
861       /// Const metadata reference type.
862       typedef typename rebind_traits<_Alloc, metadata_type>::const_reference    metadata_const_reference;
863 
864       inline
_Node_citer(node_pointer p_nd=0,a_const_pointer p_traits=0)865       _Node_citer(node_pointer p_nd = 0, a_const_pointer p_traits = 0)
866       : m_p_nd(const_cast<node_pointer>(p_nd)), m_p_traits(p_traits)
867       { }
868 
869       /// Subtree valid prefix.
870       std::pair<a_const_iterator, a_const_iterator>
valid_prefix() const871       valid_prefix() const
872       { return std::make_pair(pref_begin(), pref_end()); }
873 
874       /// Const access; returns the __const iterator* associated with
875       /// the current leaf.
876       const_reference
operator *() const877       operator*() const
878       {
879           _GLIBCXX_DEBUG_ASSERT(num_children() == 0);
880           return _CIterator(m_p_nd);
881       }
882 
883       /// Metadata access.
884       metadata_const_reference
get_metadata() const885       get_metadata() const
886       { return m_p_nd->get_metadata(); }
887 
888       /// Returns the number of children in the corresponding node.
889       size_type
num_children() const890       num_children() const
891       {
892           if (m_p_nd->m_type == leaf_node)
893             return 0;
894           _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
895           inode_pointer inp = static_cast<inode_pointer>(m_p_nd);
896           return std::distance(inp->begin(), inp->end());
897       }
898 
899       /// Returns a __const node __iterator to the corresponding node's
900       /// i-th child.
901       _Node_citer
get_child(size_type i) const902       get_child(size_type i) const
903       {
904           _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
905           inode_pointer inp = static_cast<inode_pointer>(m_p_nd);
906           typename Inode::iterator it = inp->begin();
907           std::advance(it, i);
908           return _Node_citer(*it, m_p_traits);
909       }
910 
911       /// Compares content to a different iterator object.
912       bool
operator ==(const _Node_citer & other) const913       operator==(const _Node_citer& other) const
914       { return m_p_nd == other.m_p_nd; }
915 
916       /// Compares content (negatively) to a different iterator object.
917       bool
operator !=(const _Node_citer & other) const918       operator!=(const _Node_citer& other) const
919       { return m_p_nd != other.m_p_nd; }
920 
921       node_pointer                      m_p_nd;
922       a_const_pointer                             m_p_traits;
923     };
924 
925 
926     /// Node iterator.
927     template<typename Node,
928                typename Leaf,
929                typename Head,
930                typename Inode,
931                typename _CIterator,
932                typename Iterator,
933                typename _Alloc>
934     class _Node_iter
935     : public _Node_citer<Node, Leaf, Head, Inode, _CIterator, Iterator, _Alloc>
936     {
937     private:
938       typedef _Node_citer<Node, Leaf, Head, Inode,
939                                 _CIterator, Iterator, _Alloc>         base_type;
940       typedef typename rebind_traits<_Alloc, Node>::pointer node_pointer;
941       typedef typename base_type::inode_pointer   inode_pointer;
942       typedef typename base_type::a_const_pointer           a_const_pointer;
943       typedef Iterator                                                iterator;
944 
945     public:
946       typedef typename base_type::size_type                 size_type;
947 
948       typedef Iterator                                                value_type;
949       typedef value_type                                    reference;
950       typedef value_type                                    const_reference;
951 
_Node_iter(node_pointer p_nd=0,a_const_pointer p_traits=0)952       _Node_iter(node_pointer p_nd = 0, a_const_pointer p_traits = 0)
953       : base_type(p_nd, p_traits)
954       { }
955 
956       /// Access; returns the iterator*  associated with the current leaf.
957       reference
operator *() const958       operator*() const
959       {
960           _GLIBCXX_DEBUG_ASSERT(base_type::num_children() == 0);
961           return iterator(base_type::m_p_nd);
962       }
963 
964       /// Returns a node __iterator to the corresponding node's i-th child.
965       _Node_iter
get_child(size_type i) const966       get_child(size_type i) const
967       {
968           _GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == i_node);
969 
970           typename Inode::iterator it =
971             static_cast<inode_pointer>(base_type::m_p_nd)->begin();
972 
973           std::advance(it, i);
974           return _Node_iter(*it, base_type::m_p_traits);
975       }
976     };
977     };
978 
979 
980 #define PB_DS_CLASS_T_DEC \
981     template<typename _ATraits, typename Metadata>
982 
983 #define PB_DS_CLASS_C_DEC \
984     pat_trie_base::_Inode<_ATraits, Metadata>
985 
986     PB_DS_CLASS_T_DEC
987     typename PB_DS_CLASS_C_DEC::__rebind_l
988     PB_DS_CLASS_C_DEC::s_leaf_alloc;
989 
990     PB_DS_CLASS_T_DEC
991     typename PB_DS_CLASS_C_DEC::__rebind_in
992     PB_DS_CLASS_C_DEC::s_inode_alloc;
993 
994     PB_DS_CLASS_T_DEC
995     inline typename PB_DS_CLASS_C_DEC::size_type
996     PB_DS_CLASS_C_DEC::
get_pref_pos(a_const_iterator b_it,a_const_iterator e_it,a_const_pointer p_traits) const997     get_pref_pos(a_const_iterator b_it, a_const_iterator e_it,
998                      a_const_pointer p_traits) const
999     {
1000       if (static_cast<std::size_t>(std::distance(b_it, e_it)) <= m_e_ind)
1001           return 0;
1002       std::advance(b_it, m_e_ind);
1003       return 1 + p_traits->e_pos(*b_it);
1004     }
1005 
1006     PB_DS_CLASS_T_DEC
1007     PB_DS_CLASS_C_DEC::
_Inode(size_type len,const a_const_iterator it)1008     _Inode(size_type len, const a_const_iterator it)
1009     : base_type(i_node), m_e_ind(len), m_pref_b_it(it), m_pref_e_it(it)
1010     {
1011       std::advance(m_pref_e_it, m_e_ind);
1012       std::fill(m_a_p_children, m_a_p_children + arr_size,
1013                     static_cast<node_pointer>(0));
1014     }
1015 
1016     PB_DS_CLASS_T_DEC
1017     void
1018     PB_DS_CLASS_C_DEC::
update_prefixes(a_const_pointer p_traits)1019     update_prefixes(a_const_pointer p_traits)
1020     {
1021       node_pointer p_first = *begin();
1022       if (p_first->m_type == leaf_node)
1023           {
1024             leaf_const_pointer p = static_cast<leaf_const_pointer>(p_first);
1025             m_pref_b_it = p_traits->begin(access_traits::extract_key(p->value()));
1026           }
1027       else
1028           {
1029             inode_pointer p = static_cast<inode_pointer>(p_first);
1030             _GLIBCXX_DEBUG_ASSERT(p_first->m_type == i_node);
1031             m_pref_b_it = p->pref_b_it();
1032           }
1033       m_pref_e_it = m_pref_b_it;
1034       std::advance(m_pref_e_it, m_e_ind);
1035     }
1036 
1037     PB_DS_CLASS_T_DEC
1038     typename PB_DS_CLASS_C_DEC::const_iterator
1039     PB_DS_CLASS_C_DEC::
begin() const1040     begin() const
1041     {
1042       typedef node_pointer_pointer pointer_type;
1043       pointer_type p = const_cast<pointer_type>(m_a_p_children);
1044       return const_iterator(p + get_begin_pos(), p + arr_size);
1045     }
1046 
1047     PB_DS_CLASS_T_DEC
1048     typename PB_DS_CLASS_C_DEC::iterator
1049     PB_DS_CLASS_C_DEC::
begin()1050     begin()
1051     {
1052       return iterator(m_a_p_children + get_begin_pos(),
1053                           m_a_p_children + arr_size);
1054     }
1055 
1056     PB_DS_CLASS_T_DEC
1057     typename PB_DS_CLASS_C_DEC::const_iterator
1058     PB_DS_CLASS_C_DEC::
end() const1059     end() const
1060     {
1061       typedef node_pointer_pointer pointer_type;
1062       pointer_type p = const_cast<pointer_type>(m_a_p_children) + arr_size;
1063       return const_iterator(p, p);
1064     }
1065 
1066     PB_DS_CLASS_T_DEC
1067     typename PB_DS_CLASS_C_DEC::iterator
1068     PB_DS_CLASS_C_DEC::
end()1069     end()
1070     { return iterator(m_a_p_children + arr_size, m_a_p_children + arr_size); }
1071 
1072     PB_DS_CLASS_T_DEC
1073     inline typename PB_DS_CLASS_C_DEC::node_pointer
1074     PB_DS_CLASS_C_DEC::
get_child_node(a_const_iterator b_it,a_const_iterator e_it,a_const_pointer p_traits)1075     get_child_node(a_const_iterator b_it, a_const_iterator e_it,
1076                        a_const_pointer p_traits)
1077     {
1078       const size_type i = get_pref_pos(b_it, e_it, p_traits);
1079       _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1080       return m_a_p_children[i];
1081     }
1082 
1083     PB_DS_CLASS_T_DEC
1084     inline typename PB_DS_CLASS_C_DEC::iterator
1085     PB_DS_CLASS_C_DEC::
get_child_it(a_const_iterator b_it,a_const_iterator e_it,a_const_pointer p_traits)1086     get_child_it(a_const_iterator b_it, a_const_iterator e_it,
1087                      a_const_pointer p_traits)
1088     {
1089       const size_type i = get_pref_pos(b_it, e_it, p_traits);
1090       _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1091       _GLIBCXX_DEBUG_ASSERT(m_a_p_children[i] != 0);
1092       return iterator(m_a_p_children + i, m_a_p_children + i);
1093     }
1094 
1095     PB_DS_CLASS_T_DEC
1096     inline typename PB_DS_CLASS_C_DEC::node_const_pointer
1097     PB_DS_CLASS_C_DEC::
get_child_node(a_const_iterator b_it,a_const_iterator e_it,a_const_pointer p_traits) const1098     get_child_node(a_const_iterator b_it, a_const_iterator e_it,
1099                        a_const_pointer p_traits) const
1100     { return const_cast<node_pointer>(get_child_node(b_it, e_it, p_traits)); }
1101 
1102     PB_DS_CLASS_T_DEC
1103     typename PB_DS_CLASS_C_DEC::node_pointer
1104     PB_DS_CLASS_C_DEC::
get_lower_bound_child_node(a_const_iterator b_it,a_const_iterator e_it,size_type checked_ind,a_const_pointer p_traits)1105     get_lower_bound_child_node(a_const_iterator b_it, a_const_iterator e_it,
1106                                      size_type checked_ind,
1107                                      a_const_pointer p_traits)
1108     {
1109       if (!should_be_mine(b_it, e_it, checked_ind, p_traits))
1110           {
1111             if (p_traits->cmp_prefixes(b_it, e_it, m_pref_b_it,
1112                                              m_pref_e_it, true))
1113               return leftmost_descendant();
1114             return rightmost_descendant();
1115           }
1116 
1117       size_type i = get_pref_pos(b_it, e_it, p_traits);
1118       _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1119 
1120       if (m_a_p_children[i] != 0)
1121           return m_a_p_children[i];
1122 
1123       while (++i < arr_size)
1124           if (m_a_p_children[i] != 0)
1125             {
1126               const node_type& __nt = m_a_p_children[i]->m_type;
1127               node_pointer ret = m_a_p_children[i];
1128 
1129               if (__nt == leaf_node)
1130                 return ret;
1131 
1132               _GLIBCXX_DEBUG_ASSERT(__nt == i_node);
1133               inode_pointer inp = static_cast<inode_pointer>(ret);
1134               return inp->leftmost_descendant();
1135             }
1136 
1137       return rightmost_descendant();
1138     }
1139 
1140     PB_DS_CLASS_T_DEC
1141     inline typename PB_DS_CLASS_C_DEC::node_pointer
1142     PB_DS_CLASS_C_DEC::
add_child(node_pointer p_nd,a_const_iterator b_it,a_const_iterator e_it,a_const_pointer p_traits)1143     add_child(node_pointer p_nd, a_const_iterator b_it, a_const_iterator e_it,
1144                 a_const_pointer p_traits)
1145     {
1146       const size_type i = get_pref_pos(b_it, e_it, p_traits);
1147       _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1148       if (m_a_p_children[i] == 0)
1149           {
1150             m_a_p_children[i] = p_nd;
1151             p_nd->m_p_parent = this;
1152             return p_nd;
1153           }
1154       return m_a_p_children[i];
1155     }
1156 
1157     PB_DS_CLASS_T_DEC
1158     typename PB_DS_CLASS_C_DEC::node_const_pointer
1159     PB_DS_CLASS_C_DEC::
get_join_child(node_const_pointer p_nd,a_const_pointer p_tr) const1160     get_join_child(node_const_pointer p_nd,
1161                        a_const_pointer p_tr) const
1162     {
1163       node_pointer p = const_cast<node_pointer>(p_nd);
1164       return const_cast<inode_pointer>(this)->get_join_child(p, p_tr);
1165     }
1166 
1167     PB_DS_CLASS_T_DEC
1168     typename PB_DS_CLASS_C_DEC::node_pointer
1169     PB_DS_CLASS_C_DEC::
get_join_child(node_pointer p_nd,a_const_pointer p_traits)1170     get_join_child(node_pointer p_nd, a_const_pointer p_traits)
1171     {
1172       size_type i;
1173       a_const_iterator b_it;
1174       a_const_iterator e_it;
1175       if (p_nd->m_type == leaf_node)
1176           {
1177             leaf_const_pointer p = static_cast<leaf_const_pointer>(p_nd);
1178 
1179             typedef typename type_traits::key_const_reference kcr;
1180             kcr r_key = access_traits::extract_key(p->value());
1181             b_it = p_traits->begin(r_key);
1182             e_it = p_traits->end(r_key);
1183           }
1184       else
1185           {
1186             b_it = static_cast<inode_pointer>(p_nd)->pref_b_it();
1187             e_it = static_cast<inode_pointer>(p_nd)->pref_e_it();
1188           }
1189       i = get_pref_pos(b_it, e_it, p_traits);
1190       _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1191       return m_a_p_children[i];
1192     }
1193 
1194     PB_DS_CLASS_T_DEC
1195     void
1196     PB_DS_CLASS_C_DEC::
remove_child(node_pointer p_nd)1197     remove_child(node_pointer p_nd)
1198     {
1199       size_type i = 0;
1200       for (; i < arr_size; ++i)
1201           if (m_a_p_children[i] == p_nd)
1202             {
1203               m_a_p_children[i] = 0;
1204               return;
1205             }
1206       _GLIBCXX_DEBUG_ASSERT(i != arr_size);
1207     }
1208 
1209     PB_DS_CLASS_T_DEC
1210     void
1211     PB_DS_CLASS_C_DEC::
remove_child(iterator it)1212     remove_child(iterator it)
1213     { *it.m_p_p_cur = 0; }
1214 
1215     PB_DS_CLASS_T_DEC
1216     void
1217     PB_DS_CLASS_C_DEC::
replace_child(node_pointer p_nd,a_const_iterator b_it,a_const_iterator e_it,a_const_pointer p_traits)1218     replace_child(node_pointer p_nd, a_const_iterator b_it,
1219                       a_const_iterator e_it,
1220                       a_const_pointer p_traits)
1221     {
1222       const size_type i = get_pref_pos(b_it, e_it, p_traits);
1223       _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1224       m_a_p_children[i] = p_nd;
1225       p_nd->m_p_parent = this;
1226     }
1227 
1228     PB_DS_CLASS_T_DEC
1229     inline typename PB_DS_CLASS_C_DEC::a_const_iterator
1230     PB_DS_CLASS_C_DEC::
pref_b_it() const1231     pref_b_it() const
1232     { return m_pref_b_it; }
1233 
1234     PB_DS_CLASS_T_DEC
1235     inline typename PB_DS_CLASS_C_DEC::a_const_iterator
1236     PB_DS_CLASS_C_DEC::
pref_e_it() const1237     pref_e_it() const
1238     { return m_pref_e_it; }
1239 
1240     PB_DS_CLASS_T_DEC
1241     bool
1242     PB_DS_CLASS_C_DEC::
should_be_mine(a_const_iterator b_it,a_const_iterator e_it,size_type checked_ind,a_const_pointer p_traits) const1243     should_be_mine(a_const_iterator b_it, a_const_iterator e_it,
1244                        size_type checked_ind,
1245                        a_const_pointer p_traits) const
1246     {
1247       if (m_e_ind == 0)
1248           return true;
1249 
1250       const size_type num_es = std::distance(b_it, e_it);
1251       if (num_es < m_e_ind)
1252           return false;
1253 
1254       a_const_iterator key_b_it = b_it;
1255       std::advance(key_b_it, checked_ind);
1256       a_const_iterator key_e_it = b_it;
1257       std::advance(key_e_it, m_e_ind);
1258 
1259       a_const_iterator value_b_it = m_pref_b_it;
1260       std::advance(value_b_it, checked_ind);
1261       a_const_iterator value_e_it = m_pref_b_it;
1262       std::advance(value_e_it, m_e_ind);
1263 
1264       return p_traits->equal_prefixes(key_b_it, key_e_it, value_b_it,
1265                                               value_e_it);
1266     }
1267 
1268     PB_DS_CLASS_T_DEC
1269     typename PB_DS_CLASS_C_DEC::leaf_pointer
1270     PB_DS_CLASS_C_DEC::
leftmost_descendant()1271     leftmost_descendant()
1272     {
1273       node_pointer p_pot = *begin();
1274       if (p_pot->m_type == leaf_node)
1275           return (static_cast<leaf_pointer>(p_pot));
1276       _GLIBCXX_DEBUG_ASSERT(p_pot->m_type == i_node);
1277       return static_cast<inode_pointer>(p_pot)->leftmost_descendant();
1278     }
1279 
1280     PB_DS_CLASS_T_DEC
1281     typename PB_DS_CLASS_C_DEC::leaf_const_pointer
1282     PB_DS_CLASS_C_DEC::
leftmost_descendant() const1283     leftmost_descendant() const
1284     { return const_cast<inode_pointer>(this)->leftmost_descendant(); }
1285 
1286     PB_DS_CLASS_T_DEC
1287     typename PB_DS_CLASS_C_DEC::leaf_pointer
1288     PB_DS_CLASS_C_DEC::
rightmost_descendant()1289     rightmost_descendant()
1290     {
1291       const size_type num_children = std::distance(begin(), end());
1292       _GLIBCXX_DEBUG_ASSERT(num_children >= 2);
1293 
1294       iterator it = begin();
1295       std::advance(it, num_children - 1);
1296       node_pointer p_pot =* it;
1297       if (p_pot->m_type == leaf_node)
1298           return static_cast<leaf_pointer>(p_pot);
1299       _GLIBCXX_DEBUG_ASSERT(p_pot->m_type == i_node);
1300       return static_cast<inode_pointer>(p_pot)->rightmost_descendant();
1301     }
1302 
1303     PB_DS_CLASS_T_DEC
1304     typename PB_DS_CLASS_C_DEC::leaf_const_pointer
1305     PB_DS_CLASS_C_DEC::
rightmost_descendant() const1306     rightmost_descendant() const
1307     { return const_cast<inode_pointer>(this)->rightmost_descendant(); }
1308 
1309     PB_DS_CLASS_T_DEC
1310     typename PB_DS_CLASS_C_DEC::size_type
1311     PB_DS_CLASS_C_DEC::
get_begin_pos() const1312     get_begin_pos() const
1313     {
1314       size_type i = 0;
1315       for (; i < arr_size && m_a_p_children[i] == 0; ++i)
1316           ;
1317       return i;
1318     }
1319 
1320 #ifdef _GLIBCXX_DEBUG
1321     PB_DS_CLASS_T_DEC
1322     typename PB_DS_CLASS_C_DEC::node_debug_info
1323     PB_DS_CLASS_C_DEC::
assert_valid_imp(a_const_pointer p_traits,const char * __file,int __line) const1324     assert_valid_imp(a_const_pointer p_traits,
1325                          const char* __file, int __line) const
1326     {
1327       PB_DS_DEBUG_VERIFY(base_type::m_type == i_node);
1328       PB_DS_DEBUG_VERIFY(static_cast<size_type>(std::distance(pref_b_it(), pref_e_it())) == m_e_ind);
1329       PB_DS_DEBUG_VERIFY(std::distance(begin(), end()) >= 2);
1330 
1331       for (typename _Inode::const_iterator it = begin(); it != end(); ++it)
1332           {
1333             node_const_pointer p_nd = *it;
1334             PB_DS_DEBUG_VERIFY(p_nd->m_p_parent == this);
1335             node_debug_info child_ret = p_nd->assert_valid_imp(p_traits,
1336                                                                            __file, __line);
1337 
1338             PB_DS_DEBUG_VERIFY(static_cast<size_type>(std::distance(child_ret.first, child_ret.second)) >= m_e_ind);
1339             PB_DS_DEBUG_VERIFY(should_be_mine(child_ret.first, child_ret.second, 0, p_traits));
1340             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));
1341           }
1342       return std::make_pair(pref_b_it(), pref_e_it());
1343     }
1344 #endif
1345 
1346 #undef PB_DS_CLASS_T_DEC
1347 #undef PB_DS_CLASS_C_DEC
1348   } // namespace detail
1349 } // namespace __gnu_pbds
1350 
1351 #endif
1352