xref: /openbsd-src/gnu/lib/libiberty/src/partition.c (revision 150b7e42cfa21e6546d96ae514ca23e80d970ac7)
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