1 changed files with 185 additions and 0 deletions
@ -0,0 +1,185 @@ |
|||
/* List implentation of a partition of consecutive integers.
|
|||
Copyright (C) 2000 Free Software Foundation, Inc. |
|||
Contributed by CodeSourcery, LLC. |
|||
|
|||
This file is part of GNU CC. |
|||
|
|||
GNU CC is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2, or (at your option) |
|||
any later version. |
|||
|
|||
GNU CC is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with GNU CC; see the file COPYING. If not, write to |
|||
the Free Software Foundation, 59 Temple Place - Suite 330, |
|||
Boston, MA 02111-1307, USA. */ |
|||
|
|||
#ifdef HAVE_CONFIG_H |
|||
#include "config.h" |
|||
#endif |
|||
|
|||
#ifdef HAVE_STDLIB_H |
|||
#include <stdlib.h> |
|||
#endif |
|||
|
|||
#include "libiberty.h" |
|||
#include "partition.h" |
|||
|
|||
/* Creates a partition of NUM_ELEMENTS elements. Initially each
|
|||
element is in a class by itself. */ |
|||
|
|||
partition |
|||
partition_new (num_elements) |
|||
int num_elements; |
|||
{ |
|||
int e; |
|||
|
|||
partition part = (partition) |
|||
xmalloc (sizeof (struct partition_def) + |
|||
(num_elements - 1) * sizeof (struct partition_elem)); |
|||
part->num_elements = num_elements; |
|||
for (e = 0; e < num_elements; ++e) |
|||
{ |
|||
part->elements[e].class_element = e; |
|||
part->elements[e].next = &(part->elements[e]); |
|||
part->elements[e].class_count = 1; |
|||
} |
|||
|
|||
return part; |
|||
} |
|||
|
|||
/* Freeds a partition. */ |
|||
|
|||
void |
|||
partition_delete (part) |
|||
partition part; |
|||
{ |
|||
free (part); |
|||
} |
|||
|
|||
/* Unites the classes containing ELEM1 and ELEM2 into a single class
|
|||
of partition PART. If ELEM1 and ELEM2 are already in the same |
|||
class, does nothing. Returns the canonical element of the |
|||
resulting union class. */ |
|||
|
|||
int |
|||
partition_union (part, elem1, elem2) |
|||
partition part; |
|||
int elem1; |
|||
int elem2; |
|||
{ |
|||
struct partition_elem *elements = part->elements; |
|||
struct partition_elem *e1; |
|||
struct partition_elem *e2; |
|||
struct partition_elem *p; |
|||
struct partition_elem *old_next; |
|||
/* The canonical element of the resulting union class. */ |
|||
int class_element = elements[elem1].class_element; |
|||
|
|||
/* If they're already in the same class, do nothing. */ |
|||
if (class_element == elements[elem2].class_element) |
|||
return class_element; |
|||
|
|||
/* Make sure ELEM1 is in the larger class of the two. If not, swap
|
|||
them. This way we always scan the shorter list. */ |
|||
if (elements[elem1].class_count < elements[elem2].class_count) |
|||
{ |
|||
int temp = elem1; |
|||
elem1 = elem2; |
|||
elem2 = temp; |
|||
class_element = elements[elem1].class_element; |
|||
} |
|||
|
|||
e1 = &(elements[elem1]); |
|||
e2 = &(elements[elem2]); |
|||
|
|||
/* Keep a count of the number of elements in the list. */ |
|||
elements[class_element].class_count |
|||
+= elements[e2->class_element].class_count; |
|||
|
|||
/* Update the class fields in elem2's class list. */ |
|||
e2->class_element = class_element; |
|||
for (p = e2->next; p != e2; p = p->next) |
|||
p->class_element = class_element; |
|||
|
|||
/* Splice ELEM2's class list into ELEM1's. These are circular
|
|||
lists. */ |
|||
old_next = e1->next; |
|||
e1->next = e2->next; |
|||
e2->next = old_next; |
|||
|
|||
return class_element; |
|||
} |
|||
|
|||
/* Compare elements ELEM1 and ELEM2 from array of integers, given a
|
|||
pointer to each. Used to qsort such an array. */ |
|||
|
|||
static int |
|||
elem_compare (elem1, elem2) |
|||
const void *elem1; |
|||
const void *elem2; |
|||
{ |
|||
int e1 = * (int *) elem1; |
|||
int e2 = * (int *) elem2; |
|||
if (e1 < e2) |
|||
return -1; |
|||
else if (e1 > e2) |
|||
return 1; |
|||
else |
|||
return 0; |
|||
} |
|||
|
|||
/* Prints PART to the file pointer FP. The elements of each
|
|||
class are sorted. */ |
|||
|
|||
void |
|||
partition_print (part, fp) |
|||
partition part; |
|||
FILE *fp; |
|||
{ |
|||
char *done; |
|||
int num_elements = part->num_elements; |
|||
struct partition_elem *elements = part->elements; |
|||
int *class_elements; |
|||
int e; |
|||
|
|||
/* Flag the elements we've already printed. */ |
|||
done = (char *) xmalloc (num_elements); |
|||
memset (done, 0, num_elements); |
|||
|
|||
/* A buffer used to sort elements in a class. */ |
|||
class_elements = (int *) xmalloc (num_elements * sizeof (int)); |
|||
|
|||
fputc ('[', fp); |
|||
for (e = 0; e < num_elements; ++e) |
|||
/* If we haven't printed this element, print its entire class. */ |
|||
if (! done[e]) |
|||
{ |
|||
int c = e; |
|||
int count = elements[elements[e].class_element].class_count; |
|||
int i; |
|||
|
|||
/* Collect the elements in this class. */ |
|||
for (i = 0; i < count; ++i) { |
|||
class_elements[i] = c; |
|||
done[c] = 1; |
|||
c = elements[c].next - elements; |
|||
} |
|||
/* Sort them. */ |
|||
qsort ((void *) class_elements, count, sizeof (int), &elem_compare); |
|||
/* Print them. */ |
|||
fputc ('(', fp); |
|||
for (i = 0; i < count; ++i) |
|||
fprintf (fp, i == 0 ? "%d" : " %d", class_elements[i]); |
|||
fputc (')', fp); |
|||
} |
|||
fputc (']', fp); |
|||
|
|||
free (done); |
|||
} |
|||
|
|||
Loading…
Reference in new issue