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