137c53322Sespie /* List implementation of a partition of consecutive integers.
237c53322Sespie Copyright (C) 2000, 2001 Free Software Foundation, Inc.
300bf4279Sespie Contributed by CodeSourcery, LLC.
400bf4279Sespie
500bf4279Sespie This file is part of GNU CC.
600bf4279Sespie
700bf4279Sespie GNU CC is free software; you can redistribute it and/or modify
800bf4279Sespie it under the terms of the GNU General Public License as published by
900bf4279Sespie the Free Software Foundation; either version 2, or (at your option)
1000bf4279Sespie any later version.
1100bf4279Sespie
1200bf4279Sespie GNU CC is distributed in the hope that it will be useful,
1300bf4279Sespie but WITHOUT ANY WARRANTY; without even the implied warranty of
1400bf4279Sespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1500bf4279Sespie GNU General Public License for more details.
1600bf4279Sespie
1700bf4279Sespie You should have received a copy of the GNU General Public License
1800bf4279Sespie along with GNU CC; see the file COPYING. If not, write to
19*150b7e42Smiod the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20*150b7e42Smiod Boston, MA 02110-1301, USA. */
2100bf4279Sespie
2200bf4279Sespie #ifdef HAVE_CONFIG_H
2300bf4279Sespie #include "config.h"
2400bf4279Sespie #endif
2500bf4279Sespie
2600bf4279Sespie #ifdef HAVE_STDLIB_H
2700bf4279Sespie #include <stdlib.h>
2800bf4279Sespie #endif
2900bf4279Sespie
30f5dd06f4Sespie #ifdef HAVE_STRING_H
31f5dd06f4Sespie #include <string.h>
32f5dd06f4Sespie #endif
33f5dd06f4Sespie
3400bf4279Sespie #include "libiberty.h"
3500bf4279Sespie #include "partition.h"
3600bf4279Sespie
37*150b7e42Smiod static int elem_compare (const void *, const void *);
38f5dd06f4Sespie
3900bf4279Sespie /* Creates a partition of NUM_ELEMENTS elements. Initially each
4000bf4279Sespie element is in a class by itself. */
4100bf4279Sespie
4200bf4279Sespie partition
partition_new(int num_elements)43*150b7e42Smiod partition_new (int num_elements)
4400bf4279Sespie {
4500bf4279Sespie int e;
4600bf4279Sespie
4700bf4279Sespie partition part = (partition)
4800bf4279Sespie xmalloc (sizeof (struct partition_def) +
4900bf4279Sespie (num_elements - 1) * sizeof (struct partition_elem));
5000bf4279Sespie part->num_elements = num_elements;
5100bf4279Sespie for (e = 0; e < num_elements; ++e)
5200bf4279Sespie {
5300bf4279Sespie part->elements[e].class_element = e;
5400bf4279Sespie part->elements[e].next = &(part->elements[e]);
5500bf4279Sespie part->elements[e].class_count = 1;
5600bf4279Sespie }
5700bf4279Sespie
5800bf4279Sespie return part;
5900bf4279Sespie }
6000bf4279Sespie
6100bf4279Sespie /* Freeds a partition. */
6200bf4279Sespie
6300bf4279Sespie void
partition_delete(partition part)64*150b7e42Smiod partition_delete (partition part)
6500bf4279Sespie {
6600bf4279Sespie free (part);
6700bf4279Sespie }
6800bf4279Sespie
6900bf4279Sespie /* Unites the classes containing ELEM1 and ELEM2 into a single class
7000bf4279Sespie of partition PART. If ELEM1 and ELEM2 are already in the same
7100bf4279Sespie class, does nothing. Returns the canonical element of the
7200bf4279Sespie resulting union class. */
7300bf4279Sespie
7400bf4279Sespie int
partition_union(partition part,int elem1,int elem2)75*150b7e42Smiod partition_union (partition part, int elem1, int elem2)
7600bf4279Sespie {
7700bf4279Sespie struct partition_elem *elements = part->elements;
7800bf4279Sespie struct partition_elem *e1;
7900bf4279Sespie struct partition_elem *e2;
8000bf4279Sespie struct partition_elem *p;
8100bf4279Sespie struct partition_elem *old_next;
8200bf4279Sespie /* The canonical element of the resulting union class. */
8300bf4279Sespie int class_element = elements[elem1].class_element;
8400bf4279Sespie
8500bf4279Sespie /* If they're already in the same class, do nothing. */
8600bf4279Sespie if (class_element == elements[elem2].class_element)
8700bf4279Sespie return class_element;
8800bf4279Sespie
8900bf4279Sespie /* Make sure ELEM1 is in the larger class of the two. If not, swap
9000bf4279Sespie them. This way we always scan the shorter list. */
9100bf4279Sespie if (elements[elem1].class_count < elements[elem2].class_count)
9200bf4279Sespie {
9300bf4279Sespie int temp = elem1;
9400bf4279Sespie elem1 = elem2;
9500bf4279Sespie elem2 = temp;
9600bf4279Sespie class_element = elements[elem1].class_element;
9700bf4279Sespie }
9800bf4279Sespie
9900bf4279Sespie e1 = &(elements[elem1]);
10000bf4279Sespie e2 = &(elements[elem2]);
10100bf4279Sespie
10200bf4279Sespie /* Keep a count of the number of elements in the list. */
10300bf4279Sespie elements[class_element].class_count
10400bf4279Sespie += elements[e2->class_element].class_count;
10500bf4279Sespie
10600bf4279Sespie /* Update the class fields in elem2's class list. */
10700bf4279Sespie e2->class_element = class_element;
10800bf4279Sespie for (p = e2->next; p != e2; p = p->next)
10900bf4279Sespie p->class_element = class_element;
11000bf4279Sespie
11100bf4279Sespie /* Splice ELEM2's class list into ELEM1's. These are circular
11200bf4279Sespie lists. */
11300bf4279Sespie old_next = e1->next;
11400bf4279Sespie e1->next = e2->next;
11500bf4279Sespie e2->next = old_next;
11600bf4279Sespie
11700bf4279Sespie return class_element;
11800bf4279Sespie }
11900bf4279Sespie
12000bf4279Sespie /* Compare elements ELEM1 and ELEM2 from array of integers, given a
12100bf4279Sespie pointer to each. Used to qsort such an array. */
12200bf4279Sespie
12300bf4279Sespie static int
elem_compare(const void * elem1,const void * elem2)124*150b7e42Smiod elem_compare (const void *elem1, const void *elem2)
12500bf4279Sespie {
126f5dd06f4Sespie int e1 = * (const int *) elem1;
127f5dd06f4Sespie int e2 = * (const int *) elem2;
12800bf4279Sespie if (e1 < e2)
12900bf4279Sespie return -1;
13000bf4279Sespie else if (e1 > e2)
13100bf4279Sespie return 1;
13200bf4279Sespie else
13300bf4279Sespie return 0;
13400bf4279Sespie }
13500bf4279Sespie
13600bf4279Sespie /* Prints PART to the file pointer FP. The elements of each
13700bf4279Sespie class are sorted. */
13800bf4279Sespie
13900bf4279Sespie void
partition_print(partition part,FILE * fp)140*150b7e42Smiod partition_print (partition part, FILE *fp)
14100bf4279Sespie {
14200bf4279Sespie char *done;
14300bf4279Sespie int num_elements = part->num_elements;
14400bf4279Sespie struct partition_elem *elements = part->elements;
14500bf4279Sespie int *class_elements;
14600bf4279Sespie int e;
14700bf4279Sespie
14800bf4279Sespie /* Flag the elements we've already printed. */
14900bf4279Sespie done = (char *) xmalloc (num_elements);
15000bf4279Sespie memset (done, 0, num_elements);
15100bf4279Sespie
15200bf4279Sespie /* A buffer used to sort elements in a class. */
15300bf4279Sespie class_elements = (int *) xmalloc (num_elements * sizeof (int));
15400bf4279Sespie
15500bf4279Sespie fputc ('[', fp);
15600bf4279Sespie for (e = 0; e < num_elements; ++e)
15700bf4279Sespie /* If we haven't printed this element, print its entire class. */
15800bf4279Sespie if (! done[e])
15900bf4279Sespie {
16000bf4279Sespie int c = e;
16100bf4279Sespie int count = elements[elements[e].class_element].class_count;
16200bf4279Sespie int i;
16300bf4279Sespie
16400bf4279Sespie /* Collect the elements in this class. */
16500bf4279Sespie for (i = 0; i < count; ++i) {
16600bf4279Sespie class_elements[i] = c;
16700bf4279Sespie done[c] = 1;
16800bf4279Sespie c = elements[c].next - elements;
16900bf4279Sespie }
17000bf4279Sespie /* Sort them. */
171f5dd06f4Sespie qsort ((void *) class_elements, count, sizeof (int), elem_compare);
17200bf4279Sespie /* Print them. */
17300bf4279Sespie fputc ('(', fp);
17400bf4279Sespie for (i = 0; i < count; ++i)
17500bf4279Sespie fprintf (fp, i == 0 ? "%d" : " %d", class_elements[i]);
17600bf4279Sespie fputc (')', fp);
17700bf4279Sespie }
17800bf4279Sespie fputc (']', fp);
17900bf4279Sespie
180*150b7e42Smiod free (class_elements);
18100bf4279Sespie free (done);
18200bf4279Sespie }
18300bf4279Sespie
184