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