// -*- C++ -*-

// Copyright (C) 2005, 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the terms
// of the GNU General Public License as published by the Free Software
// Foundation; either version 3, or (at your option) any later
// version.

// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

// Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.

// Permission to use, copy, modify, sell, and distribute this software
// is hereby granted without fee, provided that the above copyright
// notice appears in all copies, and that both that copyright notice
// and this permission notice appear in supporting documentation. None
// of the above authors, nor IBM Haifa Research Laboratories, make any
// representation about the suitability of this software for any
// purpose. It is provided "as is" without express or implied
// warranty.

/**
 * @file rb_tree_map_/split_join_fn_imps.hpp
 * Contains an implementation for rb_tree_.
 */

PB_DS_CLASS_T_DEC
inline void
PB_DS_CLASS_C_DEC::
join(PB_DS_CLASS_C_DEC& other)
{
  PB_DS_ASSERT_VALID((*this))
  PB_DS_ASSERT_VALID(other)
  if (base_type::join_prep(other) == false)
    {
      PB_DS_ASSERT_VALID((*this))
      PB_DS_ASSERT_VALID(other)
      return;
    }

  const node_pointer p_x = other.split_min();
  join_imp(p_x, other.m_p_head->m_p_parent);
  base_type::join_finish(other);
  PB_DS_ASSERT_VALID((*this))
  PB_DS_ASSERT_VALID(other)
 }

PB_DS_CLASS_T_DEC
void
PB_DS_CLASS_C_DEC::
join_imp(node_pointer p_x, node_pointer p_r)
{
  _GLIBCXX_DEBUG_ASSERT(p_x != 0);
  if (p_r != 0)
    p_r->m_red = false;

  const size_type h = black_height(base_type::m_p_head->m_p_parent);
  const size_type other_h = black_height(p_r);
  node_pointer p_x_l;
  node_pointer p_x_r;
  std::pair<node_pointer, node_pointer> join_pos;
  const bool right_join = h >= other_h;
  if (right_join)
    {
      join_pos = find_join_pos_right(base_type::m_p_head->m_p_parent, 
				     h, other_h);
      p_x_l = join_pos.first;
      p_x_r = p_r;
    }
  else
    {
      p_x_l = base_type::m_p_head->m_p_parent;
      base_type::m_p_head->m_p_parent = p_r;
      if (p_r != 0)
	p_r->m_p_parent = base_type::m_p_head;

      join_pos = find_join_pos_left(base_type::m_p_head->m_p_parent, 
				    h, other_h);
      p_x_r = join_pos.first;
    }

  node_pointer p_parent = join_pos.second;
  if (p_parent == base_type::m_p_head)
    {
      base_type::m_p_head->m_p_parent = p_x;
      p_x->m_p_parent = base_type::m_p_head;
    }
  else
    {
      p_x->m_p_parent = p_parent;
      if (right_join)
	p_x->m_p_parent->m_p_right = p_x;
      else
	p_x->m_p_parent->m_p_left = p_x;
    }

  p_x->m_p_left = p_x_l;
  if (p_x_l != 0)
    p_x_l->m_p_parent = p_x;

  p_x->m_p_right = p_x_r;
  if (p_x_r != 0)
    p_x_r->m_p_parent = p_x;

  p_x->m_red = true;

  base_type::initialize_min_max();
  PB_DS_STRUCT_ONLY_ASSERT_VALID((*this))
  base_type::update_to_top(p_x, (node_update* )this);
  insert_fixup(p_x);
  PB_DS_STRUCT_ONLY_ASSERT_VALID((*this))
}

PB_DS_CLASS_T_DEC
inline typename PB_DS_CLASS_C_DEC::node_pointer
PB_DS_CLASS_C_DEC::
split_min()
{
  node_pointer p_min = base_type::m_p_head->m_p_left;

#ifdef _GLIBCXX_DEBUG
  const node_pointer p_head = base_type::m_p_head;
  _GLIBCXX_DEBUG_ASSERT(p_min != p_head);
#endif 

  remove_node(p_min);
  return p_min;
}

PB_DS_CLASS_T_DEC
std::pair<
  typename PB_DS_CLASS_C_DEC::node_pointer,
  typename PB_DS_CLASS_C_DEC::node_pointer>
PB_DS_CLASS_C_DEC::
find_join_pos_right(node_pointer p_l, size_type h_l, size_type h_r)
{
  _GLIBCXX_DEBUG_ASSERT(h_l >= h_r);

  if (base_type::m_p_head->m_p_parent == 0)
    return (std::make_pair((node_pointer)0, base_type::m_p_head));

  node_pointer p_l_parent = base_type::m_p_head;
  while (h_l > h_r)
    {
      if (p_l->m_red == false)
        {
	  _GLIBCXX_DEBUG_ASSERT(h_l > 0);
	  --h_l;
        }

      p_l_parent = p_l;
      p_l = p_l->m_p_right;
    }

  if (!is_effectively_black(p_l))
    {
      p_l_parent = p_l;
      p_l = p_l->m_p_right;
    }

  _GLIBCXX_DEBUG_ASSERT(is_effectively_black(p_l));
  _GLIBCXX_DEBUG_ASSERT(black_height(p_l) == h_r);
  _GLIBCXX_DEBUG_ASSERT(p_l == 0 || p_l->m_p_parent == p_l_parent);
  return std::make_pair(p_l, p_l_parent);
}

PB_DS_CLASS_T_DEC
std::pair<
  typename PB_DS_CLASS_C_DEC::node_pointer,
  typename PB_DS_CLASS_C_DEC::node_pointer>
PB_DS_CLASS_C_DEC::
find_join_pos_left(node_pointer p_r, size_type h_l, size_type h_r)
{
  _GLIBCXX_DEBUG_ASSERT(h_r > h_l);
  if (base_type::m_p_head->m_p_parent == 0)
    return (std::make_pair((node_pointer)0,
			   base_type::m_p_head));
  node_pointer p_r_parent = base_type::m_p_head;
  while (h_r > h_l)
    {
      if (p_r->m_red == false)
        {
	  _GLIBCXX_DEBUG_ASSERT(h_r > 0);
	  --h_r;
        }

      p_r_parent = p_r;
      p_r = p_r->m_p_left;
    }

  if (!is_effectively_black(p_r))
    {
      p_r_parent = p_r;
      p_r = p_r->m_p_left;
    }

  _GLIBCXX_DEBUG_ASSERT(is_effectively_black(p_r));
  _GLIBCXX_DEBUG_ASSERT(black_height(p_r) == h_l);
  _GLIBCXX_DEBUG_ASSERT(p_r == 0 || p_r->m_p_parent == p_r_parent);
  return std::make_pair(p_r, p_r_parent);
}

PB_DS_CLASS_T_DEC
inline typename PB_DS_CLASS_C_DEC::size_type
PB_DS_CLASS_C_DEC::
black_height(node_pointer p_nd)
{
  size_type h = 1;
  while (p_nd != 0)
    {
      if (p_nd->m_red == false)
	++h;
      p_nd = p_nd->m_p_left;
    }
  return h;
}

PB_DS_CLASS_T_DEC
void
PB_DS_CLASS_C_DEC::
split(key_const_reference r_key, PB_DS_CLASS_C_DEC& other)
{
  PB_DS_ASSERT_VALID((*this))
  PB_DS_ASSERT_VALID(other)

  if (base_type::split_prep(r_key, other) == false)
    {
      PB_DS_ASSERT_VALID((*this))
      PB_DS_ASSERT_VALID(other)
      return;
    }

  PB_DS_STRUCT_ONLY_ASSERT_VALID((*this))
  PB_DS_STRUCT_ONLY_ASSERT_VALID(other)
  node_pointer p_nd = this->upper_bound(r_key).m_p_nd;
  do
    {
      node_pointer p_next_nd = p_nd->m_p_parent;
      if (Cmp_Fn::operator()(r_key, PB_DS_V2F(p_nd->m_value)))
	split_at_node(p_nd, other);

      PB_DS_STRUCT_ONLY_ASSERT_VALID((*this))
      PB_DS_STRUCT_ONLY_ASSERT_VALID(other)
      p_nd = p_next_nd;
    }
  while (p_nd != base_type::m_p_head);

  base_type::split_finish(other);
  PB_DS_ASSERT_VALID((*this))
}

PB_DS_CLASS_T_DEC
void
PB_DS_CLASS_C_DEC::
split_at_node(node_pointer p_nd, PB_DS_CLASS_C_DEC& other)
{
  _GLIBCXX_DEBUG_ASSERT(p_nd != 0);

  node_pointer p_l = p_nd->m_p_left;
  node_pointer p_r = p_nd->m_p_right;
  node_pointer p_parent = p_nd->m_p_parent;
  if (p_parent == base_type::m_p_head)
    {
      base_type::m_p_head->m_p_parent = p_l;
      if (p_l != 0)
        {
	  p_l->m_p_parent = base_type::m_p_head;
	  p_l->m_red = false;
        }
    }
  else
    {
      if (p_parent->m_p_left == p_nd)
	p_parent->m_p_left = p_l;
      else
	p_parent->m_p_right = p_l;

      if (p_l != 0)
	p_l->m_p_parent = p_parent;

      this->update_to_top(p_parent, (node_update* )this);

      if (!p_nd->m_red)
	remove_fixup(p_l, p_parent);
    }

  base_type::initialize_min_max();
  other.join_imp(p_nd, p_r);
  PB_DS_STRUCT_ONLY_ASSERT_VALID((*this))
  PB_DS_STRUCT_ONLY_ASSERT_VALID(other)
}

