///////////////////////////////////////////////////////////////////////////
// FILE: _rbtree (std::_OW::RedBlackTree definition)
//
// =========================================================================
//
//                          Open Watcom Project
//
// Copyright (c) 2004-2026 The Open Watcom Contributors. All Rights Reserved.
//
//    This file is automatically generated. Do not edit directly.
//
// =========================================================================
//
// Description: This header is an Open Watcom red black tree container implementation. Although
//              it not part of the 14882 C++ standard library it is written with a similar
//              interface. It is used by the Open Watcom implementation of the C++ standard
//              library (map, set, multimap, multiset)
///////////////////////////////////////////////////////////////////////////
#ifndef __RBTREE_H_INCLUDED
#define __RBTREE_H_INCLUDED

#ifndef _ENABLE_AUTODEPEND
 #pragma read_only_file
#endif

#ifndef __cplusplus
 #error This header file requires C++
#endif

#ifndef _UTILITY_INCLUDED
 #include <utility>
#endif

#ifndef _ITERATOR_INCLUDED
 #include <iterator>
#endif

#ifndef _FUNCTIONAL_INCLUDED
 #include <functional>
#endif

#ifndef _MEMORY_INCLUDED
 #include <memory>
#endif

namespace std {

    namespace _ow {

        /* ==================================================================
         * value wrappers
         * Two classes/functors for set and map that allow single keys and pairs to be used so
         * memory is not wasted. Provides a common interface for getting the key value so the
         * same tree code can be used.
         */

        template< class Key >
        struct TreeKeyWrapper{
            typedef const Key value_type;
            const Key &operator()( const value_type &v ) const
                { return( v ); }
        };

        template< class Key, class Type >
        struct TreePairWrapper{
            typedef pair< const Key, Type > value_type;
            const Key &operator()( const value_type &v ) const
                { return( v.first ); }
        };

        /* ==================================================================
         * Red-Black Tree container interface
         * To do:
         *  * find out what supposed to do with allocator alloc/construct exceptions
         *  * rebind and copy allocator
         *  * finish off all functions so has 14882 style interface
         *  * check const is used where ever it can/needed
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        class RedBlackTree{
        public:
            typedef ValueWrapper::value_type value_type;
            typedef Key                      key_type;
            typedef unsigned int             size_type;

        protected:
            struct Node {
                enum Chroma { red = 0, black = 1 };
                value_type value;
                Node *left;
                Node *right;
            private:
                Node *parent;
#if 0
                // Simple implementation stores color in separate member.
                Chroma colour;
            public:
                void   set_parent( Node *p )  { parent = p;       }
                Node  *get_parent( )          { return( parent ); }
                void   set_red( )             { colour = red;     }
                void   set_black( )           { colour = black;   }
                Chroma get_colour( )          { return( colour ); }
                void   set_colour( Chroma c ) { colour = c;       }
                bool   is_red( )              { return( colour == red   ); }
                bool   is_black( )            { return( colour == black ); }
#else
                // Colour hidden in the least significant bit of the parent pointer.
            public:
                void set_parent( Node *p )
                {
                    // TODO: Add a debugging assertion that the parent really has LSB clear.
                    parent = (Node *)( (long)p | ((long)parent & 1) );
                }

                Node *get_parent( )
                    { return( (Node *)( (long)parent & -2 ) ); }

                void set_red( )
                    { parent = (Node *)( (long)parent & -2 ) ; }

                void set_black( )
                    { parent = (Node *)( (long)parent | 1 ) ; }

                Chroma get_colour( )
                    { return( (Chroma)( (long)parent & 1 ) ); }

                void set_colour( Chroma c )
                {
                    parent = (Node *)( (long)parent & -2 );
                    parent = (Node *)( (long)parent |  c );
                }

                bool is_red( )
                    { return( !( (long)parent & 1 ) ); }

                bool is_black( )
                    { return( (bool)( (long)parent & 1 ) ); }
#endif

                Node( const value_type &v, Node *p = 0, Chroma c = red )
                    : value( v ), left( 0 ), right( 0 )
                {
                    set_parent( p );
                    set_colour( c );
                }
            };  // End of struct Node

            // !!! moved up here until compiler bug fixed !!!
            Allocator::rebind< Node >::other mem;

        public:
            class iterator;

            // Constructors and destructor.
            explicit RedBlackTree( Compare c, Allocator a )
                : mRoot(0), mFirst(0), mLast(0), mSize(0), mError(0), cmp(c), mem(a)
                { }

            template< class InputIterator >
            RedBlackTree(
                InputIterator    f,
                InputIterator    l,
                const Compare   &c,
                const Allocator &a )
                : mRoot(0), mFirst(0), mLast(0), mSize(0), mError(0), cmp(c), mem(a)
            {
                // Presume initial data sorted. The hint is ignored when the tree is empty.
                iterator hint;
                for( ; f != l ; ++f ) {
                    hint = insert( hint, *f ).first;
                }
            }

            RedBlackTree( const RedBlackTree & );
            RedBlackTree& operator=( const RedBlackTree & );
           ~RedBlackTree( );
            Allocator get_allocator( ) const
                { Allocator a( mem ); return( a ); }


            /* ------------------------------------------------------------------
             * iterators
             */
            class iterator_base :
                public std::iterator< std::bidirectional_iterator_tag, value_type > {

                friend class RedBlackTree;
                typedef RedBlackTree<Key, Compare, Allocator, ValueWrapper> rbt_type;

            public:
                bool operator==( iterator_base i )
                    { return( self == i.self ); }

                bool operator!=( iterator_base i )
                    { return( self != i.self ); }

                iterator_base &operator++( )
                {
                    self = rbt->walk_right( self );
                    return *this;
                }

                iterator_base &operator--( )
                {
                    self ? self = rbt->walk_left( self ) : self = rbt->mLast;
                    return *this;
                }

            protected:
                iterator_base( const iterator_base &i ) : self( i.self ), rbt( i.rbt )
                    { }

                iterator_base( ) : self( 0 ), rbt( 0 )
                    { }

                iterator_base( const rbt_type *rb, Node *n ) : self( n ), rbt( rb )
                    { }

                Node *get_node_pointer( )
                    { return( self ); }

                Node *self;
                const rbt_type *rbt;
            };

            class iterator : public iterator_base {
            public:
                iterator( ) : iterator_base( ) { }
                iterator( const iterator_base &i ) : iterator_base( i ) { }
                iterator( const rbt_type *rb, Node *n )
                    : iterator_base( rb, n )
                    { }

                RedBlackTree::value_type &operator*( )
                    { return( self->value ); }

                RedBlackTree::value_type *operator->( )
                    { return &(self->value); }

                iterator &operator++( )
                    { return( (iterator &)iterator_base::operator++( ) ); }

                iterator operator++( int )
                    { iterator i = *this; operator++( ); return i; }

                iterator& operator--( )
                    { return( (iterator &)iterator_base::operator--( ) ); }

                iterator operator--( int )
                    { iterator i = *this; operator--( ); return i; }
            };

            class const_iterator : public iterator_base {
            public:
                const_iterator( const iterator_base &i ) : iterator_base( i ) { }
                const_iterator( ) : iterator_base( ) { }
                const_iterator( const rbt_type *rb, Node *n )
                    : iterator_base( rb, n )
                { }

                const RedBlackTree::value_type &operator*( )
                    { return self->value; }

                const RedBlackTree::value_type *operator->( )
                    { return &(self->value); }

                const_iterator &operator++( )
                    { return( (const_iterator &)iterator_base::operator++( )); }

                const_iterator operator++( int )
                    { const_iterator i = *this; operator++( ); return i; }

                const_iterator& operator--( )
                    { return( (const_iterator &)iterator_base::operator--( )); }

                const_iterator operator--( int )
                    { const_iterator i = *this; operator--( ); return i; }
            };

            friend class iterator_base;
            friend class iterator;
            friend class const_iterator;
            /*
             * end of iterators
             * ------------------------------------------------------------------ */

            iterator end( )
                { return iterator( this, (Node *)0 ); }

            iterator begin( )
                { return iterator( this, mFirst ); }

            const_iterator end( ) const
                { return const_iterator( this, (Node *)0 ); }

            const_iterator begin( ) const
                { return const_iterator( this, mFirst ); }

            // pair< iterator, bool > insert( value_type const & );

            // TODO: Move to out-of-line when compiler supports syntax.
            template< class InputIterator >
            void RedBlackTree< Key, Compare, Allocator, ValueWrapper>::insert(
                InputIterator first_it, InputIterator last_it )
            {
                // presume data sorted; use last insert point as hint
                iterator hint;
                if( first_it != last_it )
                    hint = insert( *first_it ).first;
                for( ++first_it ; first_it != last_it ; ++first_it ) {
                    hint = insert( hint, *first_it ).first;
                }
            }

            void            erase( iterator );
            size_type       erase( const key_type & );
            // void erase( iterator first, iterator last );
            void            clear( );
            iterator        find( const key_type & );
            const_iterator  find( const key_type & ) const;
            bool            empty( ) const { return( mSize == 0 ); }
            size_type       size( ) const  { return( mSize ); }
            size_type       max_size( ) const;
            iterator        upper_bound( const key_type & );
            const_iterator  upper_bound( const key_type &x) const;
            iterator        lower_bound( const key_type & );
            const_iterator  lower_bound( const key_type &x) const;

            std::pair< iterator, iterator >
            equal_range( const key_type & x )
                { return( make_pair( lower_bound(x), upper_bound(x) ) ); }

            std::pair< const_iterator, const_iterator >
            equal_range( const key_type & x ) const
                { return( make_pair( lower_bound(x), upper_bound(x) ) ); }

            bool _Sane( );
            int mError;

        protected:
            void    double_black_transform( Node *parent, bool lefty );
            void    insert_balance_transform( Node *inserted );
            // std::pair< iterator, bool > unbalanced_insert( value_type const & );
            int     black_height( iterator );
            int     height( iterator );
            Node   *walk_right( Node * ) const;
            Node   *walk_left( Node * ) const;
            int     mSize;
            Node   *mRoot;
            Node   *mFirst;
            Node   *mLast;
            Compare cmp;
            ValueWrapper key_getter;

            std::pair< RedBlackTree::iterator, bool >
                unbalanced_insert( const value_type &v );

        public:
            std::pair< RedBlackTree::iterator, bool >
                insert( const value_type &v );

            std::pair< RedBlackTree::iterator, bool >
                insert( iterator hint, const value_type &v );

        }; // End of class RedBlackTree.


        /* ==================================================================
         * Red-Black Tree Functions
         */

        /* ------------------------------------------------------------------
         * Copy Ctor
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::RedBlackTree(
            const RedBlackTree< Key, Compare, Allocator, ValueWrapper > &that )
            : mem(that.mem)
        {
            // Copy comparator?
            // Other bits?
            mSize = that.mSize;
            // Copy nodes.
            // Special case node.
            if( !that.mRoot ) {
                // No root, therefore first and last don't exist either
                mFirst = 0;
                mLast = 0;
                mRoot = 0;
                return;
            }
            mRoot = mem.allocate( 1 );
            try {
                mem.construct( mRoot, Node( that.mRoot->value, 0, that.mRoot->get_colour( ) ) );
            }
            catch( ... ) {
                mem.deallocate( mRoot, 1 );
                mRoot = 0;
                throw;
            }

            Node *n;
            Node *o;

            o = that.mRoot;
            n = mRoot;
            for( ;; ) {
                // Check to see if reached first/last and fix up.
                if( o == that.mFirst ) {
                    mFirst = n;
                }
                if( o == that.mLast ) {
                    mLast = n;
                }
                // Logic for tree traverse and copy.
                if( o->left && !n->left ) {
                    // Copy left node if we can/haven't already.
                    o = o->left;
                    try {
                        n->left = mem.allocate( 1 );
                        try {
                            mem.construct( n->left, Node( o->value, n, o->get_colour( ) ) );
                        }
                        catch( ... ) {
                            mem.deallocate( n->left, 1 );
                            throw;
                        }
                    }
                    catch( ... ) {
                        n->left = 0;
                        clear( );
                        throw;
                    }
                    n = n->left;
                } else if( o->right && !n->right ) {
                    // Or copy right node if we can/haven't already.
                    o = o->right;
                    try {
                        n->right = mem.allocate( 1 );
                        try {
                            mem.construct( n->right, Node( o->value, n, o->get_colour( ) ) );
                        }
                        catch( ... ) {
                            mem.deallocate( n->right, 1 );
                            throw;
                        }
                    }
                    catch( ... ) {
                        n->right = 0;
                        clear( );
                        throw;
                    }
                    n = n->right;
                } else if( o->get_parent( ) ) {
                    // No children nodes left to copy, move back up.
                    o = o->get_parent( );
                    n = n->get_parent( );
                } else {
                    //no children nodes left to copy and we are root therefore
                    //finished
                    return;
                }
            } // End for( ;; ).
        }

        /* ------------------------------------------------------------------
         * operator=
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >&
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::operator=(
            const RedBlackTree< Key, Compare, Allocator, ValueWrapper > &that )
        {
            clear( );
            new ( this ) RedBlackTree( that );  //call copy ctor to do the copy
            return( *this );
        }

        /* ------------------------------------------------------------------
         * Dtor
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::~RedBlackTree( )
        {
            clear( );
        }

        /* ------------------------------------------------------------------
         * clear( )
         *
         * Erase all elements. Should be quicker than iterating through each one as we don't
         * have to walk and rebalance
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        void RedBlackTree< Key, Compare, Allocator, ValueWrapper >::clear( )
        {
            // Note copy constructor clean up assumes clear( ) need any members set correctly
            // except mRoot.
            Node *n = mRoot;
            while( n ) {
                if( n->left ) {
                    n = n->left;
                } else if( n->right ) {
                    n = n->right;
                } else {
                    // Delete it when all children gone.
                    if( !n->get_parent( ) ) {
                        // If no parent then root, therefore finished.
                        mem.destroy( n );
                        mem.deallocate( n, 1 );
                        mSize  = 0;
                        mRoot  = 0;
                        mFirst = 0;
                        mLast  = 0;
                        return;
                    }
                    if( n == n->get_parent( )->left ) {
                        n->get_parent( )->left = 0;
                    } else {
                        n->get_parent( )->right = 0;
                    }
                    Node *delete_me = n;
                    n = n->get_parent( );
                    mem.destroy( delete_me );
                    mem.deallocate( delete_me, 1 );
                }
            }
        }

        /* ------------------------------------------------------------------
         * find( )
         * Climb the tree until we get to the key :)
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::iterator
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::find(const Key &find_me)
        {
            Node *n = mRoot;
            Node *notLT = 0;

            while( n ) {
                if( cmp( find_me, key_getter( n->value ) ) ) {
                    n = n->left;
                } else {
                    notLT = n;
                    n = n->right;
                }
            }
            // The last node the key is not less than (if any) may be equal, in which case it
            // was found.
            if( notLT && !(cmp( key_getter( notLT->value ), find_me ) ) ) { // !(a<b) & !(b<a) then a==b
                return iterator( this, notLT );
            } else {
                return end( );
            }
        }

        /* ------------------------------------------------------------------
         * find( ) const
         * Climb the tree until we get to the key :)
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::const_iterator
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::find(const Key &find_me) const
        {
            Node *n = mRoot;
            Node *notLT = 0;

            while( n ) {
                if( cmp( find_me, key_getter( n->value ) ) ) {
                    n = n->left;
                } else {
                    notLT = n;
                    n = n->right;
                }
            }
            // The last node the key is not less than (if any) may be equal, in which case it
            // was found.
            if( notLT && !(cmp( key_getter( notLT->value ), find_me ) ) ) { // !(a<b) & !(b<a) then a==b
                return const_iterator( this, notLT );
            } else {
                return end( );
            }
        }

        /* ------------------------------------------------------------------
         * lower_bound( key_type )
         *
         * find first[lowest/most left] node that !(node.key < k) [equivalent to node.key >= k]
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::iterator
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::lower_bound(
            const key_type &find_me )
        {
            Node *n = mRoot;
            Node *nodeNotLTkey = 0;

            while( n ) {
                if( cmp( key_getter( n->value ), find_me ) ) {
                    n = n->right;
                } else {
                    nodeNotLTkey = n;
                    n = n->left;
                }
            }
            // If there are no nodes >= find_me then nodeNotLTkey will still be 0 thus the end( )
            // iterator will be created as expected.
            return( iterator( this, nodeNotLTkey ) );
        }

        /* ------------------------------------------------------------------
         * lower_bound( key_type ) const
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::const_iterator
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::lower_bound(
            const key_type &k ) const
        {
            return( const_cast<RedBlackTree*>( this )->lower_bound( k ) );
        }

        /* ------------------------------------------------------------------
         * upper_bound( key_type )
         * find first[lowest/most left] node that node.key > k
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::iterator
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::upper_bound(
            const key_type &find_me )
        {
            Node *n = mRoot;
            Node *nodeGTkey = 0;

            while( n ) {
                if( cmp( find_me, key_getter( n->value ) ) ) {
                    nodeGTkey = n;
                    n = n->left;
                } else {
                    n = n->right;
                }
            }
            // If there are no node > find_me then nodeNotGTkey will still be 0 thus the end( )
            // iterator will be created as expected.
            return( iterator( this, nodeGTkey ) );
        }


        /* ------------------------------------------------------------------
         * upper_bound( key_type ) const
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::const_iterator
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::upper_bound(
            const key_type &k ) const
        {
            return( const_cast<RedBlackTree*>( this )->upper_bound( k ) );
        }

        /* ------------------------------------------------------------------
         * walk_right( Node* )
         *
         * iterate to next greater node
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::Node *
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::walk_right( Node *n ) const
        {
            if( n->right ) {
                n = n->right;
                while( n->left ) {
                    n = n->left;
                }
            } else {
                while( n->get_parent( ) && (n == n->get_parent( )->right) ) {
                    n = n->get_parent( );
                }
                n = n->get_parent( );
            }
            return n;
        }

        /* ------------------------------------------------------------------
         * walk_left( Node* )
         * iterate to next node with lower key
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::Node *
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::walk_left( Node *n ) const
        {
            if( n->left ) {
                n = n->left;
                while( n->right ) {
                    n = n->right;
                }
            } else {
                while( n->get_parent( ) && (n == n->get_parent( )->left) ) {
                    n = n->get_parent( );
                }
                n = n->get_parent( );
            }
            return n;
        }

        /* ------------------------------------------------------------------
         * black_height( iterator )
         * Calculate black height of node.
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        int RedBlackTree< Key, Compare, Allocator, ValueWrapper >::black_height( iterator i )
        {
            Node *n = i.get_node_pointer( );
            int c = 0;
            while( n ) {
                if( n->is_black( ) )
                    c++;
                n = n->get_parent( );
            }
            return c;
        }

        /* ------------------------------------------------------------------
         * height( iterator )
         * calculate height of node
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        int RedBlackTree< Key, Compare, Allocator, ValueWrapper >::height( iterator i )
        {
            Node *n = i.get_node_pointer( );
            int c = 0;
            while( n ) {
                c++;
                n = n->get_parent( );
            }
            return c;
        }

        /* ------------------------------------------------------------------
         * insert_balance_transform
         *
         * Ref: Chris Okasaki paper (2005?) proposing simple transform for insert balance and
         * Lyn Turbak CS231 handout #21 (2001)
         *
         * If uncle is red we just do a colour change, if uncle is black we do a transform in
         * summary 4 cases transform to this:
         *
         *        y(b)
         *      /     \
         *    x(r)    z(r)
         *  /   \     /   \
         * a(b) b(b) c(b) d(b)
         *
         * case 1:          case 2:        case 3:         case 4:
         * (insert x)      (insert y)     (insert z)      (insert y)
         *       z             z             x                x
         *      / \           / \           / \              /  \
         *     y   d         x   d         a   y            a   z
         *    / \           / \               / \              /        \
         *   x   c         a   y             b   z            y   d
         *  / \               / \               / \          /  \
         * a   b             b   c             c   d        b   c
         */
        template<class Key, class Compare, class Allocator, class ValueWrapper>
        void RedBlackTree<Key, Compare, Allocator, ValueWrapper>::insert_balance_transform(
            Node *inserted )
        {
            // At this point inserted->colour == red.
            for( ;; ) {
                /* Terminating case.
                 * 1. We have moved up the tree and are now the root.
                 * 2. Our parent is the root (therefore must be black).
                 * 3. Our parent is black (no red-red problem any more).
                 */
                if( inserted->get_parent( ) == 0 ||
                    inserted->get_parent( )->get_parent( ) == 0 ||
                    inserted->get_parent( )->is_black( ) )
                    return;

                /* So at this point parent must also be red, and grandparent must be black
                 * therefore our sibling must be black (our children are black by definition)
                 * leaving two main cases : our uncle can black or red.
                 */
                Node *parent = inserted->get_parent( );
                Node *grandparent = inserted->get_parent( )->get_parent( );
                Node *uncle;
                // Find uncle.
                if( parent == grandparent->left ) {
                    uncle = grandparent->right;
                } else {
                    uncle = grandparent->left;
                }
                if( uncle && (uncle->is_red( )) ) {    // Main case a: red uncle.
                    // Now we propagate grandparents blackness between parent and uncle (without
                    // need to rotate).
                    grandparent->set_red( );
                    parent->set_black( );
                    uncle->set_black( );
                    mRoot->set_black( );      // Just in case grandparent was root.
                    inserted = grandparent; // Prepare to propergate red-red up tree.
                    // The execusion flow now jumps back to the for loop instead of recursive
                    // insert_balance_transform( inserted ).
                } else { // Main case b:  black uncle.
                    Node *x,*y,*z,*b,*c;
                    if( (inserted == parent->left) && (parent == grandparent->left) ) {
                    // case 1
                        x = inserted;
                        y = parent;
                        z = grandparent;
                        b = x->right;
                        c = y->right;
                    } else if( (inserted == parent->right) && (parent == grandparent->left) ) {
                    //case 2
                        x = parent;
                        y = inserted;
                        z = grandparent;
                        b = y->left;
                        c = y->right;
                    } else if( (inserted == parent->right) && (parent == grandparent->right) ) {
                    //case 3
                        x = grandparent;
                        y = parent;
                        z = inserted;
                        b = y->left;
                        c = z->left;
                    } else if( (inserted == parent->left) && (parent == grandparent->right) ) {
                    //case4
                        x = grandparent;
                        y = inserted;
                        z = parent;
                        b = y->left;
                        c = y->right;
                    }

                    // Recolour - can use this order becase all leafs a,b,c,d must be black
                    // (uncle is black) this will stop red-red violation from propagating.
                    y->set_black( );
                    x->set_red( );
                    z->set_red( );

                    // Transform to balanced structure.
                    if( grandparent == mRoot ) {
                        mRoot = y;
                        y->set_parent( 0 );
                    } else {
                        if( grandparent->get_parent( )->left == grandparent ) {
                            grandparent->get_parent( )->left = y;
                        } else { // Grandparent is righty.
                            grandparent->get_parent( )->right = y;
                        }
                        y->set_parent( grandparent->get_parent( ) );
                    }

                    y->left = x;
                    y->right = z;
                    x->set_parent( y );
                    z->set_parent( y );
                    x->right = b;
                    z->left = c;
                    if( b )
                        b->set_parent( x );
                    if( c )
                        c->set_parent( z );
                    // a and d are always already linked to the right parent in this case we
                    // have fixed the red-red violation so finish.
                    return;
                } // End main case uncle black.
            } // End for( ever ).
        }

        /* ------------------------------------------------------------------
         * _Sane( )
         *
         * Test the implementation for errors and test the container hasn't been corrupt return
         * true if everything is okay.
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        bool RedBlackTree< Key, Compare, Allocator, ValueWrapper >::_Sane( )
        {
            if( !mRoot ) {
                // No element in tree.
                if( mSize != 0 ) {
                    mError = 10;
                    return false;
                } else {
                    // Nothing else in tree to check.
                    return true;
                }
            }
            iterator it = begin( );
            Node *n = it.get_node_pointer( );
            Node *high_n = n;
            Node *low_n = n;
            const Key *lowkey = &key_getter(n->value);
            const Key *highkey = &key_getter(n->value);
            int count = 0;
            int maxheight = height(it);
            int bheight = -1;

            if( n->left ) {             // Begining element cant have a left node.
                mError = 20;
                return false;
            }
            if( mRoot->is_red( ) ) {
                mError = 25;
                return false;           // Root should always be black.
            }

            do {
                if( ++count > size( ) ) {
                    mError = 30;                // We could have got trapped in a loop, can't
                    return false;               // be more iterations than size.
                }
                Node* n_old = n;
                n = it.get_node_pointer( );
                if( (it != begin( )) && (n_old == n) ) {
                    mError = 40;                // Circular links:
                    return false;               // Iterating didn't advance.
                }
                if( n->is_red( ) &&
                    n->get_parent( ) &&
                    n->get_parent( )->is_red( ) ) {
                    mError = 50;
                    return false;               // Red-red error.
                }
                if( n->get_parent( ) &&
                    (n->get_parent( )->left != n) &&
                    (n->get_parent( )->right != n) ) {
                    mError = 60;
                    return false;               // Links broken.
                }
                if( !n->get_parent( ) && (mRoot != n) ) {
                    mError = 70;
                    return false;              // Links broken.
                }
                if( (n->left == n) || (n->right == n) ) {
                    mError = 80;
                    return false;               // Simple circular loop detection.
                    // ? Not sure this works as iterating will get stuck before detection ?
                }
                if( !n->get_parent( ) && n != mRoot ) {
                    mError = 90;
                    return false;               // No parent but not root.
                }
                // Keep track of the lowest key we come across.
                if( cmp( key_getter( n->value ), *lowkey ) ) {
                    lowkey = &key_getter( n->value );
                    low_n = n;
                }
                // Keep track of the highest key we come across.
                if( cmp( *highkey, key_getter( n->value ) ) ) {
                    highkey = &key_getter( n->value );
                    high_n = n;
                }
                if( !n->left || !n->right ) {   // Null child is a leaf.
                    int bh = black_height( it );
                    if( bheight == -1 ) {
                        bheight = bh;
                    } else if( bheight != bh ) {
                        mError = 100;
                        return false;           // Black height to leaves not same.
                    }
                }
                int h = height( it );           // Keep track of deepest node depth.
                if( h > maxheight ) {
                    maxheight = h;
                }

            } while( ++it != end( ) );

            if( count != size( ) ) {
                mError = 110;
                return false;
            }
            if( n->right ) { // End element cant have a right node.
                mError = 120;
                return false;
            }
            if( (high_n != (--end( )).get_node_pointer( )) ||
                (low_n != begin( ).get_node_pointer( )) ) {
                mError = 130;
                return false;
            }
            return true;
        }

        /* ------------------------------------------------------------------
         * erase( key )
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::size_type
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::erase( const Key& k )
        {
            iterator it = find( k );
            if( it == end( ) ) {
                return 0;
            } else {
                erase( it );
                return 1;
            }
        }

        /* ------------------------------------------------------------------
         * erase( iterator )
         *
         * Maybe to do: this isn't the most easy to understand, is there a nicer way of writing
         * it?
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        void RedBlackTree< Key, Compare, Allocator, ValueWrapper >::erase( iterator it )
        {
            Node *delete_me = it.get_node_pointer( );
            Node *child;    // (Re)moved endnode child.
            Node *parent;   // Parent of (re)moved endnode.
            bool  lefty;    // True if (re)moved endnode was left child.
            Node::Chroma colour;    // (Re)moved endnode colour.

            mSize--;

            if( delete_me == mFirst ) {
                if( delete_me == mLast ) {
                    // Special case, deleted == only element in tree.
                    mFirst = 0;
                    mLast = 0;
                } else {
                    mFirst = walk_right( delete_me );
                }
            } else if( delete_me == mLast ) {
                mLast = walk_left( delete_me );
            }

            // If not end node swap for predecessor.
            if( delete_me->left && delete_me->right ) {
                Node *predecessor = walk_left( delete_me );
                colour = predecessor->get_colour( );
                child = predecessor->left;  // Predecessor can't have a right child.
                if( predecessor == predecessor->get_parent( )->left ) {
                    lefty = true;
                } else {
                    lefty = false;
                }
                // Fix up parent's link.
                if( delete_me == mRoot ) {
                    mRoot = predecessor;
                } else if( delete_me == delete_me->get_parent( )->left ) {
                    delete_me->get_parent( )->left = predecessor;
                } else {
                    delete_me->get_parent( )->right = predecessor;
                }
                // If delete_me is one level above predecessor we have to be careful linking
                // left as it could create a circular link and a link to the deleted item.
                if( predecessor != delete_me->left ) {
                    // Fix up chidren's link.
                    delete_me->left->set_parent( predecessor );
                    // Fix predecessors link.
                    predecessor->left = delete_me->left;
                    parent = predecessor->get_parent( );
                } else { // Predecessor is erased node's child.
                    parent = predecessor;
                    // Leave old left child links intact.
                }
                // Common bits.
                // Fix childrens links.
                delete_me->right->set_parent( predecessor );
                // Fix predecessor's links.
                predecessor->set_colour( delete_me->get_colour( ) );
                predecessor->set_parent( delete_me->get_parent( ) );
                predecessor->right = delete_me->right;
            } else { // End node.
                if( delete_me->left ) {
                    child = delete_me->left;
                } else {
                    child = delete_me->right;
                }
                parent = delete_me->get_parent( );
                colour = delete_me->get_colour( );
                if( parent && ( delete_me == parent->left ) ) {
                    lefty = true;
                } else {
                    lefty = false;
                }
            }

            // Delete delete_me.
            mem.destroy( delete_me );
            mem.deallocate( delete_me, 1 );
            // Handle simple cases.
            if( !parent ) {
                // Root with up to 1 child.
                if( child ) {
                    mRoot = child;
                    mRoot->set_parent( 0 );
                    mRoot->set_black( );
                } else {
                    mRoot = 0;
                }
            } else if( colour == Node::red ) {
                // Red end node cant have a single child node or it would have violated red-red
                // rule or black height rule removing it doesn't change black height so we are
                // done.
                if( lefty ) {
                    parent->left = 0;
                } else {
                    parent->right = 0;
                }
            } else if( child ) {
                // Black end node may have a single child, in which case it has to be red and we
                // can fix up the black height easily.
                if( lefty ) {
                    parent->left = child;
                } else { // Righty.
                    parent->right = child;
                }
                child->set_parent( parent );
                child->set_black( );
            } else {
                // Black node with no children.
                if( lefty ) {
                    parent->left = 0;
                } else {
                    parent->right = 0;
                }
                // (Re)moving this will cause black height problem do some operations to keep rb
                // tree valid.
                double_black_transform( parent,lefty );
            }

            return;
        }

        /* ------------------------------------------------------------------
         * double_black_transform
         * Fix double-black node to rebalance the tree after delete
         *
         * (this doesn't touch key or type, can the compiler figure out it can use one block of
         * code for all template instantiations or does it need to be coded in a non template
         * base class?)
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        void
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::double_black_transform(
            Node *parent, bool lefty )
        {
            for( ;; ) {
                Node *sibling;
                Node *x,*y,*z,*b,*c;
                if( lefty ) {
                    sibling = parent->right;
                } else { // Righty.
                    sibling = parent->left;
                }

                if( sibling->is_black( ) ) {
                    if( ( sibling->right && sibling->right->is_red( ) ) ||
                        ( sibling->left && sibling->left->is_red( ) ) ) {
                        // Main case 1 sibling black, at least one nephew red we can fix this
                        // case.
                        /*
                         *     case a               case b        case c              case d
                         *      Z(*)                 Z(*)          X(*)                X(*)
                         *     /   \\               /   \\       //    \             //    \
                         *   X(b)   d(bb)         Y(b)   d(bb)  a(bb)   Y(b)       a(bb)   Z(b)
                         *  /    \               /    \                 /  \              /  \
                         * a(*)   Y(r)          X(r)  c(*)            b(*) Z(r)         Y(r) d(*)
                         *       /   \         /   \                       /   \       /   \
                         *     b(b)   c(b)   a(b)  b(b)                   c(b) d(b)   b(b) c(b)
                         *
                         * Transform to this:
                         *       Y(*)
                         *      /               \
                         *   X(b)      Z(b)
                         *  /   \     /         \
                         * a(*) b(*) c(*) d(*)
                         *
                         * Where double black goes black & new root takes old root colour note
                         * nodes a,b,c may be null (leafs).
                         */
                        if( sibling->right && sibling->right->is_red( ) ) {
                            if( lefty ) {   // case 1 c
                                x = parent;
                                y = sibling;
                                z = sibling->right;
                                b = y->left;
                                c = z->left;
                            } else {        // case 1 a
                                z = parent;
                                x = sibling;
                                y = sibling->right;
                                b = y->left;
                                c = y->right;
                            }
                        } else { // sibling->left && sibling->left->colour == red
                            if( lefty ) {   // case 1 d
                                x = parent;
                                z = sibling;
                                y = sibling->left;
                                b = y->left;
                                c = y->right;
                            } else {        // case 1 b
                                z = parent;
                                y = sibling;
                                x = sibling->left;
                                b = x->right;
                                c = y->right;
                            }
                        }
                        // Finish off case 1 by relinking to correct sturcture.
                        y->set_parent( parent->get_parent( ) );
                        if( parent == mRoot ) {
                            mRoot = y;
                        } else {    // Link grandparent back to y.
                            if( parent == parent->get_parent( )->left ) {
                                parent->get_parent( )->left = y;
                            } else {
                                parent->get_parent( )->right = y;
                            }
                        }
                        y->set_colour( parent->get_colour( ) );
                        y->left = x;
                        y->right = z;
                        x->set_parent( y );
                        x->set_black( );
                        x->right = b;       // x->left is unchanged as a
                        if( b )
                            b->set_parent( x );
                        z->set_parent( y );
                        z->set_black( );
                        z->left = c;        // z->right is unchanged as d
                        if( c )
                            c->set_parent( z );
                        return;
                    } else {  // Nephews both black.
                        if( parent->is_red( ) ) {
                            // Main case 2: sibling black, two black nephews, parent red we can
                            // fix this case
                            /*
                             *      case a           case b
                             *       Z(r)             X(r)
                             *      /   \\           //   \
                             *    X(b)   d(bb)     a(bb)  Z(b)
                             *   /    \                  /    \
                             *  a(b)   b(b)             b(b)  d(b)
                             *
                             * Recolour to this:
                             *        Z(b)              X(b)
                             *       /    \            /    \
                             *    X(r)    d(b)       a(b)   Z(r)
                             *   /   \                     /    \
                             *  a(b) b(b)                b(b)   d(b)
                             *
                             */
                            parent->set_black( );
                            sibling->set_red( );
                            return;
                        } else { // Parent black.
                            // Main case 3: sibling black, two black nephews, parent black.
                            /*
                             *        case a           case b
                             *         Z(b)             X(b)
                             *        /   \\           //   \
                             *      X(b)   d(bb)     a(bb)  Z(b)
                             *     /    \                  /    \
                             *    a(b)   b(b)             b(b)  d(b)
                             *
                             * Recolour to propergate double black:
                             *        ||                ||
                             *       Z(bb)             X(bb)
                             *      /     \           /    \
                             *   X(r)      d(b)     a(b)   Z(r)
                             *  /   \                     /    \
                             * a(b) b(b)                b(b)   d(b)
                             *
                             * Not much we can do - propergate double black If double black has
                             * properaged to to root just set it black as we have acheived balance
                             * (higher order special cases may be possible eg node a has two red
                             * children but probably not worth the extra code to check?)
                             */
                            sibling->set_red( );
                            if( parent == mRoot ) {
                                parent->set_black( );
                                return;
                            }
                            Node* grandparent = parent->get_parent( );
                            if( parent == grandparent->left ) {
                                lefty = true;
                            } else {
                                lefty = false;
                            }
                            // Loop to top of double_black_transform with new parent (replaces
                            // recursion) double_black_transform(grandparent, lefty); return;
                            parent = grandparent;
                        }
                    } // End main case 2/3.
                } else {
                    // Main case 4: red sibling.
                    /*
                     *        case a           case b
                     *         Z(b)             X(b)
                     *        /   \\           //   \
                     *      X(r)   d(bb)     a(bb)  Z(r)
                     *     /    \                  /    \
                     *    a(b)   b(b)             c(b)  d(b)
                     *
                     * Recolour to propergate double black:
                     *       X(b)                   Z(b)
                     *      /    \                 /    \
                     *   a(b)     Z(r)           X(r)   d(b)
                     *           /   \\         //  \
                     *         b(b)  d(bb)   a(bb)  c(b)
                     *
                     * This is an annoying one! Note, a and b must have children (ie a/b
                     * can't be null/leaves) or the black height doesn't add up. Double
                     * black stays with the same node but restructure so we can use one of
                     * the previous cases (1 or 2) where the sibling is black.
                     */
                    // Common bits.
                    if( parent == mRoot ) {
                        mRoot = sibling;
                        sibling->set_parent( 0 );
                    } else if( parent == parent->get_parent( )->left ) {
                        parent->get_parent( )->left = sibling;
                        sibling->set_parent( parent->get_parent( ) );
                    } else {// Parent is a righty.
                        parent->get_parent( )->right = sibling;
                        sibling->set_parent( parent->get_parent( ) );
                    }
                    parent->set_red( );
                    sibling->set_black( );

                    if( lefty ) {
                        // case b
                        x = parent;
                        c = sibling->left;
                        z = sibling;
                        x->right = c;
                        c->set_parent( x );
                        x->set_parent( z );
                        z->left = x;
                        // a & d stay linked to the same nodes
                    } else {  // righty.
                        // case a
                        z = parent;
                        b = sibling->right;
                        x = sibling;
                        z->left = b;
                        b->set_parent( z );
                        z->set_parent( x );
                        x->right = z;
                        // a & d stay linked to the same nodes
                    }
                    // Now try again and case will be 1, 2, or 3 note old parent is still parent
                    // of double black and left/right position of double black hasn't changed
                    // recursion has been replaced with the for loop
                    // double_black_transform(parent,lefty); return;
                }
            } // End for( ever ).
        }

        /* ------------------------------------------------------------------
         * unbalanced_insert( value_type const & )
         *
         * Like find but create new node after last node visited if cant find an existing key.
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper>
        std::pair< typename RedBlackTree< Key,
                                          Compare,
                                          Allocator,
                                          ValueWrapper >::iterator, bool >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::unbalanced_insert(
            const value_type &v )
        {
            if( mRoot == 0 ) {              // Special case nothing exists yet.
                mRoot = mem.allocate( 1 );
                try {
                    mem.construct( mRoot, Node( v, 0, Node::black ) );
                }
                catch( ... ) {
                    mem.deallocate( mRoot, 1 );
                    mRoot = 0;
                    throw;
                }
                mFirst = mRoot;
                mLast = mRoot;
                mSize++;
                return( std::pair<iterator, bool>( iterator(this, mRoot), true ) );
            }

            Node *n = mRoot;
            Node *notLT = 0;
            Node *last = n;
            bool  LtLast;

            while( n ) {
                if( cmp(key_getter( v ), key_getter( n->value ) ) ) {
                    last = n;
                    LtLast = true;
                    n = n->left;
                } else {
                    last = n;
                    LtLast = false;
                    notLT = n;
                    n = n->right;
                }
            }

            // The last node the key is not less than (if any) may be equal, in which case it
            // was found.
            if( notLT && !( cmp( key_getter( notLT->value ), key_getter( v ) ) ) ) {
                // !(a<b) & !(b<a) then a==b
                return( std::pair<iterator,bool>( iterator(this, notLT), false ) );
            }
            // Otherwise insert the new node with parent as last node travelled to.
            Node *newnode = mem.allocate( 1 );
            try {
                mem.construct( newnode, Node( v, last, Node::red ) );
            }
            catch( ... ) {
                mem.deallocate( newnode, 1 );
                throw;
            }
            mSize++;
            if( LtLast ) {
                last->left = newnode;
                if( last == mFirst ) {
                    mFirst = newnode;
                }
            } else {
                last->right = newnode;
                if( last == mLast ) {
                    mLast = newnode;
                }
            }

            return( std::pair<iterator,bool>( iterator(this, newnode), true ) );
        }


        /* ------------------------------------------------------------------
         * insert( value_type const & )
         *
         * Inserts v into the tree if it doesn't exist already and maintains balance returns a
         * pair containing iterator with key equivelent to that of v and a bool that is true if
         * v was inserted or false if the key already existed.
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        std::pair< typename RedBlackTree< Key,
                                          Compare,
                                          Allocator,
                                          ValueWrapper >::iterator, bool >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::insert(
            const value_type &v )
        {
            pair< iterator, bool > inserted = unbalanced_insert( v );
            if( inserted.second ) {
                Node *n = inserted.first.get_node_pointer( );
                if( n != mRoot ) {
                    // Do some operations to keep rb tree valid.
                    insert_balance_transform( n );
                }
                // Otherwise if n == mRoot it has been inserted as single black node and there
                // is nothing else to do.
            }
            return inserted;
        }


        /* ------------------------------------------------------------------
         * insert( iterator hint, value_type const &)
         *
         * Inserts v into the tree if it doesn't exist already and maintains ballance returns a
         * pair containing iterator with key equivelent to that of v and a bool that is true if
         * v was inserted or false if the key already existed Written in the spirit of N1780
         * (not strictly standard compliant?).
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        std::pair< typename RedBlackTree< Key,
                                          Compare,
                                          Allocator,
                                          ValueWrapper >::iterator, bool >
        RedBlackTree< Key, Compare, Allocator, ValueWrapper >::insert(
            iterator hint, const value_type &v )
        {
            pair< iterator, bool > inserted;
            iterator b4hint;
            if( mSize && ( hint == end( ) || cmp( key_getter( v ), key_getter( *hint ) ) ) ) {

                // At this point tree isn't empty and key is before hint.
                b4hint = hint;
                if( hint == begin( ) || cmp( key_getter( *(--b4hint) ), key_getter( v ) ) ) {
                    // At this point key is also before begin or after (hint-1) so hint is good
                    // now, either hint->left or (hint-1)->right must have a unused leaf node
                    // where the new node belongs.
                    Node *parent;
                    bool  lefty = true;

                    if( hint != end( ) && hint.get_node_pointer( )->left == 0 ) {
                        parent = hint.get_node_pointer( );
                    } else {
                        parent = b4hint.get_node_pointer( );
                        lefty = false;
                    }
                    // Create the new node.
                    Node *newnode = mem.allocate( 1 );
                    try {
                        mem.construct( newnode, Node(v, parent, Node::red) );
                    }
                    catch( ... ) {
                        mem.deallocate( newnode, 1 );
                        throw;
                    }
                    mSize++;
                    // Fix up pointers.
                    if( lefty ) {
                        parent->left = newnode;
                        if( parent == mFirst ) {
                            mFirst = newnode;
                        }
                    } else {
                        parent->right = newnode;
                        if( parent == mLast ) {
                            mLast = newnode;
                        }
                    }
                    inserted = make_pair( iterator(this, newnode), true );
                } else {
                    inserted = unbalanced_insert( v ); // Hint bad (or key already exists).
                }
            } else {
                inserted = unbalanced_insert( v ); // Hint is bad or tree is empty.
            }

            if( inserted.second ) {
                Node *n = inserted.first.get_node_pointer( );
                if( n != mRoot ) {
                    // Do some operations to keep rb tree valid.
                    insert_balance_transform( n );
                }
                // Otherwise if n == mRoot it has been inserted as single black node and there
                // is nothing else to do.
            }
            return inserted;
        }


        /* ================================================================== */


        /* ==================================================================
         * MLRBTNode
         *
         * Sub-node type that forms a linked list and is stored in the rbtree node to create the
         * MultiListRBTree.
         */
        template< class ValueType >
        struct MLRBTNode{
            MLRBTNode *fwd;
            MLRBTNode *bwd;
            ValueType value;

            MLRBTNode( )
                { }

            MLRBTNode( ValueType v ) : value( v )
                { }
        };

        /* ==================================================================
         * ValueWrappers for MultiListRBTree
         *
         * Pairs for multimap, plain Keys for multiset wraps up the rbtree type (pointer to the
         * list) and knows how to get a key out of it.
         */
        template< class Key, class Type >
        struct ListTreePairWrapper {
            // This is the value_type actually contained in the container.
            typedef pair< const Key, Type > value_type;
            const Key &operator()( const value_type &v ) const
                { return( v.first ); }

            struct TreeWrapper {
                // This is the rbtree value_type (pointer to list).
                typedef MLRBTNode< pair< const Key, Type > > *value_type;
                const Key &operator()( const value_type &v ) const
                    { return( v->value.first ); }
            };
        };

        template< class Key >
        struct ListTreeKeyWrapper{
            // This is the value_type actually contained in the container.
            typedef Key value_type;
            const Key &operator()( const value_type &v ) const
                { return( v ); }

            struct TreeWrapper{
                // This is the rbtree value_type (pointer to list).
                typedef MLRBTNode< Key > *value_type;
                const Key &operator()( const value_type &v ) const
                    { return( v->value); }
            };
        };

        /* ==================================================================
         * MultiListRBTree
         *
         * Adds linked list to redblack tree to build a multimap/set. handles the list
         * operations in this class rather than using a full blown (or even a cut down one) list
         * object in tree node. This should save a little memory. Note for a low number of
         * repetitions of each key this alogorithm will use more memory than holding the
         * repeated nodes directly in tree for this algorithm p = 4 + 2n ; c = 1 for tree only
         * algo p = 3n ; c = n where p is num of pointers, c is num of colour enums, n is num of
         * key repetitions so if c uses same space as p (likely due to alignment?) this algo is
         * better if n >=3 This algo should have slightly faster find (+ insert/delete)
         * operations.
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        class MultiListRBTree{
        public:
            typedef ValueWrapper::value_type value_type;
            typedef unsigned int             size_type;
            typedef Key                      key_type;

        private:
            typedef RedBlackTree< Key, Compare, Allocator, ValueWrapper::TreeWrapper > tree_type;
            typedef MLRBTNode< value_type > node_type;

            Allocator::rebind< node_type >::other mem; // Moved up here to stop crash.

        public:
            MultiListRBTree(Compare c, Allocator a)
                : mSize( 0 ), mTree( tree_type( c, a ) ), mem( a )
                { }

            MultiListRBTree( const MultiListRBTree & );
           ~MultiListRBTree( );

            Allocator get_allocator( ) const
                { Allocator a(mem); return( a ); }

            MultiListRBTree &operator=( const MultiListRBTree & );

            /* ------------------------------------------------------------------
             * iterators
             */
            class iterator_base;
            friend class iterator_base;

            class iterator_base{
            public:
                iterator_base &operator++( )
                {
                    if( self == (*tit)->bwd ) {  // If last element in list.
                        ++tit;
                        if( tit != mlt->mTree.end( ) ) {
                            self = *tit;
                        } else {
                            self = 0;          // Signals end iterator.
                        }
                    } else {
                        self = self->fwd;
                    }
                    return( *this );
                }

                iterator_base &operator--( )
                {
                    if( self == 0 || self == (*tit) ) {
                        // If first element in list or end of list.
                        --tit;
                        self = (*tit)->bwd;
                    } else {
                        self = self->bwd;
                    }
                    return( *this );
                }

                value_type &operator*( )
                    { return( self->value ); }

                value_type *operator->( )
                    { return( &(self->value) ); }

                bool operator==( const iterator_base &that )
                    { return( self == that.self ); }

                bool operator!=( const iterator_base &that )
                    { return( self != that.self ); }

                const iterator_base &operator=( const iterator_base &that )
                {
                    tit = that.tit;
                    mlt = that.mlt;
                    self = that.self;
                    return( *this );
                }

            protected:
                friend class MultiListRBTree;
                iterator_base( )
                    { }

                iterator_base( const iterator_base &x )
                    : tit( x.tit ), mlt( x.mlt ), self( x.self )
                    { }

                iterator_base( const MultiListRBTree *m, const tree_type::iterator &i )
                    : mlt( m ), tit( i )
                    { ( tit != (mlt->mTree).end( ) ) ? self = (*tit) : self = 0; }

                iterator_base( const MultiListRBTree *m,
                               const tree_type::iterator &i,
                               node_type *n )
                    : mlt( m ), tit( i ), self( n )
                    { }

                tree_type::iterator tit;
                const MultiListRBTree *mlt;
                node_type *self;
            };

            class iterator : public iterator_base{
            public:
                iterator( ) : iterator_base( )
                    { }

                iterator( const iterator &i ) : iterator_base( i )
                    { }

                iterator( const MultiListRBTree *m, const tree_type::iterator &i )
                    : iterator_base( m, i )
                    { }

                iterator( const MultiListRBTree *m,
                          const tree_type::iterator &i,
                          node_type *n )
                    : iterator_base( m, i, n )
                    { }

                iterator &operator++( )
                    { return( (iterator&)iterator_base::operator++( ) ); }

                iterator &operator--( )
                    { return( (iterator&)iterator_base::operator--( ) ); }

                iterator &operator++( int )
                    { iterator i(*this); operator++( ); return( i ); }

                iterator &operator--( int )
                    { iterator i(*this); operator--( ); return( i ); }
            };

            class const_iterator : public iterator_base{
            public:
                const_iterator( ) : iterator_base( )
                    { }

                const_iterator( const const_iterator &i ) : iterator_base( i )
                    { }

                const_iterator( const iterator &i ) : iterator_base( i )
                    { }

                const_iterator( const MultiListRBTree *m, const tree_type::iterator &i )
                    : iterator_base( m, i )
                    { }

                const_iterator( const MultiListRBTree * m,
                                const tree_type::iterator &i,
                                node_type *n )
                    : iterator_base( m, i, n )
                    { }

                const_iterator &operator++( )
                    { return( (const_iterator&)iterator_base::operator++( ) ); }

                const_iterator &operator--( )
                    { return( (const_iterator&)iterator_base::operator--( ) ); }

                const_iterator &operator++( int )
                    { const_iterator i(*this); operator++( ); return( i ); }

                const_iterator &operator--( int )
                    { const_iterator i(*this); operator--( ); return( i ); }
            };

            iterator begin( )
                { return( iterator( this, mTree.begin( ) ) ); }

            iterator end( )
                { return( iterator( this, mTree.end( ) ) ); }

            // Note use const_cast<> so calls version of mTree.end( )/begin( ) that return an
            // iterator not a const_iterator for interal use within the iterator of this class.
            // mTree still doesn't get modified.
            //
            const_iterator begin( ) const
                { return( const_iterator( this, const_cast<tree_type*>(&mTree)->begin( ) ) ); }

            const_iterator end( ) const
                { return( const_iterator( this, const_cast<tree_type*>(&mTree)->end( ) ) ); }

            // Capacity.
            size_type   size( ) { return( mSize ); }
            bool        empty( ) { return( !mSize ); }

            // Modifiers.
            iterator    insert( const value_type & );
            iterator    insert( iterator, const value_type & );
            void        erase( iterator );
            size_type   erase( const key_type & );
            void        clear( );

            // Operations.
            iterator        find( const key_type & );
            const_iterator  find( const key_type & ) const;
            size_type       count( const key_type & ) const;
            iterator        upper_bound( const key_type & );
            const_iterator  upper_bound( const key_type &x) const;
            iterator        lower_bound( const key_type & );
            const_iterator  lower_bound( const key_type &x) const;

            std::pair< iterator, iterator > equal_range( const key_type &x )
                { return( make_pair( lower_bound(x), upper_bound(x) ) ); }

            std::pair< const_iterator, const_iterator > equal_range( const key_type & x ) const
                { return( make_pair( lower_bound(x), upper_bound(x) ) ); }

            // OWSTL extentions.
            bool _Sane( );

        private:
            size_type mSize;
            tree_type mTree;            // This is the tree that holds the lists.
            Compare cmp;
            ValueWrapper key_getter;
        };

        /* ------------------------------------------------------------------
         * copy ctor
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::MultiListRBTree(
            const MultiListRBTree< Key, Compare, Allocator, ValueWrapper > &that )
            : mTree( that.mTree ), mem( that.mem )
        {
            // Pointer to old list elements is copied by rbtree copy ctor and the pointers will
            // still link back to the old list elements so now make copies of new list elments
            // and fixup pointers.
            //
            tree_type::iterator it;
            tree_type::const_iterator it2;
            try {
                for( it = mTree.begin( ), it2 = that.mTree.begin( );
                     it != mTree.end( );
                     ++it, ++it2 ) {

                    // Special case, copy the first element in the list.
                    try {
                        *it = mem.allocate( 1 );
                        try {
                            mem.construct( *it, **it2 );
                        }
                        catch( ... ) {
                            mem.deallocate( *it, 1 );
                            throw;
                        }
                    }
                    catch( ... ) {
                        // Signal no first element to rewind logic.
                        *it = 0;
                        throw;
                    }
                    // Copy the rest of the list (if they exist).
                    node_type *start = *it2;
                    node_type *o = start->fwd;
                    node_type *n = *it;
                    while( o != start ) {
                        try {
                            // Allocate the next node.
                            n->fwd = mem.allocate( 1 );
                            try {
                                // o already points to the next node.
                                mem.construct( n->fwd, *o );
                            }
                            catch( ... ) {
                                mem.deallocate( n->fwd, 1 );
                                throw;
                            }
                        }
                        catch( ... ) {
                            // Finish off the links so can do a generic rewind.
                            n->fwd = *it;
                            (*it)->bwd = n;
                            throw;
                        }
                        n->fwd->bwd = n;
                        n = n->fwd;
                        o = o->fwd;
                    }
                    n->fwd = *it;
                    (*it)->bwd = n;
                }
            }
            catch( ... ) {
                // The copy either completely succeeds or completely fails so rewind the nodes
                // added so far.
                for( ; it != mTree.begin( ); --it ) {
                    if( *it == 0 )
                        continue;
                    node_type *n = *it;
                    node_type *delete_me;
                    node_type *end = n;
                    do {
                        delete_me = n;
                        n = n->fwd;
                        mem.destroy( delete_me );
                        mem.deallocate( delete_me, 1 );
                    } while( n != end );
                }
                mTree.clear( );
                throw;
            }

            // Success.
            mSize = that.mSize;
        }

        /* ------------------------------------------------------------------
         * operator=( that )
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >&
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::operator=(
            const MultiListRBTree &that )
        {
            clear( );
            new ( this ) MultiListRBTree( that );
            return( *this );
        }

        /* ------------------------------------------------------------------
         * insert( value_type const & )
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::iterator
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::insert( const value_type &x )
        {
            node_type *n;
            pair< tree_type::iterator, bool > ans;
            n = mem.allocate( 1 );
            try {
                mem.construct( n, node_type(x) );
            }
            catch( ... ) {
                mem.deallocate( n, 1 );
                throw;
            }
            try {
                ans = mTree.insert( n );
            }
            catch( ... ) {
                mem.destroy( n );
                mem.deallocate( n, 1 );
                throw;
            }
            if( ans.second ) {  // Insert happened.
                n->fwd = n;
                n->bwd = n;
            } else {            // Already inserted.
                node_type *o = *ans.first;  // Get pointer to already inserted node
                n->bwd = o->bwd;            // fix up links so as to add new node
                n->fwd = o;                 // to end of list.
                o->bwd->fwd = n;
                o->bwd = n;
            }
            mSize++;
            return iterator( this, ans.first, n );
        }

        /* ------------------------------------------------------------------
         * insert( iterator hint, const value_type & )
         *
         * Insert as close to as before hint as possible. In the spirit of N1780 (Comments on
         * LWG issue 233, Howard E. Hinnant, 23/04/2005)
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::iterator
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::insert(
            iterator hint, const value_type &v )
        {
            // !!!! I'm not happy with this function and it needs redesigning when I have time.
            // !!!

            // To insert x at p:
            //    if( p == end || x <= *p ) {
            //       if( p == begin || x >= *(p-1) ) {
            //          insert x before p
            //       } else {
            //          insert x before upper_bound(x)
            //       }
            //    } else {
            //       insert x before lower_bound(x)
            //    }

            iterator pos;
            if( mSize == 0 ) {
                pos = end( );
            } else {
                if( hint == end( ) || !cmp( key_getter( *hint ), key_getter( v ) ) ) {
                    // !(hint < v)  ==  v <= hint
                    iterator b4hint = hint;
                    if( hint == begin( ) || !cmp( key_getter( v ), key_getter( *(--b4hint) ) ) ) {
                        // !(v < hint)  ==  v >= hint
                        // Insert before hint.
                        pos = hint;
                    } else {
                        // Insert before upper_bound.
                        pos = upper_bound( key_getter(v) );
                    }
                } else {
                    // Insert before lower_bound.
                    pos = lower_bound( key_getter(v) );
                }
            }
            node_type *n;
            pair< tree_type::iterator, bool> ans;
            n = mem.allocate( 1 );
            try {
                mem.construct( n, node_type(v) );
            }
            catch( ... ) {
                mem.deallocate( n, 1 );
                throw;
            }
            try {
                // Insert into tree. to do: rewrite rbtree hint insert so it doesn't need to
                // recheck the hint pos.
                ans = mTree.insert( pos.tit, n );
            }
            catch( ... ) {
                mem.destroy( n );
                mem.deallocate( n, 1 );
                throw;
            }
            // Insert node.
            if( ans.second ) {
                // Only node in list.
                n->fwd = n;
                n->bwd = n;
            } else {
                if( pos == end( ) || cmp( key_getter( v ), key_getter( *pos ) ) ) {
                    // Insert at end of previous list.
                    --pos;
                    n->bwd = pos.self;
                    n->fwd = pos.self->fwd;
                    pos.self->fwd->bwd = n;
                    pos.self->fwd = n;
                } else {
                    // Insert in list before hint.
                    if( *(pos.tit) == pos.self )
                        *(pos.tit) = n;
                    n->bwd = pos.self->bwd;
                    n->fwd = pos.self;
                    pos.self->bwd->fwd = n;
                    pos.self->bwd = n;
                }
            }
            ++mSize;
            return( iterator(this, ans.first, n) );
        }

        /* ------------------------------------------------------------------
         * dtor
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::~MultiListRBTree( )
        {
            clear( );
        }

        /* ------------------------------------------------------------------
         * clear( )
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        void MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::clear( )
        {
            for( tree_type::iterator i = mTree.begin( ); i != mTree.end( ); ++i ) {
                node_type *n = *i;
                node_type *delete_me;
                node_type *end = n;
                do {
                    delete_me = n;
                    n = n->fwd;
                    mem.destroy( delete_me );
                    mem.deallocate( delete_me, 1 );
                } while( n != end );
            }
            mTree.clear( );
            mSize = 0;
        }

        /* ------------------------------------------------------------------
         * _Sane( )
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        bool MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::_Sane( )
        {
            if( !mTree._Sane( ) )
                return false;
            // Do more tests here.
            return true;
        }

        /* ------------------------------------------------------------------
         * find( )
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::iterator
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::find( const key_type &k )
        {
            return iterator( this, mTree.find( k ) );
        }

        /* ------------------------------------------------------------------
         * find( ) const
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::const_iterator
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::find( const key_type &k ) const
        {
            return const_iterator( this, mTree.find( k ) );
        }


        /* ------------------------------------------------------------------
         * count( key_type )
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::size_type
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::count( const key_type &k ) const
        {
            tree_type::iterator tit = mTree.find( k );
            if( tit == mTree.end( ) )
                return 0;
            node_type *start = *tit;
            node_type *n = start;
            size_type c = 0;
            do {
                n = n->fwd;
                ++c;
            } while( n != start );

            return( c );
        }

        /* ------------------------------------------------------------------
         * erase( iterator )
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        void MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::erase( iterator it )
        {
            node_type *n = it.self;
            if( n == n->fwd ) {           // If only element in list...
                mTree.erase( it.tit );
            } else if( *(it.tit) == n ) { // If master element in list & >1 element...
                n->bwd->fwd = n->fwd;     // Relink to remove n.
                n->fwd->bwd = n->bwd;
                *(it.tit) = n->fwd;       // Set tree to hold new master element.
            } else {                      // If not master element & >1 element...
                n->bwd->fwd = n->fwd;     // Relink to remove n.
                n->fwd->bwd = n->bwd;
            }
            mem.destroy( n );
            mem.deallocate( n, 1 );
            --mSize;
        }

        /* ------------------------------------------------------------------
         * erase( key_type )
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::size_type
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::erase( const key_type &k )
        {
            iterator it = find( k );
            node_type *n = it.self;
            node_type *delete_me;
            node_type *end = n;
            size_type c = 0;
            do {
                delete_me = n;
                n = n->fwd;
                mem.destroy( delete_me );
                mem.deallocate( delete_me, 1 );
                ++c;
                --mSize;
            } while( n != end );
            mTree.erase( it.tit );
            return( c );
        }

        /* ------------------------------------------------------------------
         * lower_bound( key_type )
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::iterator
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::lower_bound( const key_type &k )
        {
            tree_type::iterator tit = mTree.lower_bound( k );
            node_type *n = (tit == mTree.end( )) ? 0 : *tit;
            return( iterator( this, tit, n ) );
        }

        /* ------------------------------------------------------------------
         * lower_bound( key_type ) const
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::const_iterator
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::lower_bound( const key_type &k ) const
        {
            return( const_cast<MultiListRBTree*>(this)->lower_bound( k ) );
        }

        /* ------------------------------------------------------------------
         * upper_bound( key_type )
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::iterator
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::upper_bound( const key_type &k )
        {
            tree_type::iterator tit = mTree.upper_bound( k );
            node_type* n = (tit == mTree.end( )) ? 0 : *tit;
            return( iterator( this, tit, n ) );
        }

        /* ------------------------------------------------------------------
         * upper_bound( key_type ) const
         */
        template< class Key, class Compare, class Allocator, class ValueWrapper >
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::const_iterator
        MultiListRBTree< Key, Compare, Allocator, ValueWrapper >::upper_bound( const key_type &k ) const
        {
            return( const_cast<MultiListRBTree*>(this)->upper_bound( k ) );
        }


    } // namespace _ow

} // namespace std

#endif
