xref: /dflybsd-src/contrib/gcc-8.0/libgomp/splay-tree.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* A splay-tree datatype.
2*38fd1498Szrj    Copyright (C) 1998-2018 Free Software Foundation, Inc.
3*38fd1498Szrj    Contributed by Mark Mitchell (mark@markmitchell.com).
4*38fd1498Szrj 
5*38fd1498Szrj    This file is part of the GNU Offloading and Multi Processing Library
6*38fd1498Szrj    (libgomp).
7*38fd1498Szrj 
8*38fd1498Szrj    Libgomp is free software; you can redistribute it and/or modify it
9*38fd1498Szrj    under the terms of the GNU General Public License as published by
10*38fd1498Szrj    the Free Software Foundation; either version 3, or (at your option)
11*38fd1498Szrj    any later version.
12*38fd1498Szrj 
13*38fd1498Szrj    Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
14*38fd1498Szrj    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15*38fd1498Szrj    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16*38fd1498Szrj    more details.
17*38fd1498Szrj 
18*38fd1498Szrj    Under Section 7 of GPL version 3, you are granted additional
19*38fd1498Szrj    permissions described in the GCC Runtime Library Exception, version
20*38fd1498Szrj    3.1, as published by the Free Software Foundation.
21*38fd1498Szrj 
22*38fd1498Szrj    You should have received a copy of the GNU General Public License and
23*38fd1498Szrj    a copy of the GCC Runtime Library Exception along with this program;
24*38fd1498Szrj    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25*38fd1498Szrj    <http://www.gnu.org/licenses/>.  */
26*38fd1498Szrj 
27*38fd1498Szrj /* The splay tree code copied from include/splay-tree.h and adjusted,
28*38fd1498Szrj    so that all the data lives directly in splay_tree_node_s structure
29*38fd1498Szrj    and no extra allocations are needed.  */
30*38fd1498Szrj 
31*38fd1498Szrj /* For an easily readable description of splay-trees, see:
32*38fd1498Szrj 
33*38fd1498Szrj      Lewis, Harry R. and Denenberg, Larry.  Data Structures and Their
34*38fd1498Szrj      Algorithms.  Harper-Collins, Inc.  1991.
35*38fd1498Szrj 
36*38fd1498Szrj    The major feature of splay trees is that all basic tree operations
37*38fd1498Szrj    are amortized O(log n) time for a tree with n nodes.  */
38*38fd1498Szrj 
39*38fd1498Szrj #include "libgomp.h"
40*38fd1498Szrj 
41*38fd1498Szrj /* Rotate the edge joining the left child N with its parent P.  PP is the
42*38fd1498Szrj    grandparents' pointer to P.  */
43*38fd1498Szrj 
44*38fd1498Szrj static inline void
rotate_left(splay_tree_node * pp,splay_tree_node p,splay_tree_node n)45*38fd1498Szrj rotate_left (splay_tree_node *pp, splay_tree_node p, splay_tree_node n)
46*38fd1498Szrj {
47*38fd1498Szrj   splay_tree_node tmp;
48*38fd1498Szrj   tmp = n->right;
49*38fd1498Szrj   n->right = p;
50*38fd1498Szrj   p->left = tmp;
51*38fd1498Szrj   *pp = n;
52*38fd1498Szrj }
53*38fd1498Szrj 
54*38fd1498Szrj /* Rotate the edge joining the right child N with its parent P.  PP is the
55*38fd1498Szrj    grandparents' pointer to P.  */
56*38fd1498Szrj 
57*38fd1498Szrj static inline void
rotate_right(splay_tree_node * pp,splay_tree_node p,splay_tree_node n)58*38fd1498Szrj rotate_right (splay_tree_node *pp, splay_tree_node p, splay_tree_node n)
59*38fd1498Szrj {
60*38fd1498Szrj   splay_tree_node tmp;
61*38fd1498Szrj   tmp = n->left;
62*38fd1498Szrj   n->left = p;
63*38fd1498Szrj   p->right = tmp;
64*38fd1498Szrj   *pp = n;
65*38fd1498Szrj }
66*38fd1498Szrj 
67*38fd1498Szrj /* Bottom up splay of KEY.  */
68*38fd1498Szrj 
69*38fd1498Szrj static void
splay_tree_splay(splay_tree sp,splay_tree_key key)70*38fd1498Szrj splay_tree_splay (splay_tree sp, splay_tree_key key)
71*38fd1498Szrj {
72*38fd1498Szrj   if (sp->root == NULL)
73*38fd1498Szrj     return;
74*38fd1498Szrj 
75*38fd1498Szrj   do {
76*38fd1498Szrj     int cmp1, cmp2;
77*38fd1498Szrj     splay_tree_node n, c;
78*38fd1498Szrj 
79*38fd1498Szrj     n = sp->root;
80*38fd1498Szrj     cmp1 = splay_compare (key, &n->key);
81*38fd1498Szrj 
82*38fd1498Szrj     /* Found.  */
83*38fd1498Szrj     if (cmp1 == 0)
84*38fd1498Szrj       return;
85*38fd1498Szrj 
86*38fd1498Szrj     /* Left or right?  If no child, then we're done.  */
87*38fd1498Szrj     if (cmp1 < 0)
88*38fd1498Szrj       c = n->left;
89*38fd1498Szrj     else
90*38fd1498Szrj       c = n->right;
91*38fd1498Szrj     if (!c)
92*38fd1498Szrj       return;
93*38fd1498Szrj 
94*38fd1498Szrj     /* Next one left or right?  If found or no child, we're done
95*38fd1498Szrj        after one rotation.  */
96*38fd1498Szrj     cmp2 = splay_compare (key, &c->key);
97*38fd1498Szrj     if (cmp2 == 0
98*38fd1498Szrj 	|| (cmp2 < 0 && !c->left)
99*38fd1498Szrj 	|| (cmp2 > 0 && !c->right))
100*38fd1498Szrj       {
101*38fd1498Szrj 	if (cmp1 < 0)
102*38fd1498Szrj 	  rotate_left (&sp->root, n, c);
103*38fd1498Szrj 	else
104*38fd1498Szrj 	  rotate_right (&sp->root, n, c);
105*38fd1498Szrj 	return;
106*38fd1498Szrj       }
107*38fd1498Szrj 
108*38fd1498Szrj     /* Now we have the four cases of double-rotation.  */
109*38fd1498Szrj     if (cmp1 < 0 && cmp2 < 0)
110*38fd1498Szrj       {
111*38fd1498Szrj 	rotate_left (&n->left, c, c->left);
112*38fd1498Szrj 	rotate_left (&sp->root, n, n->left);
113*38fd1498Szrj       }
114*38fd1498Szrj     else if (cmp1 > 0 && cmp2 > 0)
115*38fd1498Szrj       {
116*38fd1498Szrj 	rotate_right (&n->right, c, c->right);
117*38fd1498Szrj 	rotate_right (&sp->root, n, n->right);
118*38fd1498Szrj       }
119*38fd1498Szrj     else if (cmp1 < 0 && cmp2 > 0)
120*38fd1498Szrj       {
121*38fd1498Szrj 	rotate_right (&n->left, c, c->right);
122*38fd1498Szrj 	rotate_left (&sp->root, n, n->left);
123*38fd1498Szrj       }
124*38fd1498Szrj     else if (cmp1 > 0 && cmp2 < 0)
125*38fd1498Szrj       {
126*38fd1498Szrj 	rotate_left (&n->right, c, c->left);
127*38fd1498Szrj 	rotate_right (&sp->root, n, n->right);
128*38fd1498Szrj       }
129*38fd1498Szrj   } while (1);
130*38fd1498Szrj }
131*38fd1498Szrj 
132*38fd1498Szrj /* Insert a new NODE into SP.  The NODE shouldn't exist in the tree.  */
133*38fd1498Szrj 
134*38fd1498Szrj attribute_hidden void
splay_tree_insert(splay_tree sp,splay_tree_node node)135*38fd1498Szrj splay_tree_insert (splay_tree sp, splay_tree_node node)
136*38fd1498Szrj {
137*38fd1498Szrj   int comparison = 0;
138*38fd1498Szrj 
139*38fd1498Szrj   splay_tree_splay (sp, &node->key);
140*38fd1498Szrj 
141*38fd1498Szrj   if (sp->root)
142*38fd1498Szrj     comparison = splay_compare (&sp->root->key, &node->key);
143*38fd1498Szrj 
144*38fd1498Szrj   if (sp->root && comparison == 0)
145*38fd1498Szrj     gomp_fatal ("Duplicate node");
146*38fd1498Szrj   else
147*38fd1498Szrj     {
148*38fd1498Szrj       /* Insert it at the root.  */
149*38fd1498Szrj       if (sp->root == NULL)
150*38fd1498Szrj 	node->left = node->right = NULL;
151*38fd1498Szrj       else if (comparison < 0)
152*38fd1498Szrj 	{
153*38fd1498Szrj 	  node->left = sp->root;
154*38fd1498Szrj 	  node->right = node->left->right;
155*38fd1498Szrj 	  node->left->right = NULL;
156*38fd1498Szrj 	}
157*38fd1498Szrj       else
158*38fd1498Szrj 	{
159*38fd1498Szrj 	  node->right = sp->root;
160*38fd1498Szrj 	  node->left = node->right->left;
161*38fd1498Szrj 	  node->right->left = NULL;
162*38fd1498Szrj 	}
163*38fd1498Szrj 
164*38fd1498Szrj       sp->root = node;
165*38fd1498Szrj     }
166*38fd1498Szrj }
167*38fd1498Szrj 
168*38fd1498Szrj /* Remove node with KEY from SP.  It is not an error if it did not exist.  */
169*38fd1498Szrj 
170*38fd1498Szrj attribute_hidden void
splay_tree_remove(splay_tree sp,splay_tree_key key)171*38fd1498Szrj splay_tree_remove (splay_tree sp, splay_tree_key key)
172*38fd1498Szrj {
173*38fd1498Szrj   splay_tree_splay (sp, key);
174*38fd1498Szrj 
175*38fd1498Szrj   if (sp->root && splay_compare (&sp->root->key, key) == 0)
176*38fd1498Szrj     {
177*38fd1498Szrj       splay_tree_node left, right;
178*38fd1498Szrj 
179*38fd1498Szrj       left = sp->root->left;
180*38fd1498Szrj       right = sp->root->right;
181*38fd1498Szrj 
182*38fd1498Szrj       /* One of the children is now the root.  Doesn't matter much
183*38fd1498Szrj 	 which, so long as we preserve the properties of the tree.  */
184*38fd1498Szrj       if (left)
185*38fd1498Szrj 	{
186*38fd1498Szrj 	  sp->root = left;
187*38fd1498Szrj 
188*38fd1498Szrj 	  /* If there was a right child as well, hang it off the
189*38fd1498Szrj 	     right-most leaf of the left child.  */
190*38fd1498Szrj 	  if (right)
191*38fd1498Szrj 	    {
192*38fd1498Szrj 	      while (left->right)
193*38fd1498Szrj 		left = left->right;
194*38fd1498Szrj 	      left->right = right;
195*38fd1498Szrj 	    }
196*38fd1498Szrj 	}
197*38fd1498Szrj       else
198*38fd1498Szrj 	sp->root = right;
199*38fd1498Szrj     }
200*38fd1498Szrj }
201*38fd1498Szrj 
202*38fd1498Szrj /* Lookup KEY in SP, returning NODE if present, and NULL
203*38fd1498Szrj    otherwise.  */
204*38fd1498Szrj 
205*38fd1498Szrj attribute_hidden splay_tree_key
splay_tree_lookup(splay_tree sp,splay_tree_key key)206*38fd1498Szrj splay_tree_lookup (splay_tree sp, splay_tree_key key)
207*38fd1498Szrj {
208*38fd1498Szrj   splay_tree_splay (sp, key);
209*38fd1498Szrj 
210*38fd1498Szrj   if (sp->root && splay_compare (&sp->root->key, key) == 0)
211*38fd1498Szrj     return &sp->root->key;
212*38fd1498Szrj   else
213*38fd1498Szrj     return NULL;
214*38fd1498Szrj }
215*38fd1498Szrj 
216*38fd1498Szrj /* Helper function for splay_tree_foreach.
217*38fd1498Szrj 
218*38fd1498Szrj    Run FUNC on every node in KEY.  */
219*38fd1498Szrj 
220*38fd1498Szrj static void
splay_tree_foreach_internal(splay_tree_node node,splay_tree_callback func,void * data)221*38fd1498Szrj splay_tree_foreach_internal (splay_tree_node node, splay_tree_callback func,
222*38fd1498Szrj 			     void *data)
223*38fd1498Szrj {
224*38fd1498Szrj   if (!node)
225*38fd1498Szrj     return;
226*38fd1498Szrj   func (&node->key, data);
227*38fd1498Szrj   splay_tree_foreach_internal (node->left, func, data);
228*38fd1498Szrj   /* Yeah, whatever.  GCC can fix my tail recursion.  */
229*38fd1498Szrj   splay_tree_foreach_internal (node->right, func, data);
230*38fd1498Szrj }
231*38fd1498Szrj 
232*38fd1498Szrj /* Run FUNC on each of the nodes in SP.  */
233*38fd1498Szrj 
234*38fd1498Szrj attribute_hidden void
splay_tree_foreach(splay_tree sp,splay_tree_callback func,void * data)235*38fd1498Szrj splay_tree_foreach (splay_tree sp, splay_tree_callback func, void *data)
236*38fd1498Szrj {
237*38fd1498Szrj   splay_tree_foreach_internal (sp->root, func, data);
238*38fd1498Szrj }
239