Home | History | Annotate | Line # | Download | only in libiberty
      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