198b9484cSchristos /* List implementation of a partition of consecutive integers. 2*5173eb0aSchristos Copyright (C) 2000-2024 Free Software Foundation, Inc. 398b9484cSchristos Contributed by CodeSourcery, LLC. 498b9484cSchristos 598b9484cSchristos This file is part of GNU CC. 698b9484cSchristos 798b9484cSchristos GNU CC is free software; you can redistribute it and/or modify 898b9484cSchristos it under the terms of the GNU General Public License as published by 998b9484cSchristos the Free Software Foundation; either version 2, or (at your option) 1098b9484cSchristos any later version. 1198b9484cSchristos 1298b9484cSchristos GNU CC is distributed in the hope that it will be useful, 1398b9484cSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 1498b9484cSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1598b9484cSchristos GNU General Public License for more details. 1698b9484cSchristos 1798b9484cSchristos You should have received a copy of the GNU General Public License 1898b9484cSchristos along with GNU CC; see the file COPYING. If not, write to 1998b9484cSchristos the Free Software Foundation, 51 Franklin Street - Fifth Floor, 2098b9484cSchristos Boston, MA 02110-1301, USA. */ 2198b9484cSchristos 2298b9484cSchristos #ifdef HAVE_CONFIG_H 2398b9484cSchristos #include "config.h" 2498b9484cSchristos #endif 2598b9484cSchristos 2698b9484cSchristos #ifdef HAVE_STDLIB_H 2798b9484cSchristos #include <stdlib.h> 2898b9484cSchristos #endif 2998b9484cSchristos 3098b9484cSchristos #ifdef HAVE_STRING_H 3198b9484cSchristos #include <string.h> 3298b9484cSchristos #endif 3398b9484cSchristos 3498b9484cSchristos #include "libiberty.h" 3598b9484cSchristos #include "partition.h" 3698b9484cSchristos 3798b9484cSchristos static int elem_compare (const void *, const void *); 3898b9484cSchristos 3998b9484cSchristos /* Creates a partition of NUM_ELEMENTS elements. Initially each 4098b9484cSchristos element is in a class by itself. */ 4198b9484cSchristos 4298b9484cSchristos partition 4398b9484cSchristos partition_new (int num_elements) 4498b9484cSchristos { 4598b9484cSchristos int e; 4698b9484cSchristos 4798b9484cSchristos partition part = (partition) 4898b9484cSchristos xmalloc (sizeof (struct partition_def) + 4998b9484cSchristos (num_elements - 1) * sizeof (struct partition_elem)); 5098b9484cSchristos part->num_elements = num_elements; 5198b9484cSchristos for (e = 0; e < num_elements; ++e) 5298b9484cSchristos { 5398b9484cSchristos part->elements[e].class_element = e; 5498b9484cSchristos part->elements[e].next = &(part->elements[e]); 5598b9484cSchristos part->elements[e].class_count = 1; 5698b9484cSchristos } 5798b9484cSchristos 5898b9484cSchristos return part; 5998b9484cSchristos } 6098b9484cSchristos 6198b9484cSchristos /* Freeds a partition. */ 6298b9484cSchristos 6398b9484cSchristos void 6498b9484cSchristos partition_delete (partition part) 6598b9484cSchristos { 6698b9484cSchristos free (part); 6798b9484cSchristos } 6898b9484cSchristos 6998b9484cSchristos /* Unites the classes containing ELEM1 and ELEM2 into a single class 7098b9484cSchristos of partition PART. If ELEM1 and ELEM2 are already in the same 7198b9484cSchristos class, does nothing. Returns the canonical element of the 7298b9484cSchristos resulting union class. */ 7398b9484cSchristos 7498b9484cSchristos int 7598b9484cSchristos partition_union (partition part, int elem1, int elem2) 7698b9484cSchristos { 7798b9484cSchristos struct partition_elem *elements = part->elements; 7898b9484cSchristos struct partition_elem *e1; 7998b9484cSchristos struct partition_elem *e2; 8098b9484cSchristos struct partition_elem *p; 8198b9484cSchristos struct partition_elem *old_next; 8298b9484cSchristos /* The canonical element of the resulting union class. */ 8398b9484cSchristos int class_element = elements[elem1].class_element; 8498b9484cSchristos 8598b9484cSchristos /* If they're already in the same class, do nothing. */ 8698b9484cSchristos if (class_element == elements[elem2].class_element) 8798b9484cSchristos return class_element; 8898b9484cSchristos 8998b9484cSchristos /* Make sure ELEM1 is in the larger class of the two. If not, swap 9098b9484cSchristos them. This way we always scan the shorter list. */ 9198b9484cSchristos if (elements[elem1].class_count < elements[elem2].class_count) 9298b9484cSchristos { 9398b9484cSchristos int temp = elem1; 9498b9484cSchristos elem1 = elem2; 9598b9484cSchristos elem2 = temp; 9698b9484cSchristos class_element = elements[elem1].class_element; 9798b9484cSchristos } 9898b9484cSchristos 9998b9484cSchristos e1 = &(elements[elem1]); 10098b9484cSchristos e2 = &(elements[elem2]); 10198b9484cSchristos 10298b9484cSchristos /* Keep a count of the number of elements in the list. */ 10398b9484cSchristos elements[class_element].class_count 10498b9484cSchristos += elements[e2->class_element].class_count; 10598b9484cSchristos 10698b9484cSchristos /* Update the class fields in elem2's class list. */ 10798b9484cSchristos e2->class_element = class_element; 10898b9484cSchristos for (p = e2->next; p != e2; p = p->next) 10998b9484cSchristos p->class_element = class_element; 11098b9484cSchristos 11198b9484cSchristos /* Splice ELEM2's class list into ELEM1's. These are circular 11298b9484cSchristos lists. */ 11398b9484cSchristos old_next = e1->next; 11498b9484cSchristos e1->next = e2->next; 11598b9484cSchristos e2->next = old_next; 11698b9484cSchristos 11798b9484cSchristos return class_element; 11898b9484cSchristos } 11998b9484cSchristos 12098b9484cSchristos /* Compare elements ELEM1 and ELEM2 from array of integers, given a 12198b9484cSchristos pointer to each. Used to qsort such an array. */ 12298b9484cSchristos 12398b9484cSchristos static int 12498b9484cSchristos elem_compare (const void *elem1, const void *elem2) 12598b9484cSchristos { 12698b9484cSchristos int e1 = * (const int *) elem1; 12798b9484cSchristos int e2 = * (const int *) elem2; 12898b9484cSchristos if (e1 < e2) 12998b9484cSchristos return -1; 13098b9484cSchristos else if (e1 > e2) 13198b9484cSchristos return 1; 13298b9484cSchristos else 13398b9484cSchristos return 0; 13498b9484cSchristos } 13598b9484cSchristos 13698b9484cSchristos /* Prints PART to the file pointer FP. The elements of each 13798b9484cSchristos class are sorted. */ 13898b9484cSchristos 13998b9484cSchristos void 14098b9484cSchristos partition_print (partition part, FILE *fp) 14198b9484cSchristos { 14298b9484cSchristos char *done; 14398b9484cSchristos int num_elements = part->num_elements; 14498b9484cSchristos struct partition_elem *elements = part->elements; 14598b9484cSchristos int *class_elements; 14698b9484cSchristos int e; 14798b9484cSchristos 14898b9484cSchristos /* Flag the elements we've already printed. */ 14998b9484cSchristos done = (char *) xmalloc (num_elements); 15098b9484cSchristos memset (done, 0, num_elements); 15198b9484cSchristos 15298b9484cSchristos /* A buffer used to sort elements in a class. */ 15398b9484cSchristos class_elements = (int *) xmalloc (num_elements * sizeof (int)); 15498b9484cSchristos 15598b9484cSchristos fputc ('[', fp); 15698b9484cSchristos for (e = 0; e < num_elements; ++e) 15798b9484cSchristos /* If we haven't printed this element, print its entire class. */ 15898b9484cSchristos if (! done[e]) 15998b9484cSchristos { 16098b9484cSchristos int c = e; 16198b9484cSchristos int count = elements[elements[e].class_element].class_count; 16298b9484cSchristos int i; 16398b9484cSchristos 16498b9484cSchristos /* Collect the elements in this class. */ 16598b9484cSchristos for (i = 0; i < count; ++i) { 16698b9484cSchristos class_elements[i] = c; 16798b9484cSchristos done[c] = 1; 16898b9484cSchristos c = elements[c].next - elements; 16998b9484cSchristos } 17098b9484cSchristos /* Sort them. */ 17198b9484cSchristos qsort ((void *) class_elements, count, sizeof (int), elem_compare); 17298b9484cSchristos /* Print them. */ 17398b9484cSchristos fputc ('(', fp); 17498b9484cSchristos for (i = 0; i < count; ++i) 17598b9484cSchristos fprintf (fp, i == 0 ? "%d" : " %d", class_elements[i]); 17698b9484cSchristos fputc (')', fp); 17798b9484cSchristos } 17898b9484cSchristos fputc (']', fp); 17998b9484cSchristos 18098b9484cSchristos free (class_elements); 18198b9484cSchristos free (done); 18298b9484cSchristos } 18398b9484cSchristos 184