12a6b7db3Sskrll /* List implementation of a partition of consecutive integers.
2*f22f0ef4Schristos    Copyright (C) 2000-2022 Free Software Foundation, Inc.
32a6b7db3Sskrll    Contributed by CodeSourcery, LLC.
42a6b7db3Sskrll 
52a6b7db3Sskrll    This file is part of GNU CC.
62a6b7db3Sskrll 
72a6b7db3Sskrll    GNU CC is free software; you can redistribute it and/or modify
82a6b7db3Sskrll    it under the terms of the GNU General Public License as published by
92a6b7db3Sskrll    the Free Software Foundation; either version 2, or (at your option)
102a6b7db3Sskrll    any later version.
112a6b7db3Sskrll 
122a6b7db3Sskrll    GNU CC is distributed in the hope that it will be useful,
132a6b7db3Sskrll    but WITHOUT ANY WARRANTY; without even the implied warranty of
142a6b7db3Sskrll    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
152a6b7db3Sskrll    GNU General Public License for more details.
162a6b7db3Sskrll 
172a6b7db3Sskrll    You should have received a copy of the GNU General Public License
182a6b7db3Sskrll    along with GNU CC; see the file COPYING.  If not, write to
192a6b7db3Sskrll    the Free Software Foundation, 51 Franklin Street - Fifth Floor,
202a6b7db3Sskrll    Boston, MA 02110-1301, USA.  */
212a6b7db3Sskrll 
222a6b7db3Sskrll #ifdef HAVE_CONFIG_H
232a6b7db3Sskrll #include "config.h"
242a6b7db3Sskrll #endif
252a6b7db3Sskrll 
262a6b7db3Sskrll #ifdef HAVE_STDLIB_H
272a6b7db3Sskrll #include <stdlib.h>
282a6b7db3Sskrll #endif
292a6b7db3Sskrll 
302a6b7db3Sskrll #ifdef HAVE_STRING_H
312a6b7db3Sskrll #include <string.h>
322a6b7db3Sskrll #endif
332a6b7db3Sskrll 
342a6b7db3Sskrll #include "libiberty.h"
352a6b7db3Sskrll #include "partition.h"
362a6b7db3Sskrll 
372a6b7db3Sskrll static int elem_compare (const void *, const void *);
382a6b7db3Sskrll 
392a6b7db3Sskrll /* Creates a partition of NUM_ELEMENTS elements.  Initially each
402a6b7db3Sskrll    element is in a class by itself.  */
412a6b7db3Sskrll 
422a6b7db3Sskrll partition
partition_new(int num_elements)432a6b7db3Sskrll partition_new (int num_elements)
442a6b7db3Sskrll {
452a6b7db3Sskrll   int e;
462a6b7db3Sskrll 
472a6b7db3Sskrll   partition part = (partition)
482a6b7db3Sskrll     xmalloc (sizeof (struct partition_def) +
492a6b7db3Sskrll 	     (num_elements - 1) * sizeof (struct partition_elem));
502a6b7db3Sskrll   part->num_elements = num_elements;
512a6b7db3Sskrll   for (e = 0; e < num_elements; ++e)
522a6b7db3Sskrll     {
532a6b7db3Sskrll       part->elements[e].class_element = e;
542a6b7db3Sskrll       part->elements[e].next = &(part->elements[e]);
552a6b7db3Sskrll       part->elements[e].class_count = 1;
562a6b7db3Sskrll     }
572a6b7db3Sskrll 
582a6b7db3Sskrll   return part;
592a6b7db3Sskrll }
602a6b7db3Sskrll 
612a6b7db3Sskrll /* Freeds a partition.  */
622a6b7db3Sskrll 
632a6b7db3Sskrll void
partition_delete(partition part)642a6b7db3Sskrll partition_delete (partition part)
652a6b7db3Sskrll {
662a6b7db3Sskrll   free (part);
672a6b7db3Sskrll }
682a6b7db3Sskrll 
692a6b7db3Sskrll /* Unites the classes containing ELEM1 and ELEM2 into a single class
702a6b7db3Sskrll    of partition PART.  If ELEM1 and ELEM2 are already in the same
712a6b7db3Sskrll    class, does nothing.  Returns the canonical element of the
722a6b7db3Sskrll    resulting union class.  */
732a6b7db3Sskrll 
742a6b7db3Sskrll int
partition_union(partition part,int elem1,int elem2)752a6b7db3Sskrll partition_union (partition part, int elem1, int elem2)
762a6b7db3Sskrll {
772a6b7db3Sskrll   struct partition_elem *elements = part->elements;
782a6b7db3Sskrll   struct partition_elem *e1;
792a6b7db3Sskrll   struct partition_elem *e2;
802a6b7db3Sskrll   struct partition_elem *p;
812a6b7db3Sskrll   struct partition_elem *old_next;
822a6b7db3Sskrll   /* The canonical element of the resulting union class.  */
832a6b7db3Sskrll   int class_element = elements[elem1].class_element;
842a6b7db3Sskrll 
852a6b7db3Sskrll   /* If they're already in the same class, do nothing.  */
862a6b7db3Sskrll   if (class_element == elements[elem2].class_element)
872a6b7db3Sskrll     return class_element;
882a6b7db3Sskrll 
892a6b7db3Sskrll   /* Make sure ELEM1 is in the larger class of the two.  If not, swap
902a6b7db3Sskrll      them.  This way we always scan the shorter list.  */
912a6b7db3Sskrll   if (elements[elem1].class_count < elements[elem2].class_count)
922a6b7db3Sskrll     {
932a6b7db3Sskrll       int temp = elem1;
942a6b7db3Sskrll       elem1 = elem2;
952a6b7db3Sskrll       elem2 = temp;
962a6b7db3Sskrll       class_element = elements[elem1].class_element;
972a6b7db3Sskrll     }
982a6b7db3Sskrll 
992a6b7db3Sskrll   e1 = &(elements[elem1]);
1002a6b7db3Sskrll   e2 = &(elements[elem2]);
1012a6b7db3Sskrll 
1022a6b7db3Sskrll   /* Keep a count of the number of elements in the list.  */
1032a6b7db3Sskrll   elements[class_element].class_count
1042a6b7db3Sskrll     += elements[e2->class_element].class_count;
1052a6b7db3Sskrll 
1062a6b7db3Sskrll   /* Update the class fields in elem2's class list.  */
1072a6b7db3Sskrll   e2->class_element = class_element;
1082a6b7db3Sskrll   for (p = e2->next; p != e2; p = p->next)
1092a6b7db3Sskrll     p->class_element = class_element;
1102a6b7db3Sskrll 
1112a6b7db3Sskrll   /* Splice ELEM2's class list into ELEM1's.  These are circular
1122a6b7db3Sskrll      lists.  */
1132a6b7db3Sskrll   old_next = e1->next;
1142a6b7db3Sskrll   e1->next = e2->next;
1152a6b7db3Sskrll   e2->next = old_next;
1162a6b7db3Sskrll 
1172a6b7db3Sskrll   return class_element;
1182a6b7db3Sskrll }
1192a6b7db3Sskrll 
1202a6b7db3Sskrll /* Compare elements ELEM1 and ELEM2 from array of integers, given a
1212a6b7db3Sskrll    pointer to each.  Used to qsort such an array.  */
1222a6b7db3Sskrll 
1232a6b7db3Sskrll static int
elem_compare(const void * elem1,const void * elem2)1242a6b7db3Sskrll elem_compare (const void *elem1, const void *elem2)
1252a6b7db3Sskrll {
1262a6b7db3Sskrll   int e1 = * (const int *) elem1;
1272a6b7db3Sskrll   int e2 = * (const int *) elem2;
1282a6b7db3Sskrll   if (e1 < e2)
1292a6b7db3Sskrll     return -1;
1302a6b7db3Sskrll   else if (e1 > e2)
1312a6b7db3Sskrll     return 1;
1322a6b7db3Sskrll   else
1332a6b7db3Sskrll     return 0;
1342a6b7db3Sskrll }
1352a6b7db3Sskrll 
1362a6b7db3Sskrll /* Prints PART to the file pointer FP.  The elements of each
1372a6b7db3Sskrll    class are sorted.  */
1382a6b7db3Sskrll 
1392a6b7db3Sskrll void
partition_print(partition part,FILE * fp)1402a6b7db3Sskrll partition_print (partition part, FILE *fp)
1412a6b7db3Sskrll {
1422a6b7db3Sskrll   char *done;
1432a6b7db3Sskrll   int num_elements = part->num_elements;
1442a6b7db3Sskrll   struct partition_elem *elements = part->elements;
1452a6b7db3Sskrll   int *class_elements;
1462a6b7db3Sskrll   int e;
1472a6b7db3Sskrll 
1482a6b7db3Sskrll   /* Flag the elements we've already printed.  */
1492a6b7db3Sskrll   done = (char *) xmalloc (num_elements);
1502a6b7db3Sskrll   memset (done, 0, num_elements);
1512a6b7db3Sskrll 
1522a6b7db3Sskrll   /* A buffer used to sort elements in a class.  */
1532a6b7db3Sskrll   class_elements = (int *) xmalloc (num_elements * sizeof (int));
1542a6b7db3Sskrll 
1552a6b7db3Sskrll   fputc ('[', fp);
1562a6b7db3Sskrll   for (e = 0; e < num_elements; ++e)
1572a6b7db3Sskrll     /* If we haven't printed this element, print its entire class.  */
1582a6b7db3Sskrll     if (! done[e])
1592a6b7db3Sskrll       {
1602a6b7db3Sskrll 	int c = e;
1612a6b7db3Sskrll 	int count = elements[elements[e].class_element].class_count;
1622a6b7db3Sskrll 	int i;
1632a6b7db3Sskrll 
1642a6b7db3Sskrll       /* Collect the elements in this class.  */
1652a6b7db3Sskrll 	for (i = 0; i < count; ++i) {
1662a6b7db3Sskrll 	  class_elements[i] = c;
1672a6b7db3Sskrll 	  done[c] = 1;
1682a6b7db3Sskrll 	  c = elements[c].next - elements;
1692a6b7db3Sskrll 	}
1702a6b7db3Sskrll 	/* Sort them.  */
1712a6b7db3Sskrll 	qsort ((void *) class_elements, count, sizeof (int), elem_compare);
1722a6b7db3Sskrll 	/* Print them.  */
1732a6b7db3Sskrll 	fputc ('(', fp);
1742a6b7db3Sskrll 	for (i = 0; i < count; ++i)
1752a6b7db3Sskrll 	  fprintf (fp, i == 0 ? "%d" : " %d", class_elements[i]);
1762a6b7db3Sskrll 	fputc (')', fp);
1772a6b7db3Sskrll       }
1782a6b7db3Sskrll   fputc (']', fp);
1792a6b7db3Sskrll 
1802a6b7db3Sskrll   free (class_elements);
1812a6b7db3Sskrll   free (done);
1822a6b7db3Sskrll }
1832a6b7db3Sskrll 
184