annotate libgomp/splay-tree.c @ 111:04ced10e8804

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