1 | /* List implementation of a partition of consecutive integers.
|
---|
2 | Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
---|
3 | Contributed by CodeSourcery, LLC.
|
---|
4 |
|
---|
5 | This file is part of GNU CC.
|
---|
6 |
|
---|
7 | GNU CC is free software; you can redistribute it and/or modify
|
---|
8 | it under the terms of the GNU General Public License as published by
|
---|
9 | the Free Software Foundation; either version 2, or (at your option)
|
---|
10 | any later version.
|
---|
11 |
|
---|
12 | GNU CC is distributed in the hope that it will be useful,
|
---|
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
15 | GNU General Public License for more details.
|
---|
16 |
|
---|
17 | You should have received a copy of the GNU General Public License
|
---|
18 | along with GNU CC; see the file COPYING. If not, write to
|
---|
19 | the Free Software Foundation, 59 Temple Place - Suite 330,
|
---|
20 | Boston, MA 02111-1307, USA. */
|
---|
21 |
|
---|
22 | #ifdef HAVE_CONFIG_H
|
---|
23 | #include "config.h"
|
---|
24 | #endif
|
---|
25 |
|
---|
26 | #ifdef HAVE_STDLIB_H
|
---|
27 | #include <stdlib.h>
|
---|
28 | #endif
|
---|
29 |
|
---|
30 | #ifdef HAVE_STRING_H
|
---|
31 | #include <string.h>
|
---|
32 | #endif
|
---|
33 |
|
---|
34 | #include "libiberty.h"
|
---|
35 | #include "partition.h"
|
---|
36 |
|
---|
37 | static int elem_compare PARAMS ((const void *, const void *));
|
---|
38 |
|
---|
39 | /* Creates a partition of NUM_ELEMENTS elements. Initially each
|
---|
40 | element is in a class by itself. */
|
---|
41 |
|
---|
42 | partition
|
---|
43 | partition_new (num_elements)
|
---|
44 | int num_elements;
|
---|
45 | {
|
---|
46 | int e;
|
---|
47 |
|
---|
48 | partition part = (partition)
|
---|
49 | xmalloc (sizeof (struct partition_def) +
|
---|
50 | (num_elements - 1) * sizeof (struct partition_elem));
|
---|
51 | part->num_elements = num_elements;
|
---|
52 | for (e = 0; e < num_elements; ++e)
|
---|
53 | {
|
---|
54 | part->elements[e].class_element = e;
|
---|
55 | part->elements[e].next = &(part->elements[e]);
|
---|
56 | part->elements[e].class_count = 1;
|
---|
57 | }
|
---|
58 |
|
---|
59 | return part;
|
---|
60 | }
|
---|
61 |
|
---|
62 | /* Freeds a partition. */
|
---|
63 |
|
---|
64 | void
|
---|
65 | partition_delete (part)
|
---|
66 | partition part;
|
---|
67 | {
|
---|
68 | free (part);
|
---|
69 | }
|
---|
70 |
|
---|
71 | /* Unites the classes containing ELEM1 and ELEM2 into a single class
|
---|
72 | of partition PART. If ELEM1 and ELEM2 are already in the same
|
---|
73 | class, does nothing. Returns the canonical element of the
|
---|
74 | resulting union class. */
|
---|
75 |
|
---|
76 | int
|
---|
77 | partition_union (part, elem1, elem2)
|
---|
78 | partition part;
|
---|
79 | int elem1;
|
---|
80 | int elem2;
|
---|
81 | {
|
---|
82 | struct partition_elem *elements = part->elements;
|
---|
83 | struct partition_elem *e1;
|
---|
84 | struct partition_elem *e2;
|
---|
85 | struct partition_elem *p;
|
---|
86 | struct partition_elem *old_next;
|
---|
87 | /* The canonical element of the resulting union class. */
|
---|
88 | int class_element = elements[elem1].class_element;
|
---|
89 |
|
---|
90 | /* If they're already in the same class, do nothing. */
|
---|
91 | if (class_element == elements[elem2].class_element)
|
---|
92 | return class_element;
|
---|
93 |
|
---|
94 | /* Make sure ELEM1 is in the larger class of the two. If not, swap
|
---|
95 | them. This way we always scan the shorter list. */
|
---|
96 | if (elements[elem1].class_count < elements[elem2].class_count)
|
---|
97 | {
|
---|
98 | int temp = elem1;
|
---|
99 | elem1 = elem2;
|
---|
100 | elem2 = temp;
|
---|
101 | class_element = elements[elem1].class_element;
|
---|
102 | }
|
---|
103 |
|
---|
104 | e1 = &(elements[elem1]);
|
---|
105 | e2 = &(elements[elem2]);
|
---|
106 |
|
---|
107 | /* Keep a count of the number of elements in the list. */
|
---|
108 | elements[class_element].class_count
|
---|
109 | += elements[e2->class_element].class_count;
|
---|
110 |
|
---|
111 | /* Update the class fields in elem2's class list. */
|
---|
112 | e2->class_element = class_element;
|
---|
113 | for (p = e2->next; p != e2; p = p->next)
|
---|
114 | p->class_element = class_element;
|
---|
115 |
|
---|
116 | /* Splice ELEM2's class list into ELEM1's. These are circular
|
---|
117 | lists. */
|
---|
118 | old_next = e1->next;
|
---|
119 | e1->next = e2->next;
|
---|
120 | e2->next = old_next;
|
---|
121 |
|
---|
122 | return class_element;
|
---|
123 | }
|
---|
124 |
|
---|
125 | /* Compare elements ELEM1 and ELEM2 from array of integers, given a
|
---|
126 | pointer to each. Used to qsort such an array. */
|
---|
127 |
|
---|
128 | static int
|
---|
129 | elem_compare (elem1, elem2)
|
---|
130 | const void *elem1;
|
---|
131 | const void *elem2;
|
---|
132 | {
|
---|
133 | int e1 = * (const int *) elem1;
|
---|
134 | int e2 = * (const int *) elem2;
|
---|
135 | if (e1 < e2)
|
---|
136 | return -1;
|
---|
137 | else if (e1 > e2)
|
---|
138 | return 1;
|
---|
139 | else
|
---|
140 | return 0;
|
---|
141 | }
|
---|
142 |
|
---|
143 | /* Prints PART to the file pointer FP. The elements of each
|
---|
144 | class are sorted. */
|
---|
145 |
|
---|
146 | void
|
---|
147 | partition_print (part, fp)
|
---|
148 | partition part;
|
---|
149 | FILE *fp;
|
---|
150 | {
|
---|
151 | char *done;
|
---|
152 | int num_elements = part->num_elements;
|
---|
153 | struct partition_elem *elements = part->elements;
|
---|
154 | int *class_elements;
|
---|
155 | int e;
|
---|
156 |
|
---|
157 | /* Flag the elements we've already printed. */
|
---|
158 | done = (char *) xmalloc (num_elements);
|
---|
159 | memset (done, 0, num_elements);
|
---|
160 |
|
---|
161 | /* A buffer used to sort elements in a class. */
|
---|
162 | class_elements = (int *) xmalloc (num_elements * sizeof (int));
|
---|
163 |
|
---|
164 | fputc ('[', fp);
|
---|
165 | for (e = 0; e < num_elements; ++e)
|
---|
166 | /* If we haven't printed this element, print its entire class. */
|
---|
167 | if (! done[e])
|
---|
168 | {
|
---|
169 | int c = e;
|
---|
170 | int count = elements[elements[e].class_element].class_count;
|
---|
171 | int i;
|
---|
172 |
|
---|
173 | /* Collect the elements in this class. */
|
---|
174 | for (i = 0; i < count; ++i) {
|
---|
175 | class_elements[i] = c;
|
---|
176 | done[c] = 1;
|
---|
177 | c = elements[c].next - elements;
|
---|
178 | }
|
---|
179 | /* Sort them. */
|
---|
180 | qsort ((void *) class_elements, count, sizeof (int), elem_compare);
|
---|
181 | /* Print them. */
|
---|
182 | fputc ('(', fp);
|
---|
183 | for (i = 0; i < count; ++i)
|
---|
184 | fprintf (fp, i == 0 ? "%d" : " %d", class_elements[i]);
|
---|
185 | fputc (')', fp);
|
---|
186 | }
|
---|
187 | fputc (']', fp);
|
---|
188 |
|
---|
189 | free (done);
|
---|
190 | }
|
---|
191 |
|
---|