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