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