--- /dev/null
+// Splay tree utilities -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC 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.
+//
+// GCC 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#define INCLUDE_ALGORITHM
+#define INCLUDE_ARRAY
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "pretty-print.h"
+#include "splay-tree-utils.h"
+#include "selftest.h"
+
+#if CHECKING_P
+namespace {
+// A simple test node for rootless_splay_tree.
+struct rootless_test_node
+{
+ int data;
+ rootless_test_node *m_parent;
+ rootless_test_node *m_children[2];
+};
+}
+
+namespace selftest {
+
+// Random input data.
+static const size_t MAX_DATA = 32768;
+static const int data[] = {
+ 1379, 14643, 30579, 28160, 31750, 22280, 5502, 4720, 30075, 27595,
+ 8395, 19410, 518, 19709, 29694, 19865, 25372, 11752, 15485, 21547,
+ 25153, 25072, 10146, 3341, 15625, 3038, 10189, 19943, 1322, 11762,
+ 807, 430, 11284, 11841, 23965, 32008, 4547, 8087, 13225, 23054,
+ 22284, 13756, 2182, 26450, 30482, 32502, 23348, 20265, 29509, 3290,
+ 10807, 1242, 3212, 32178, 25354, 22032, 30509, 16157, 22432, 1295,
+ 8348, 23342, 24678, 193, 31016, 10316, 3872, 13521, 19211, 30594,
+ 12229, 4794, 25083, 16098, 28144, 27896, 4801, 20689, 31450, 15614,
+ 19597, 13731, 30309, 24846, 11042, 31929, 18306, 28520, 16907, 12488,
+ 15001, 18487, 3438, 1706, 4829, 20892, 6226, 18204, 15776, 30717,
+ 19398, 2480, 19434, 2838, 2605, 3994, 22538, 12269, 6486, 1314,
+ 30301, 9919, 31405, 30847, 25000, 24013, 22196, 30220, 31415, 14630,
+ 26319, 4880, 21292, 20217, 20078, 14679, 25686, 28675, 13883, 14853,
+ 2872, 2428, 3636, 14131, 2952, 2133, 4470, 25808, 12576, 31395,
+ 5938, 28393, 14553, 4494, 14928, 24310, 17394, 17436, 23385, 22792,
+ 9785, 13118, 22338, 23320, 27059, 17663, 16434, 14954, 16962, 31088,
+ 22247, 22600, 7980, 1344, 15635, 13611, 32739, 3283, 12924, 17904,
+ 28216, 7542, 9212, 28308, 18873, 3912, 5473, 4666, 11900, 21420,
+ 20072, 27662, 16445, 29848, 24444, 31668, 30664, 14287, 13754, 29276,
+ 21462, 25517, 17632, 8105, 32510, 16677, 11162, 20734, 26873, 5097
+};
+
+// Look up VALUE in TREE using the single-comparator lookup function.
+static int
+lookup1 (splay_tree<int> &tree, int value)
+{
+ auto compare = [&](splay_tree_node<int> *node)
+ {
+ return value - node->value ();
+ };
+ return tree.lookup (compare);
+}
+
+// Look up VALUE in TREE using the double-comparator lookup function.
+static int
+lookup2 (splay_tree<int> &tree, int value)
+{
+ auto want_something_smaller = [&](splay_tree_node<int> *node)
+ {
+ return value < node->value ();
+ };
+ auto want_something_bigger = [&](splay_tree_node<int> *node)
+ {
+ return value > node->value ();
+ };
+ return tree.lookup (want_something_smaller, want_something_bigger);
+}
+
+// Test printing TREE to a pretty printer. Don't check the output against
+// anything; just make sure that it doesn't crash.
+static void
+test_print (splay_tree<int> &tree)
+{
+ auto print_node = [](pretty_printer *pp, splay_tree_node<int> *node)
+ {
+ pp_decimal_int (pp, node->value ());
+ };
+ pretty_printer pp;
+ tree.print (&pp, print_node);
+}
+
+// Test various lookups on TREE using LOOKUP, where lookup returns the
+// same kind of value as the rooted_splay_tree lookup functions.
+static void
+test_lookup (splay_tree<int> &tree, int (*lookup) (splay_tree<int> &, int))
+{
+ // Look up values that are known to exist.
+ for (int value : data)
+ ASSERT_EQ (lookup (tree, value), 0);
+
+ // Look up values that are 1 less than values that are known to exist.
+ for (int value : data)
+ {
+ int result = lookup (tree, value - 1);
+ if (result == 0)
+ ASSERT_EQ (tree->value (), value - 1);
+ else if (result < 0)
+ // VALUE - 1 is less than the root.
+ ASSERT_EQ (tree->value (), value);
+ else if (result > 0)
+ {
+ // VALUE - 1 is greater than the root.
+ ASSERT_TRUE (tree->value () < value - 1);
+ if (tree.splay_next_node ())
+ ASSERT_EQ (tree->value (), value);
+ }
+ }
+
+ // Look up values that are 1 greater than values that are known to exist.
+ for (int value : data)
+ {
+ int result = lookup (tree, value + 1);
+ if (result == 0)
+ ASSERT_EQ (tree->value (), value + 1);
+ else if (result < 0)
+ {
+ // VALUE + 1 is less than the root.
+ ASSERT_TRUE (tree->value () > value + 1);
+ if (tree.splay_prev_node ())
+ ASSERT_EQ (tree->value (), value);
+ }
+ else if (result > 0)
+ // VALUE + 1 is greater than the root.
+ ASSERT_EQ (tree->value (), value);
+ }
+}
+
+// Run all tests for this module.
+void
+splay_tree_cc_tests ()
+{
+ obstack ob;
+ gcc_obstack_init (&ob);
+
+ // Build up the splay tree.
+ splay_tree<int> tree;
+ for (int value : data)
+ {
+ auto *node = XOBNEW (&ob, splay_tree_node<int>);
+ new (node) splay_tree_node<int> (value);
+ auto compare = [&](splay_tree_node<int> *other_node)
+ {
+ return value - other_node->value ();
+ };
+ bool inserted = tree.insert (node, compare);
+ ASSERT_TRUE (inserted);
+ }
+
+ // Test the single-comparator lookup function.
+ test_lookup (tree, lookup1);
+
+ // Sort the input data.
+ std::array<int, ARRAY_SIZE (data)> sorted;
+ std::copy (data, data + ARRAY_SIZE (data), sorted.begin ());
+ std::sort (sorted.begin (), sorted.end ());
+
+ // Iterate over the tree in ascending order.
+ tree.splay_min_node ();
+ bool result = true;
+ for (int value : sorted)
+ {
+ ASSERT_TRUE (result);
+ ASSERT_EQ (tree->value (), value);
+ result = tree.splay_next_node ();
+ }
+ ASSERT_FALSE (result);
+ ASSERT_EQ (tree.min_node ()->value (), sorted.front ());
+
+ // Test the double-comparator lookup function.
+ test_lookup (tree, lookup2);
+
+ // Test printing the tree now, while it's still bushy.
+ test_print (tree);
+
+ // Iterate over the tree in descending order.
+ tree.splay_max_node ();
+ result = true;
+ for (auto it = sorted.rbegin (); it != sorted.rend (); ++it)
+ {
+ ASSERT_TRUE (result);
+ ASSERT_EQ (tree->value (), *it);
+ result = tree.splay_prev_node ();
+ }
+ ASSERT_FALSE (result);
+ ASSERT_EQ (tree.max_node ()->value (), sorted.back ());
+
+ // Try splitting the tree into three.
+ int mid_min = sorted[sorted.size () / 3];
+ int mid_max = sorted[sorted.size () * 2 / 3];
+ ASSERT_EQ (lookup1 (tree, mid_min), 0);
+ splay_tree<int> left = tree.split_before_root ();
+ ASSERT_EQ (lookup1 (tree, mid_max), 0);
+ splay_tree<int> right = tree.split_after_root ();
+
+ // Test removing all the nodes from their respective trees.
+ for (int value : data)
+ {
+ splay_tree<int> &t = (value < mid_min ? left
+ : value > mid_max ? right : tree);
+ ASSERT_EQ (lookup1 (t, value), 0);
+ t.remove_root ();
+ }
+ ASSERT_EQ (left.root (), nullptr);
+ ASSERT_EQ (tree.root (), nullptr);
+ ASSERT_EQ (right.root (), nullptr);
+
+ using rootless = default_rootless_splay_tree<rootless_test_node *>;
+
+ // Build a tree in ascending order with the lowest element as the root.
+ auto *nodes = XOBNEWVEC (&ob, rootless_test_node *, MAX_DATA);
+ rootless_test_node *parent = nullptr;
+ for (int data : sorted)
+ {
+ auto *node = XOBNEW (&ob, rootless_test_node);
+ new (node) rootless_test_node ();
+ node->data = data;
+ nodes[data] = node;
+ if (parent)
+ rootless::insert_child (parent, 1, node);
+ parent = node;
+ }
+
+ // Try comparing nodes to make sure that their order matches the data.
+ for (size_t i = 1; i < ARRAY_SIZE (data); ++i)
+ {
+ int data1 = data[i - 1];
+ int data2 = data[i];
+ int comparison = rootless::compare_nodes (nodes[data1], nodes[data2]);
+ if (data1 < data2)
+ ASSERT_TRUE (comparison < 0);
+ else if (data1 > data2)
+ ASSERT_TRUE (comparison > 0);
+ else
+ ASSERT_EQ (comparison, 0);
+ }
+
+ obstack_free (&ob, nullptr);
+}
+}
+#endif // CHECKING_P
--- /dev/null
+// Splay tree utilities -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC 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.
+//
+// GCC 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Implement splay tree node accessors for a class that stores its
+// two child nodes in a member variable of the form:
+//
+// Node m_children[2];
+template<typename Node>
+class default_splay_tree_accessors
+{
+public:
+ using node_type = Node;
+
+ static auto
+ child (node_type node, unsigned int index)
+ -> decltype (node->m_children[index]) &
+ {
+ return node->m_children[index];
+ }
+};
+
+// Implement splay tree node accessors for a class that stores its
+// two child nodes in a member variable of the form:
+//
+// Node m_children[2];
+//
+// and also stores its parent node in a member variable of the form:
+//
+// Node m_parent;
+template<typename Node>
+class default_splay_tree_accessors_with_parent
+ : public default_splay_tree_accessors<Node>
+{
+public:
+ using node_type = Node;
+
+ static auto
+ parent (node_type node) -> decltype (node->m_parent) &
+ {
+ return node->m_parent;
+ }
+};
+
+// Base is a splay tree accessor class for nodes that have no parent field.
+// Base therefore provides a Base::child method but does not provide a
+// Base::parent method. Extend Base with dummy routines for setting the
+// parent, which is a no-op when the parent is not stored.
+template<typename Base>
+class splay_tree_accessors_without_parent : public Base
+{
+public:
+ using typename Base::node_type;
+
+ static void set_parent (node_type, node_type) {}
+};
+
+// Base is splay tree accessor class for nodes that have a parent field.
+// Base therefore provides both Base::child and Base::parent methods.
+// Extend Base with routines for setting the parent.
+template<typename Base>
+class splay_tree_accessors_with_parent : public Base
+{
+public:
+ using typename Base::node_type;
+
+ // Record that NODE's parent is now NEW_PARENT.
+ static void
+ set_parent (node_type node, node_type new_parent)
+ {
+ Base::parent (node) = new_parent;
+ }
+};
+
+// A base class that provides some splay tree operations that are common
+// to both rooted_splay_tree and rootless_splay_tree.
+//
+// Nodes in the splay tree have type Accessors::node_type; this is
+// usually a pointer type. The Accessors class provides the following
+// static member functions for accessing nodes:
+//
+// - Accessors::child (NODE, INDEX)
+// INDEX is guaranteed to be 0 or 1. If INDEX is 0, return a reference
+// to where NODE's left child is stored, otherwise return a reference
+// to where NODE's right child is stored.
+//
+// - Accessors::set_parent (NODE, PARENT)
+// Record that NODE's parent node is now PARENT.
+template<typename Accessors>
+class base_splay_tree : protected Accessors
+{
+public:
+ using typename Accessors::node_type;
+
+ // INDEX is either 0 or 1. If INDEX is 0, insert CHILD immediately
+ // before NODE, otherwise insert CHILD immediately after NODE.
+ //
+ // Complexity: O(1).
+ static void insert_child (node_type node, unsigned int index,
+ node_type child);
+
+ // Print NODE and its child nodes to PP for debugging purposes,
+ // using PRINTER (PP, N) to print the data for node N.
+ template<typename Printer>
+ static void print (pretty_printer *pp, node_type node, Printer printer);
+
+protected:
+ using Accessors::set_parent;
+
+ static node_type get_child (node_type, unsigned int);
+ static void set_child (node_type, unsigned int, node_type);
+ static node_type promote_child (node_type, unsigned int);
+ static void promote_child (node_type, unsigned int, node_type);
+
+ template<unsigned int N>
+ static node_type splay_limit (node_type);
+
+ static node_type remove_node_internal (node_type);
+
+ template<typename Printer>
+ static void print (pretty_printer *pp, node_type node, Printer printer,
+ char, vec<char> &);
+};
+
+// This class provides splay tree routines for cases in which the root
+// of the splay tree is known. It works with both nodes that store
+// their parent node and nodes that don't.
+//
+// The class is lightweight: it only contains a single root node.
+template<typename Accessors>
+class rooted_splay_tree : public base_splay_tree<Accessors>
+{
+ using parent = base_splay_tree<Accessors>;
+
+public:
+ using typename Accessors::node_type;
+
+protected:
+ // The root of the splay tree, or node_type () if the tree is empty.
+ node_type m_root;
+
+public:
+ rooted_splay_tree () : m_root () {}
+
+ // Construct a tree with the specified root node.
+ rooted_splay_tree (node_type root) : m_root (root) {}
+
+ // Return the root of the tree.
+ node_type root () const { return m_root; }
+
+ // Return true if the tree contains any nodes.
+ explicit operator bool () const { return m_root; }
+
+ // Dereference the root node.
+ node_type operator-> () { return m_root; }
+
+ // Insert NEW_NODE into the splay tree, if no equivalent node already
+ // exists. For a given node N, COMPARE (N) should return:
+ //
+ // - a negative value if NEW_NODE should come before N
+ // - zero if NEW_NODE and N are the same
+ // - a positive value if NEW_NODE should come after N
+ //
+ // Return true if NEW_NODE was inserted.
+ //
+ // On return, NEW_NODE or its equivalent is the root of the tree.
+ //
+ // Complexity: amortized O(C log N), worst-cast O(C N), where C is
+ // the complexity of the comparison.
+ template<typename Comparator>
+ bool insert (node_type new_node, Comparator compare);
+
+ // Insert NEW_NODE into the splay tree, given that NEW_NODE is the
+ // maximum node of the new tree. On return, NEW_NODE is also the
+ // root of the tree.
+ //
+ // Complexity: O(1).
+ void insert_max_node (node_type new_node);
+
+ // Splice NEXT_TREE onto this one, given that all nodes in NEXT_TREE
+ // are greater than the maximum node in this tree. NEXT_TREE should
+ // not be used afterwards.
+ //
+ // Complexity: O(1) if the root of the splay tree is already the maximum
+ // node. Otherwise amortized O(log N), worst-cast O(N).
+ void splice_next_tree (rooted_splay_tree next_tree);
+
+ // The root of the tree is currently the maximum node. Replace it
+ // with NEW_NODE.
+ //
+ // Complexity: O(1).
+ void replace_max_node_at_root (node_type new_node);
+
+ // Remove the root node of the splay tree.
+ //
+ // Complexity: O(1) if removing the maximum or minimum node.
+ // Otherwise amortized O(log N), worst-cast O(N).
+ void remove_root ();
+
+ // Split the left child of the current root out into a separate tree
+ // and return the new tree.
+ rooted_splay_tree split_before_root ();
+
+ // Split the right child of the current root out into a separate tree
+ // and return the new tree.
+ rooted_splay_tree split_after_root ();
+
+ // If the root is not the minimum node of the splay tree, bring the previous
+ // node to the root and return true, otherwise return false.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ bool splay_prev_node ();
+
+ // If the root is not the maximum node of the splay tree, bring the next
+ // node to the root and return true, otherwise return false.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ bool splay_next_node ();
+
+ // Bring the minimum node of the splay tree to the root.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ void splay_min_node ();
+
+ // Bring the maximum node of the splay tree to the root.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ void splay_max_node ();
+
+ // Return the minimum node of the splay tree, or node_type () if the
+ // tree is empty. On return, the minimum node (if any) is also the
+ // root of the tree.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ node_type min_node ();
+
+ // Return the maximum node of the splay tree, or node_type () if the
+ // tree is empty. On return, the maximum node (if any) is also the
+ // root of the tree.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ node_type max_node ();
+
+ // Search the splay tree. For a given node N, COMPARE (N) should return:
+ //
+ // - a negative value if N is bigger than the node being searched for
+ // - zero if N is the node being searched for
+ // - a positive value if N is smaller than the node being searched for
+ //
+ // If the node that COMPARE is looking for exists, install it as the root
+ // node of the splay tree. Otherwise, arbitrarily pick either:
+ //
+ // - the maximum node that is smaller than the node being searched for or
+ // - the minimum node that is bigger than the node being searched for
+ //
+ // and install that node as the root instead.
+ //
+ // Return the result of COMPARE for the new root.
+ //
+ // This form of lookup is intended for cases in which both the following
+ // are true:
+ //
+ // (a) The work that COMPARE needs to do to detect if a node is too big
+ // is the same as the work that COMPARE needs to do to detect if a
+ // node is too small. (This is not true of range comparisons,
+ // for example.)
+ //
+ // (b) COMPARE is (or might be) relatively complex.
+ //
+ // This form of lookup is also useful if the items being compared naturally
+ // provide a <=>-style comparison result, without the result having to be
+ // forced by the equivalent of a ?: expression.
+ //
+ // The implementation only invokes COMPARE once per node.
+ //
+ // Complexity: amortized O(C log N), worst-cast O(C N), where C is
+ // the complexity of the comparison.
+ template<typename Comparator>
+ auto lookup (Comparator compare) -> decltype (compare (m_root));
+
+ // Search the splay tree. For a given node N, WANT_SOMETHING_SMALLER (N)
+ // is true if N is too big and WANT_SOMETHING_BIGGER (N) is true if N
+ // is too small. Both functions return false if N is the node being
+ // searched for.
+ //
+ // If the node that is being searched for exists, install it as the root
+ // node of the splay tree and return 0. Otherwise, arbitrarily choose
+ // between these two options:
+ //
+ // - Install the maximum node that is smaller than the node being
+ // searched for as the root of the splay tree and return 1.
+ //
+ // - Install the minimum node that is bigger than the node being
+ // searched for and return -1.
+ //
+ // This form of lookup is intended for cases in which either of the
+ // following are true:
+ //
+ // (a) WANT_SOMETHING_SMALLER and WANT_SOMETHING_BIGGER test different
+ // parts of the node's data. For example, when comparing ranges,
+ // WANT_SOMETHING_SMALLER would test the lower limit of the given
+ // node's range while WANT_SOMETHING_BIGGER would test the upper
+ // limit of the given node's range.
+ //
+ // (b) There is no significant overhead to calling both
+ // WANT_SOMETHING_SMALLER and WANT_SOMETHING_BIGGER for the same node.
+ //
+ // Complexity: amortized O(C log N), worst-cast O(C N), where C is
+ // the complexity of the comparisons.
+ template<typename LeftPredicate, typename RightPredicate>
+ int lookup (LeftPredicate want_something_smaller,
+ RightPredicate want_something_bigger);
+
+ // Keep the ability to print subtrees.
+ using parent::print;
+
+ // Print the tree to PP for debugging purposes, using PRINTER (PP, N)
+ // to print the data for node N.
+ template<typename Printer>
+ void print (pretty_printer *pp, Printer printer) const;
+
+protected:
+ using parent::get_child;
+ using parent::set_child;
+ using parent::promote_child;
+
+ using parent::set_parent;
+
+ template<unsigned int N>
+ bool splay_neighbor ();
+};
+
+// Provide splay tree routines for nodes of type Accessors::node_type,
+// which doesn't have a parent field. Use Accessors::child to access
+// the children of a node.
+template<typename Accessors>
+using splay_tree_without_parent
+ = rooted_splay_tree<splay_tree_accessors_without_parent<Accessors>>;
+
+// A splay tree for nodes of type Node, which is usually a pointer type.
+// The child nodes are stored in a member variable:
+//
+// Node m_children[2];
+//
+// Node does not have a parent field.
+template<typename Node>
+using default_splay_tree
+ = splay_tree_without_parent<default_splay_tree_accessors<Node>>;
+
+// A simple splay tree node that stores a value of type T.
+template<typename T>
+class splay_tree_node
+{
+ friend class default_splay_tree_accessors<splay_tree_node *>;
+
+public:
+ splay_tree_node () = default;
+ splay_tree_node (T value) : m_value (value), m_children () {}
+
+ T &value () { return m_value; }
+ const T &value () const { return m_value; }
+
+private:
+ T m_value;
+ splay_tree_node *m_children[2];
+};
+
+// A splay tree whose nodes hold values of type T.
+template<typename T>
+using splay_tree = default_splay_tree<splay_tree_node<T> *>;
+
+// Provide splay tree routines for cases in which the root of the tree
+// is not explicitly stored.
+//
+// The nodes of the tree have type Accessors::node_type, which is usually
+// a pointer type. The nodes have a link back to their parent.
+//
+// The Accessors class provides the following static member functions:
+//
+// - Accessors::child (NODE, INDEX)
+// INDEX is guaranteed to be 0 or 1. If INDEX is 0, return a reference
+// to where NODE's left child is stored, otherwise return a reference
+// to where NODE's right child is stored.
+//
+// - Accessors::parent (NODE)
+// Return a reference to where NODE's parent is stored.
+template<typename Accessors>
+class rootless_splay_tree
+ : public base_splay_tree<splay_tree_accessors_with_parent<Accessors>>
+{
+ using full_accessors = splay_tree_accessors_with_parent<Accessors>;
+ using parent = base_splay_tree<full_accessors>;
+
+public:
+ using rooted = rooted_splay_tree<full_accessors>;
+
+ using typename Accessors::node_type;
+
+ // Remove NODE from the splay tree. Return the node that replaces it,
+ // or null if NODE had no children.
+ //
+ // Complexity: O(1) if removing the maximum or minimum node.
+ // Otherwise amortized O(log N), worst-cast O(N).
+ static node_type remove_node (node_type node);
+
+ // Splay NODE so that it becomes the root of the splay tree.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ static void splay (node_type node);
+
+ // Like splay, but take advantage of the fact that NODE is known to be
+ // the minimum node in the tree.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ static void splay_known_min_node (node_type node);
+
+ // Like splay, but take advantage of the fact that NODE is known to be
+ // the maximum node in the tree.
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ static void splay_known_max_node (node_type node);
+
+ // Splay NODE while looking for an ancestor node N for which PREDICATE (N)
+ // is true. If such an ancestor node exists, stop the splay operation
+ // early and return PREDICATE (N). Otherwise, complete the splay operation
+ // and return DEFAULT_RESULT. In the latter case, NODE is now the root of
+ // the splay tree.
+ //
+ // Note that this routine only examines nodes that happen to be ancestors
+ // of NODE. It does not search the full tree.
+ //
+ // Complexity: amortized O(P log N), worst-cast O(P N), where P is the
+ // complexity of the predicate.
+ template<typename DefaultResult, typename Predicate>
+ static auto splay_and_search (node_type node, DefaultResult default_result,
+ Predicate predicate)
+ -> decltype (predicate (node, 0));
+
+ // NODE1 and NODE2 are known to belong to the same splay tree. Return:
+ //
+ // -1 if NODE1 < NODE2
+ // 0 if NODE1 == NODE2
+ // 1 if NODE1 > NODE2
+ //
+ // Complexity: amortized O(log N), worst-cast O(N).
+ static int compare_nodes (node_type node1, node_type node2);
+
+protected:
+ using parent::get_child;
+ using parent::set_child;
+ using parent::promote_child;
+
+ static node_type get_parent (node_type);
+ using parent::set_parent;
+
+ static unsigned int child_index (node_type, node_type);
+
+ static int compare_nodes_one_way (node_type, node_type);
+
+ template<unsigned int N>
+ static void splay_known_limit (node_type);
+};
+
+// Provide rootless splay tree routines for nodes of type Node.
+// The child nodes are stored in a member variable:
+//
+// Node m_children[2];
+//
+// and the parent node is stored in a member variable:
+//
+// Node m_parent;
+template<typename Node>
+using default_rootless_splay_tree
+ = rootless_splay_tree<default_splay_tree_accessors_with_parent<Node>>;
+
+#include "splay-tree-utils.tcc"
--- /dev/null
+// Splay tree utilities -*- C++ -*-
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of GCC.
+//
+// GCC 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.
+//
+// GCC 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.
+//
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// INDEX is either 0 or 1. If it is 0, return NODE's left child,
+// otherwise return NODE's right child.
+template<typename Accessors>
+inline typename base_splay_tree<Accessors>::node_type
+base_splay_tree<Accessors>::get_child (node_type node, unsigned int index)
+{
+ return Accessors::child (node, index);
+}
+
+// INDEX is either 0 or 1. If it is 0, change NODE's left child to CHILD,
+// otherwise change NODE's right child to CHILD. If CHILD has a parent
+// field, record that its parent is now NODE.
+template<typename Accessors>
+inline void
+base_splay_tree<Accessors>::set_child (node_type node, unsigned int index,
+ node_type child)
+{
+ Accessors::child (node, index) = child;
+ if (child)
+ set_parent (child, node);
+}
+
+// Rotate the tree to promote child number INDEX of NODE, so that that
+// child becomes a parent of NODE. Return the promoted node.
+//
+// The caller has the responsibility of assigning a correct parent
+// to the returned node.
+template<typename Accessors>
+inline typename base_splay_tree<Accessors>::node_type
+base_splay_tree<Accessors>::promote_child (node_type node, unsigned int index)
+{
+ node_type promoted = get_child (node, index);
+ set_child (node, index, get_child (promoted, 1 - index));
+ set_child (promoted, 1 - index, node);
+ return promoted;
+}
+
+// Treat child number INDEX of NODE as being CHILD and rotate the tree
+// so that CHILD becomes a parent of NODE.
+//
+// The caller has the responsibility of assigning a correct parent to CHILD.
+template<typename Accessors>
+inline void
+base_splay_tree<Accessors>::promote_child (node_type node, unsigned int index,
+ node_type child)
+{
+ set_child (node, index, get_child (child, 1 - index));
+ set_child (child, 1 - index, node);
+}
+
+// Print NODE to PP, using PRINTER (PP, N) to print the contents of node N.
+// Prefix each new line with INDENT_STRING. CODE is 'T' if NODE is the root
+// node, 'L' if NODE is the left child of its parent, or 'R' if NODE is the
+// right child of its parent.
+template<typename Accessors>
+template<typename Printer>
+void
+base_splay_tree<Accessors>::print (pretty_printer *pp, node_type node,
+ Printer printer, char code,
+ vec<char> &indent_string)
+{
+ // In the comments below, PREFIX refers to the incoming contents
+ // of INDENT_STRING.
+ node_type left = get_child (node, 0);
+ node_type right = get_child (node, 1);
+
+ auto orig_indent_len = indent_string.length ();
+ indent_string.safe_grow (orig_indent_len + 3);
+ char *extra_indent = indent_string.address () + orig_indent_len;
+
+ // Print [T], [L], or [R].
+ extra_indent[0] = '[';
+ extra_indent[1] = code;
+ extra_indent[2] = ']';
+ pp_append_text (pp, extra_indent, indent_string.end ());
+ pp_space (pp);
+
+ // Print the node itself, using PREFIX + " | " or PREFIX + " " to indent
+ // new lines under the "[_]" that we just printed.
+ extra_indent[0] = ' ';
+ extra_indent[1] = (left || right ? '|' : ' ');
+ extra_indent[2] = ' ';
+ {
+ pretty_printer sub_pp;
+ printer (&sub_pp, node);
+ const char *text = pp_formatted_text (&sub_pp);
+ while (const char *end = strchr (text, '\n'))
+ {
+ pp_append_text (pp, text, end);
+ pp_newline_and_indent (pp, 0);
+ pp_append_text (pp, indent_string.begin (), indent_string.end ());
+ text = end + 1;
+ }
+ pp_string (pp, text);
+ }
+
+ if (left)
+ {
+ // Print PREFIX + " +-" for the first line of the left subtree,
+ // to be followed by "[L]".
+ extra_indent[1] = '+';
+ extra_indent[2] = '-';
+ pp_newline_and_indent (pp, 0);
+ pp_append_text (pp, indent_string.begin (), indent_string.end ());
+
+ // Print the left subtree, using PREFIX + " | " or PREFIX + " "
+ // to indent under the PREFIX + " +-" that we just printed.
+ extra_indent[1] = right ? '|' : ' ';
+ extra_indent[2] = ' ';
+ print (pp, left, printer, 'L', indent_string);
+ extra_indent = indent_string.address () + orig_indent_len;
+
+ // If LEFT is not a leaf and we also have a right subtree, use a
+ // PREFIX + " |" line to separate them.
+ if (right && (get_child (left, 0) || get_child (left, 1)))
+ {
+ pp_newline_and_indent (pp, 0);
+ pp_append_text (pp, indent_string.begin (), &extra_indent[2]);
+ }
+ }
+ if (right)
+ {
+ // Print PREFIX + " +-" for the first line of the right subtree,
+ // to be followed by "[R]".
+ extra_indent[1] = '+';
+ extra_indent[2] = '-';
+ pp_newline_and_indent (pp, 0);
+ pp_append_text (pp, indent_string.begin (), indent_string.end ());
+
+ // Print the right subtree, using PREFIX + " " to indent under the
+ // PREFIX + " +-" that we just printed.
+ extra_indent[1] = ' ';
+ extra_indent[2] = ' ';
+ print (pp, right, printer, 'R', indent_string);
+ }
+ indent_string.truncate (orig_indent_len);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename Printer>
+void
+base_splay_tree<Accessors>::print (pretty_printer *pp, node_type node,
+ Printer printer)
+{
+ if (!node)
+ {
+ pp_string (pp, "null");
+ return;
+ }
+ auto_vec<char, 64> indent_string;
+ print (pp, node, printer, 'T', indent_string);
+}
+
+// If N is 1, splay the last (rightmost) node reachable from START
+// to the position that START current holds and return the splayed node.
+// START is not itself the last node.
+//
+// If N is 0, splay the first (leftmost) node reachable from START
+// to the position that START current holds and return the splayed node.
+// START is not itself the first node.
+//
+// The caller has the responsibility of updating the parent of the
+// returned node.
+template<typename Accessors>
+template<unsigned int N>
+typename base_splay_tree<Accessors>::node_type
+base_splay_tree<Accessors>::splay_limit (node_type start)
+{
+ // This essentially follows the simpilfied top-down method described
+ // in Sleator and Tarjan's "Self-adjusting Binary Search Trees", but
+ // specialized for the case in which the comparison result is fixed.
+ // The first iteration is peeled to avoid the need for stack temporaries.
+ //
+ // The comments and names reflect the behavior for N == 1, but the
+ // N == 0 case behaves analogously.
+
+ // Rotate the tree to promote the right child of START to the root.
+ node_type node = promote_child (start, N);
+ if (node_type right = get_child (node, N))
+ {
+ // Perform the link left step, which for this first iteration
+ // means making NODE the root of the left tree.
+ //
+ // NODE will become left child of the final node. For a right
+ // spine starting at NODE of the form:
+ //
+ // 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> ... -> N
+ // | | | | | | | |
+ // V V V V V V V V
+ // A B C D E F G NL
+ //
+ // the next step is to create a subtree of N whose right spine contains
+ // the odd-numbered nodes, as follows:
+ //
+ // N
+ // |
+ // V
+ // 1 ------> 3 ------> 5 ------> 7 -> .... -> NL
+ // | | | |
+ // V V V V
+ // A 2 -> C 4 -> E 6 -> G
+ // | | |
+ // V V V
+ // B D F
+ //
+ // First record 1 as the left child of the final root (N) and move
+ // on to node 2.
+ node_type final_child = node;
+ node_type new_spine_end = node;
+ node = right;
+ while (node_type right = get_child (node, N))
+ {
+ // Perform another rotate left step.
+ //
+ // We've built the tree rooted at 1 in the diagram above up to,
+ // but not including, an even-numbered node NODE on the original
+ // right spine. Rotate the tree at NODE to promote the following
+ // odd-numbered node.
+ promote_child (node, N, right);
+ node = right;
+ if (node_type right = get_child (node, N))
+ {
+ // Perform another link left step.
+ //
+ // Add the promoted odd-numbered node to the right spine of the
+ // tree rooted at 1 and move on to the next even-numbered node.
+ set_child (new_spine_end, N, node);
+ new_spine_end = node;
+ node = right;
+ }
+ }
+ // Perform the assembly step.
+ //
+ // Add NL to the new spine and make N the new root.
+ set_child (new_spine_end, N, get_child (node, 1 - N));
+ set_child (node, 1 - N, final_child);
+ }
+ return node;
+}
+
+// Remove NODE from its position in the splay tree. If NODE has at least
+// one child node, return the node that should now hold NODE's position in
+// the splay tree. If NODE has no children, return null.
+//
+// The caller has the responsibility of updating the parent of the
+// returned node.
+template<typename Accessors>
+inline typename base_splay_tree<Accessors>::node_type
+base_splay_tree<Accessors>::remove_node_internal (node_type node)
+{
+ node_type left = get_child (node, 0);
+ node_type right = get_child (node, 1);
+ if (!left)
+ return right;
+
+ if (!right)
+ return left;
+
+ if (get_child (left, 1))
+ {
+ left = splay_limit<1> (left);
+ gcc_checking_assert (!get_child (left, 1));
+ }
+ set_child (left, 1, right);
+ return left;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+base_splay_tree<Accessors>::insert_child (node_type node, unsigned int index,
+ node_type child)
+{
+ gcc_checking_assert (!get_child (child, 0) && !get_child (child, 1));
+ set_child (child, index, get_child (node, index));
+ set_child (node, index, child);
+}
+
+// Implement splay_next_node if N == 1 and splay_prev_node if N == 0.
+template<typename Accessors>
+template<unsigned int N>
+bool
+rooted_splay_tree<Accessors>::splay_neighbor ()
+{
+ node_type node = m_root;
+ node_type new_root = get_child (node, N);
+ if (!new_root)
+ return false;
+
+ if (get_child (new_root, 1 - N))
+ {
+ // NEW_ROOT is not itself the required node, so splay the required
+ // node into its place.
+ new_root = parent::template splay_limit<1 - N> (new_root);
+ gcc_checking_assert (!get_child (new_root, 1 - N));
+ set_child (node, N, node_type ());
+ set_child (new_root, 1 - N, node);
+ }
+ else
+ promote_child (node, N, new_root);
+ set_parent (new_root, node_type ());
+ m_root = new_root;
+ return true;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename Comparator>
+bool
+rooted_splay_tree<Accessors>::insert (node_type new_node, Comparator compare)
+{
+ gcc_checking_assert (!get_child (new_node, 0) && !get_child (new_node, 1));
+ if (!m_root)
+ {
+ m_root = new_node;
+ return true;
+ }
+
+ int comparison = lookup (compare);
+ if (comparison == 0)
+ return false;
+
+ // Insert NEW_NODE before M_ROOT if COMPARISON < 0 and after M_ROOT
+ // otherwise.
+ set_child (new_node, comparison < 0, m_root);
+ set_child (new_node, comparison > 0, get_child (m_root, comparison > 0));
+ set_child (m_root, comparison > 0, nullptr);
+ m_root = new_node;
+ return true;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::insert_max_node (node_type new_node)
+{
+ gcc_checking_assert (!get_child (new_node, 0) && !get_child (new_node, 1));
+ set_child (new_node, 0, m_root);
+ m_root = new_node;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::splice_next_tree (rooted_splay_tree next_tree)
+{
+ splay_max_node ();
+ set_child (m_root, 1, next_tree.m_root);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::replace_max_node_at_root (node_type new_node)
+{
+ node_type old_node = m_root;
+ gcc_checking_assert (!get_child (new_node, 0)
+ && !get_child (new_node, 1)
+ && !get_child (old_node, 1));
+ set_child (new_node, 0, get_child (old_node, 0));
+ // Clear the links from OLD_NODE. Its parent and right child are
+ // already node_type ().
+ set_child (old_node, 0, node_type ());
+ m_root = new_node;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::remove_root ()
+{
+ node_type node = m_root;
+ m_root = parent::remove_node_internal (node);
+ if (m_root)
+ set_parent (m_root, node_type ());
+ // Clear the links from NODE. Its parent is already node_type ().
+ set_child (node, 0, node_type ());
+ set_child (node, 1, node_type ());
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline rooted_splay_tree<Accessors>
+rooted_splay_tree<Accessors>::split_before_root ()
+{
+ node_type new_root = get_child (m_root, 0);
+ set_child (m_root, 0, node_type ());
+ set_parent (new_root, node_type ());
+ return new_root;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline rooted_splay_tree<Accessors>
+rooted_splay_tree<Accessors>::split_after_root ()
+{
+ node_type new_root = get_child (m_root, 1);
+ set_child (m_root, 1, node_type ());
+ set_parent (new_root, node_type ());
+ return new_root;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline bool
+rooted_splay_tree<Accessors>::splay_prev_node ()
+{
+ return splay_neighbor<0> ();
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline bool
+rooted_splay_tree<Accessors>::splay_next_node ()
+{
+ return splay_neighbor<1> ();
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::splay_min_node ()
+{
+ if (m_root && get_child (m_root, 0))
+ {
+ m_root = parent::template splay_limit<0> (m_root);
+ set_parent (m_root, node_type ());
+ }
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rooted_splay_tree<Accessors>::splay_max_node ()
+{
+ if (m_root && get_child (m_root, 1))
+ {
+ m_root = parent::template splay_limit<1> (m_root);
+ set_parent (m_root, node_type ());
+ }
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline typename rooted_splay_tree<Accessors>::node_type
+rooted_splay_tree<Accessors>::min_node ()
+{
+ splay_min_node ();
+ return m_root;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline typename rooted_splay_tree<Accessors>::node_type
+rooted_splay_tree<Accessors>::max_node ()
+{
+ splay_max_node ();
+ return m_root;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename Comparator>
+auto
+rooted_splay_tree<Accessors>::lookup (Comparator compare)
+ -> decltype (compare (m_root))
+{
+ // This essentially follows the simpilfied top-down method described
+ // in Sleator and Tarjan's "Self-adjusting Binary Search Trees", but
+ // with the complication that the comparisons are done only once.
+ using result_type = decltype (compare (m_root));
+
+ // The roots of the left and right trees.
+ node_type link_left_root = node_type ();
+ node_type link_right_root = node_type ();
+
+ // Where to add new nodes to the left and right trees.
+ node_type *link_left_ptr = &link_left_root;
+ node_type *link_right_ptr = &link_right_root;
+
+ // The nodes that contain *LINK_LEFT_PTR and *LINK_RIGHT_PTR,
+ // once they no longer point to the roots above.
+ node_type link_left_parent = node_type ();
+ node_type link_right_parent = node_type ();
+
+ auto link_left = [&](node_type node)
+ {
+ *link_left_ptr = node;
+ link_left_ptr = &Accessors::child (node, 1);
+ set_parent (node, link_left_parent);
+ link_left_parent = node;
+ };
+
+ auto link_right = [&](node_type node)
+ {
+ *link_right_ptr = node;
+ link_right_ptr = &Accessors::child (node, 0);
+ set_parent (node, link_right_parent);
+ link_right_parent = node;
+ };
+
+ node_type node = m_root;
+ node_type parent = node_type ();
+ result_type result;
+ result_type old_result = 0;
+ while (1)
+ {
+ // OLD_RESULT is 0 if NODE is the root of the middle tree.
+ // Otherwise, PARENT is the root of the middle tree and OLD_RESULT
+ // is how it compared.
+ //
+ // Results are:
+ // < 0 if we want something smaller.
+ // = 0 if we found the right node.
+ // > 0 if we want something bigger.
+ result = compare (node);
+ if (old_result < 0)
+ {
+ if (result < 0)
+ {
+ // SEARCH < NODE < PARENT
+ //
+ // Promote NODE (rotate right).
+ promote_child (parent, 0, node);
+ node_type next = get_child (node, 0);
+ if (!next)
+ break;
+
+ link_right (node);
+
+ // NEXT is now the root of the middle tree.
+ node = next;
+ old_result = 0;
+ continue;
+ }
+
+ // SEARCH >= NODE, NODE < PARENT
+ link_right (parent);
+ }
+ else if (old_result > 0)
+ {
+ if (result > 0)
+ {
+ // SEARCH > NODE > PARENT
+ //
+ // Promote NODE (rotate left).
+ promote_child (parent, 1, node);
+ node_type next = get_child (node, 1);
+ if (!next)
+ break;
+
+ link_left (node);
+
+ // NEXT is now the root of the middle tree.
+ node = next;
+ old_result = 0;
+ continue;
+ }
+
+ // SEARCH <= NODE, NODE > PARENT
+ link_left (parent);
+ }
+
+ // Microoptimization to allow NODE to be read even if RESULT == 0.
+ node_type next = get_child (node, result >= 0);
+ if (result == 0 || !next)
+ break;
+
+ // NODE is now the root of the tree.
+ parent = node;
+ node = next;
+ old_result = result;
+ }
+
+ node_type new_left = link_left_root;
+ node_type new_right = link_right_root;
+
+ if (new_left)
+ {
+ node_type old_left = get_child (node, 0);
+ *link_left_ptr = old_left;
+ if (old_left)
+ set_parent (old_left, link_left_parent);
+ set_child (node, 0, new_left);
+ }
+
+ if (new_right)
+ {
+ node_type old_right = get_child (node, 1);
+ *link_right_ptr = old_right;
+ if (old_right)
+ set_parent (old_right, link_right_parent);
+ set_child (node, 1, new_right);
+ }
+
+ set_parent (node, node_type ());
+ m_root = node;
+ return result;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename LeftPredicate, typename RightPredicate>
+int
+rooted_splay_tree<Accessors>::lookup (LeftPredicate want_something_smaller,
+ RightPredicate want_something_bigger)
+{
+ // This essentially follows the simpilfied top-down method described
+ // in Sleator and Tarjan's "Self-adjusting Binary Search Trees"
+ // (and follows it more closely than the single-comparator version above).
+
+ // The roots of the left and right trees.
+ node_type link_left_root = node_type ();
+ node_type link_right_root = node_type ();
+
+ // Where to add new nodes to the left and right trees.
+ node_type *link_left_ptr = &link_left_root;
+ node_type *link_right_ptr = &link_right_root;
+
+ // The nodes that contain *LINK_LEFT_PTR and *LINK_RIGHT_PTR,
+ // once they no longer point to the roots above.
+ node_type link_left_parent = node_type ();
+ node_type link_right_parent = node_type ();
+
+ node_type node = m_root;
+ int result;
+ for (;;)
+ {
+ // NODE is the root of the middle tree.
+ if (want_something_smaller (node))
+ {
+ result = -1;
+ node_type next = get_child (node, 0);
+ if (!next)
+ break;
+
+ if (want_something_smaller (next))
+ {
+ // Promote NODE (rotate right).
+ promote_child (node, 0, next);
+ node = next;
+ next = get_child (node, 0);
+ if (!next)
+ break;
+ }
+
+ // Add NODE to the right tree (link right).
+ *link_right_ptr = node;
+ link_right_ptr = &Accessors::child (node, 0);
+ set_parent (node, link_right_parent);
+ link_right_parent = node;
+
+ node = next;
+ }
+ else if (want_something_bigger (node))
+ {
+ result = 1;
+ node_type next = get_child (node, 1);
+ if (!next)
+ break;
+
+ if (want_something_bigger (next))
+ {
+ // Promote NODE (rotate left).
+ promote_child (node, 1, next);
+ node = next;
+ next = get_child (node, 1);
+ if (!next)
+ break;
+ }
+
+ // Add NODE to the left tree (link left).
+ *link_left_ptr = node;
+ link_left_ptr = &Accessors::child (node, 1);
+ set_parent (node, link_left_parent);
+ link_left_parent = node;
+
+ node = next;
+ }
+ else
+ {
+ result = 0;
+ break;
+ }
+ }
+
+ node_type new_left = link_left_root;
+ node_type new_right = link_right_root;
+
+ if (new_left)
+ {
+ node_type old_left = get_child (node, 0);
+ *link_left_ptr = old_left;
+ if (old_left)
+ set_parent (old_left, link_left_parent);
+ set_child (node, 0, new_left);
+ }
+
+ if (new_right)
+ {
+ node_type old_right = get_child (node, 1);
+ *link_right_ptr = old_right;
+ if (old_right)
+ set_parent (old_right, link_right_parent);
+ set_child (node, 1, new_right);
+ }
+
+ set_parent (node, node_type ());
+ m_root = node;
+ return result;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename Printer>
+inline void
+rooted_splay_tree<Accessors>::print (pretty_printer *pp, Printer printer) const
+{
+ print (pp, m_root, printer);
+}
+
+// Return NODE's current parent.
+template<typename Accessors>
+inline typename rootless_splay_tree<Accessors>::node_type
+rootless_splay_tree<Accessors>::get_parent (node_type node)
+{
+ return Accessors::parent (node);
+}
+
+// CHILD is known to be a child of PARENT. Return which index it has.
+template<typename Accessors>
+inline unsigned int
+rootless_splay_tree<Accessors>::child_index (node_type parent, node_type child)
+{
+ return get_child (parent, 1) == child;
+}
+
+// If N == 1, implement splay_known_max_node, otherwise implement
+// splay_known_min_node.
+template<typename Accessors>
+template<unsigned int N>
+inline void
+rootless_splay_tree<Accessors>::splay_known_limit (node_type node)
+{
+ node_type child = node;
+ node_type parent = get_parent (child);
+ if (!parent)
+ return;
+
+ do
+ // At this point, NODE conceptually replaces CHILD as a child of
+ // PARENT, but we haven't yet updated PARENT accordingly.
+ if (node_type grandparent = get_parent (parent))
+ {
+ node_type greatgrandparent = get_parent (grandparent);
+ promote_child (grandparent, N, parent);
+ promote_child (parent, N, node);
+ child = grandparent;
+ parent = greatgrandparent;
+ }
+ else
+ {
+ promote_child (parent, N, node);
+ break;
+ }
+ while (parent);
+ set_parent (node, node_type ());
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+typename rootless_splay_tree<Accessors>::node_type
+rootless_splay_tree<Accessors>::remove_node (node_type node)
+{
+ node_type replacement = parent::remove_node_internal (node);
+ if (node_type parent = get_parent (node))
+ set_child (parent, child_index (parent, node), replacement);
+ else if (replacement)
+ set_parent (replacement, node_type ());
+ // Clear the links from NODE.
+ set_parent (node, node_type ());
+ set_child (node, 0, node_type ());
+ set_child (node, 1, node_type ());
+ return replacement;
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+void
+rootless_splay_tree<Accessors>::splay (node_type node)
+{
+ node_type child = node;
+ node_type parent = get_parent (child);
+ if (!parent)
+ return;
+
+ do
+ {
+ // At this point, NODE conceptually replaces CHILD as a child of
+ // PARENT, but we haven't yet updated PARENT accordingly.
+ unsigned int index = child_index (parent, child);
+ if (node_type grandparent = get_parent (parent))
+ {
+ node_type greatgrandparent = get_parent (grandparent);
+ unsigned int parent_index = child_index (grandparent, parent);
+ if (index == parent_index)
+ {
+ promote_child (grandparent, parent_index, parent);
+ promote_child (parent, index, node);
+ }
+ else
+ {
+ promote_child (parent, index, node);
+ promote_child (grandparent, parent_index, node);
+ }
+ child = grandparent;
+ parent = greatgrandparent;
+ }
+ else
+ {
+ promote_child (parent, index, node);
+ break;
+ }
+ }
+ while (parent);
+ set_parent (node, node_type ());
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rootless_splay_tree<Accessors>::splay_known_min_node (node_type node)
+{
+ splay_known_limit<0> (node);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+inline void
+rootless_splay_tree<Accessors>::splay_known_max_node (node_type node)
+{
+ splay_known_limit<1> (node);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+template<typename DefaultResult, typename Predicate>
+auto
+rootless_splay_tree<Accessors>::
+splay_and_search (node_type node, DefaultResult default_result,
+ Predicate predicate)
+ -> decltype (predicate (node, 0))
+{
+ using Result = decltype (predicate (node, 0));
+
+ node_type child = node;
+ node_type parent = get_parent (child);
+ if (!parent)
+ return default_result;
+
+ do
+ {
+ // At this point, NODE conceptually replaces CHILD as a child of
+ // PARENT, but we haven't yet updated PARENT accordingly.
+ unsigned int index = child_index (parent, child);
+ if (Result result = predicate (parent, index))
+ {
+ set_child (parent, index, node);
+ return result;
+ }
+ if (node_type grandparent = get_parent (parent))
+ {
+ node_type greatgrandparent = get_parent (grandparent);
+ unsigned int parent_index = child_index (grandparent, parent);
+ if (Result result = predicate (grandparent, parent_index))
+ {
+ set_child (parent, index, node);
+ return result;
+ }
+ if (index == parent_index)
+ {
+ promote_child (grandparent, parent_index, parent);
+ promote_child (parent, index, node);
+ }
+ else
+ {
+ promote_child (parent, index, node);
+ promote_child (grandparent, parent_index, node);
+ }
+ child = grandparent;
+ parent = greatgrandparent;
+ }
+ else
+ {
+ promote_child (parent, index, node);
+ break;
+ }
+ }
+ while (parent);
+ set_parent (node, node_type ());
+ return default_result;
+}
+
+// Splay NODE1 looking to see if one of its ancestors is NODE2. If it is,
+// return -1 if NODE1 comes before NODE2 or 1 if NODE1 comes after NODE2.
+// Return 0 if NODE2 is not an ancestor of NODE1.
+template<typename Accessors>
+int
+rootless_splay_tree<Accessors>::compare_nodes_one_way (node_type node1,
+ node_type node2)
+{
+ auto compare = [&](node_type parent, unsigned int index) -> int
+ {
+ if (parent == node2)
+ return index ? 1 : -1;
+ return 0;
+ };
+ return splay_and_search (node1, 0, compare);
+}
+
+// See the comment above the declaration.
+template<typename Accessors>
+int
+rootless_splay_tree<Accessors>::compare_nodes (node_type node1,
+ node_type node2)
+{
+ if (node1 == node2)
+ return 0;
+
+ // Splay NODE1 looking for NODE2.
+ int cmp = compare_nodes_one_way (node1, node2);
+ if (cmp)
+ return cmp;
+
+ // That failed, but NODE1 is now the root of the tree. Splay NODE2
+ // to see on which side of NODE1 it falls.
+ cmp = compare_nodes_one_way (node2, node1);
+ gcc_checking_assert (cmp);
+ return -cmp;
+}