Home | History | Annotate | Line # | Download | only in libiberty
      1   1.1  christos /* List implementation of a partition of consecutive integers.
      2  1.10  christos    Copyright (C) 2000-2025 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