xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/fortran/bbt.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
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