1627f7eb2Smrg /* Balanced binary trees using treaps.
2*4c3eb207Smrg Copyright (C) 2000-2020 Free Software Foundation, Inc.
3627f7eb2Smrg Contributed by Andy Vaught
4627f7eb2Smrg
5627f7eb2Smrg This file is part of GCC.
6627f7eb2Smrg
7627f7eb2Smrg GCC is free software; you can redistribute it and/or modify it under
8627f7eb2Smrg the terms of the GNU General Public License as published by the Free
9627f7eb2Smrg Software Foundation; either version 3, or (at your option) any later
10627f7eb2Smrg version.
11627f7eb2Smrg
12627f7eb2Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13627f7eb2Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14627f7eb2Smrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15627f7eb2Smrg for more details.
16627f7eb2Smrg
17627f7eb2Smrg You should have received a copy of the GNU General Public License
18627f7eb2Smrg along with GCC; see the file COPYING3. If not see
19627f7eb2Smrg <http://www.gnu.org/licenses/>. */
20627f7eb2Smrg
21627f7eb2Smrg /* The idea is to balance the tree using pseudorandom numbers. The
22627f7eb2Smrg main constraint on this implementation is that we have several
23627f7eb2Smrg distinct structures that have to be arranged in a binary tree.
24627f7eb2Smrg These structures all contain a BBT_HEADER() in front that gives the
25627f7eb2Smrg treap-related information. The key and value are assumed to reside
26627f7eb2Smrg in the rest of the structure.
27627f7eb2Smrg
28627f7eb2Smrg When calling, we are also passed a comparison function that
29627f7eb2Smrg compares two nodes. We don't implement a separate 'find' function
30627f7eb2Smrg here, but rather use separate functions for each variety of tree.
31627f7eb2Smrg We are also restricted to not copy treap structures, which most
32627f7eb2Smrg implementations find convenient, because we otherwise would need to
33627f7eb2Smrg know how long the structure is.
34627f7eb2Smrg
35627f7eb2Smrg This implementation is based on Stefan Nilsson's article in the
36627f7eb2Smrg July 1997 Doctor Dobb's Journal, "Treaps in Java". */
37627f7eb2Smrg
38627f7eb2Smrg #include "config.h"
39627f7eb2Smrg #include "system.h"
40627f7eb2Smrg #include "coretypes.h"
41627f7eb2Smrg #include "gfortran.h"
42627f7eb2Smrg
43627f7eb2Smrg typedef struct gfc_treap
44627f7eb2Smrg {
45627f7eb2Smrg BBT_HEADER (gfc_treap);
46627f7eb2Smrg }
47627f7eb2Smrg gfc_bbt;
48627f7eb2Smrg
49627f7eb2Smrg /* Simple linear congruential pseudorandom number generator. The
50627f7eb2Smrg period of this generator is 44071, which is plenty for our
51627f7eb2Smrg purposes. */
52627f7eb2Smrg
53627f7eb2Smrg static int
pseudo_random(void)54627f7eb2Smrg pseudo_random (void)
55627f7eb2Smrg {
56627f7eb2Smrg static int x0 = 5341;
57627f7eb2Smrg
58627f7eb2Smrg x0 = (22611 * x0 + 10) % 44071;
59627f7eb2Smrg return x0;
60627f7eb2Smrg }
61627f7eb2Smrg
62627f7eb2Smrg
63627f7eb2Smrg /* Rotate the treap left. */
64627f7eb2Smrg
65627f7eb2Smrg static gfc_bbt *
rotate_left(gfc_bbt * t)66627f7eb2Smrg rotate_left (gfc_bbt *t)
67627f7eb2Smrg {
68627f7eb2Smrg gfc_bbt *temp;
69627f7eb2Smrg
70627f7eb2Smrg temp = t->right;
71627f7eb2Smrg t->right = t->right->left;
72627f7eb2Smrg temp->left = t;
73627f7eb2Smrg
74627f7eb2Smrg return temp;
75627f7eb2Smrg }
76627f7eb2Smrg
77627f7eb2Smrg
78627f7eb2Smrg /* Rotate the treap right. */
79627f7eb2Smrg
80627f7eb2Smrg static gfc_bbt *
rotate_right(gfc_bbt * t)81627f7eb2Smrg rotate_right (gfc_bbt *t)
82627f7eb2Smrg {
83627f7eb2Smrg gfc_bbt *temp;
84627f7eb2Smrg
85627f7eb2Smrg temp = t->left;
86627f7eb2Smrg t->left = t->left->right;
87627f7eb2Smrg temp->right = t;
88627f7eb2Smrg
89627f7eb2Smrg return temp;
90627f7eb2Smrg }
91627f7eb2Smrg
92627f7eb2Smrg
93627f7eb2Smrg /* Recursive insertion function. Returns the updated treap, or
94627f7eb2Smrg aborts if we find a duplicate key. */
95627f7eb2Smrg
96627f7eb2Smrg static gfc_bbt *
insert(gfc_bbt * new_bbt,gfc_bbt * t,compare_fn compare)97627f7eb2Smrg insert (gfc_bbt *new_bbt, gfc_bbt *t, compare_fn compare)
98627f7eb2Smrg {
99627f7eb2Smrg int c;
100627f7eb2Smrg
101627f7eb2Smrg if (t == NULL)
102627f7eb2Smrg return new_bbt;
103627f7eb2Smrg
104627f7eb2Smrg c = (*compare) (new_bbt, t);
105627f7eb2Smrg
106627f7eb2Smrg if (c < 0)
107627f7eb2Smrg {
108627f7eb2Smrg t->left = insert (new_bbt, t->left, compare);
109627f7eb2Smrg if (t->priority < t->left->priority)
110627f7eb2Smrg t = rotate_right (t);
111627f7eb2Smrg }
112627f7eb2Smrg else if (c > 0)
113627f7eb2Smrg {
114627f7eb2Smrg t->right = insert (new_bbt, t->right, compare);
115627f7eb2Smrg if (t->priority < t->right->priority)
116627f7eb2Smrg t = rotate_left (t);
117627f7eb2Smrg }
118627f7eb2Smrg else /* if (c == 0) */
119627f7eb2Smrg gfc_internal_error("insert_bbt(): Duplicate key found");
120627f7eb2Smrg
121627f7eb2Smrg return t;
122627f7eb2Smrg }
123627f7eb2Smrg
124627f7eb2Smrg
125627f7eb2Smrg /* Given root pointer, a new node and a comparison function, insert
126627f7eb2Smrg the new node into the treap. It is an error to insert a key that
127627f7eb2Smrg already exists. */
128627f7eb2Smrg
129627f7eb2Smrg void
gfc_insert_bbt(void * root,void * new_node,compare_fn compare)130627f7eb2Smrg gfc_insert_bbt (void *root, void *new_node, compare_fn compare)
131627f7eb2Smrg {
132627f7eb2Smrg gfc_bbt **r, *n;
133627f7eb2Smrg
134627f7eb2Smrg r = (gfc_bbt **) root;
135627f7eb2Smrg n = (gfc_bbt *) new_node;
136627f7eb2Smrg n->priority = pseudo_random ();
137627f7eb2Smrg *r = insert (n, *r, compare);
138627f7eb2Smrg }
139627f7eb2Smrg
140627f7eb2Smrg static gfc_bbt *
delete_root(gfc_bbt * t)141627f7eb2Smrg delete_root (gfc_bbt *t)
142627f7eb2Smrg {
143627f7eb2Smrg gfc_bbt *temp;
144627f7eb2Smrg
145627f7eb2Smrg if (t->left == NULL)
146627f7eb2Smrg return t->right;
147627f7eb2Smrg if (t->right == NULL)
148627f7eb2Smrg return t->left;
149627f7eb2Smrg
150627f7eb2Smrg if (t->left->priority > t->right->priority)
151627f7eb2Smrg {
152627f7eb2Smrg temp = rotate_right (t);
153627f7eb2Smrg temp->right = delete_root (t);
154627f7eb2Smrg }
155627f7eb2Smrg else
156627f7eb2Smrg {
157627f7eb2Smrg temp = rotate_left (t);
158627f7eb2Smrg temp->left = delete_root (t);
159627f7eb2Smrg }
160627f7eb2Smrg
161627f7eb2Smrg return temp;
162627f7eb2Smrg }
163627f7eb2Smrg
164627f7eb2Smrg
165627f7eb2Smrg /* Delete an element from a tree. The 'old' value does not
166627f7eb2Smrg necessarily have to point to the element to be deleted, it must
167627f7eb2Smrg just point to a treap structure with the key to be deleted.
168627f7eb2Smrg Returns the new root node of the tree. */
169627f7eb2Smrg
170627f7eb2Smrg static gfc_bbt *
delete_treap(gfc_bbt * old,gfc_bbt * t,compare_fn compare)171627f7eb2Smrg delete_treap (gfc_bbt *old, gfc_bbt *t, compare_fn compare)
172627f7eb2Smrg {
173627f7eb2Smrg int c;
174627f7eb2Smrg
175627f7eb2Smrg if (t == NULL)
176627f7eb2Smrg return NULL;
177627f7eb2Smrg
178627f7eb2Smrg c = (*compare) (old, t);
179627f7eb2Smrg
180627f7eb2Smrg if (c < 0)
181627f7eb2Smrg t->left = delete_treap (old, t->left, compare);
182627f7eb2Smrg if (c > 0)
183627f7eb2Smrg t->right = delete_treap (old, t->right, compare);
184627f7eb2Smrg if (c == 0)
185627f7eb2Smrg t = delete_root (t);
186627f7eb2Smrg
187627f7eb2Smrg return t;
188627f7eb2Smrg }
189627f7eb2Smrg
190627f7eb2Smrg
191627f7eb2Smrg void
gfc_delete_bbt(void * root,void * old,compare_fn compare)192627f7eb2Smrg gfc_delete_bbt (void *root, void *old, compare_fn compare)
193627f7eb2Smrg {
194627f7eb2Smrg gfc_bbt **t;
195627f7eb2Smrg
196627f7eb2Smrg t = (gfc_bbt **) root;
197627f7eb2Smrg *t = delete_treap ((gfc_bbt *) old, *t, compare);
198627f7eb2Smrg }
199