Commit 2f3cad5b authored by Florian Liekweg's avatar Florian Liekweg
Browse files

added qset

[r4275]
parent b4daf3f4
......@@ -15,12 +15,14 @@ srcdir = @srcdir@
topdir = ../..
subdir := ir/ana2
INSTALL_HEADERS = ecg.h irmemwalk.h lset.h typalise.h pto.h pto_util.h \
INSTALL_HEADERS = ecg.h irmemwalk.h lset.h typalise.h pto.h \
pto_init.h pto_util.h qset.h timing.h \
SOURCES = $(INSTALL_HEADERS)
SOURCES += Makefile.in \
ecg.c irmemwalk.c lset.c typalise.c pto.c pto_util.c
ecg.c irmemwalk.c lset.c typalise.c pto.c \
pto_init.c pto_util.c qset.c timing.c
include $(topdir)/MakeRules
......
/* -*- c -*- */
/*
* Time-stamp: <01.11.2004 19:45:58h liekweg>
* Project: libFIRM
* File name: ir/ana2/qset.c
* Purpose: yet another set implementation
* Author: Florian
* Modified by:
* Created: Mon 18 Oct 2004
* CVS-ID: $Id$
* Copyright: (c) 1999-2004 Universitt Karlsruhe
* Licence: This file is protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
# include <string.h>
# include <sys/time.h>
# include "timing.h"
# include "qset.h"
static __inline__ int sortable_compare (const void *pa, const void *pb)
{
const int a = * (unsigned int*) pa;
const int b = * (unsigned int*) pb;
if (a==b) {
return (0);
}
return ((a < b) ? -1 : +1);
}
/*
Allocate a list of sortables of the given length.
*/
static sortable_t *alloc_list (const int len)
{
sortable_t *values = (sortable_t*) malloc (len * sizeof (sortable_t));
memset (values, 0x00, len * sizeof (sortable_t));
return (values);
}
# ifdef UNSINN
/*
Create a list of sortables of the given length.
*/
static sortable_t *gen_list (const int len)
{
int i;
sortable_t *values = alloc_list (len);
for (i = 0; i < len; i ++) {
values [i] = rand () >> 16;
}
return (values);
}
# endif /* defined UNSINN */
/*
Helper to q_test --- return the index of val in values, or -1
*/
static int _q_test (sortable_t *values,
const sortable_t val,
const int lo, const int hi)
{
int mid;
/* fprintf (stdout, "%s for %d [%i:%i]\n", __FUNCTION__, val, lo, hi); */
if (lo == hi) {
if (EQUAL (val, values [lo])) {
return (lo);
} else {
return (-1);
}
}
if (COMPARE (val, values [lo])) {
/* too low */
return (-1);
}
if (COMPARE (values [hi], val)) {
/* too high */
return (-1);
}
mid = (hi + lo) / 2;
if (EQUAL (val, values [mid])) {
return (mid);
}
if (COMPARE (val, values [mid])) {
return (_q_test (values, val, lo, mid));
} else {
return (_q_test (values, val, mid+1, hi));
}
}
/*
Helper to q_sort
*/
static void _q_sort (sortable_t *values, const int lo, const int hi)
{
sortable_t pivot;
int p_lo;
int p_hi;
/* handle base case: */
if (lo >= hi) {
return;
}
if (1 == hi - lo) {
if (COMPARE (values [hi], values [lo])) {
sortable_t tmp = values [lo];
values [lo] = values [hi];
values [hi] = tmp;
}
return;
}
pivot = values [lo];
p_lo = lo+1;
p_hi = hi;
while (p_lo <= p_hi) {
if (COMPARE (values [p_lo], pivot)) {
values [p_lo-1] = values [p_lo];
p_lo ++;
} else {
sortable_t tmp = values [p_lo];
values [p_lo] = values [p_hi];
values [p_hi] = tmp;
p_hi --;
}
}
values [p_lo-1] = pivot;
_q_sort (values, lo, p_lo-1);
_q_sort (values, p_lo, hi);
}
# ifdef UNSINN
/*
Little test harness for q_sort and friends.
*/
static void test_qsort (const int n_runs, const int max_elems, const int incr)
{
int n_elems = 0;
int i;
fprintf (stdout, "# n_elems: q_sort time : libc qsort time\n");
while (n_elems <= max_elems) {
int total = 0;
int qtotal = 0;
for (i = 0; i < n_runs; i ++) {
sortable_t *list = gen_list (n_elems);
timing_t *timing = start_timing ();
q_sort (list, n_elems);
total += end_timing (timing);
q_check (list, n_elems);
free (list);
}
for (i = 0; i < n_runs; i ++) {
sortable_t *list = gen_list (n_elems);
timing_t *timing = start_timing ();
qsort (list, n_elems, sizeof (sortable_t), sortable_compare);
qtotal += end_timing (timing);
q_check (list, n_elems);
free (list);
}
fprintf (stdout, "%d %d %d\n", n_elems, total/n_runs, qtotal/n_runs);
fflush (stdout);
n_elems += incr;
}
fprintf (stdout, "\n");
}
/*
Little test harness for the qset implementation
*/
static void test_qset (const int n_entries)
{
int i;
int n1, n2, n;
qset_t *q1 = qset_new (n_entries);
qset_t *q2 = qset_new (n_entries);
qset_t *q = NULL;
sortable_t *values = gen_list (n_entries);
for (i = 0; i < n_entries; i ++) {
qset_insert (q1, values [i]);
qset_insert (q2, values [i]);
}
fprintf (stdout, "q1: \t\t");
qset_print (q1, stdout);
qset_sort (q1);
qset_sort (q2);
/* TEST */
q2->is_sorted = FALSE;
qset_sort (q2);
fprintf (stdout, "q1 (sorted):\t");
qset_print (q1, stdout);
assert (qset_compare (q1, q2));
q = qset_union (q1, q2);
fprintf (stdout, "qq (union):\t");
qset_print (q, stdout);
n1 = qset_size (q1);
n2 = qset_size (q2);
n = qset_size (q);
fprintf (stdout, "q1.size = %i\n", n1);
fprintf (stdout, "q1.slots = %i\n", q1->n_slots);
fprintf (stdout, "q2.size = %i\n", n2);
fprintf (stdout, "q2.slots = %i\n", q2->n_slots);
fprintf (stdout, "q.size = %i\n", n);
fprintf (stdout, "q.slots = %i\n", q->n_slots);
assert (n1 == n2);
assert (n2 == n);
assert (qset_compare (q1, q2));
assert (qset_compare (q2, q));
assert (qset_compare (q, q1));
for (i = 0; i < n_entries; i ++) {
assert (qset_contains (q1, values [i]));
assert (qset_contains (q2, values [i]));
assert (qset_contains (q, values [i]));
}
qset_compact (q1);
qset_compact (q);
fprintf (stdout, "q1.size = %i\n", n1);
fprintf (stdout, "q1.slots = %i\n", q1->n_slots);
fprintf (stdout, "q2.size = %i\n", n2);
fprintf (stdout, "q2.slots = %i\n", q2->n_slots);
fprintf (stdout, "q.size = %i\n", n);
fprintf (stdout, "q.slots = %i\n", q->n_slots);
assert (qset_compare (q1, q2));
assert (qset_compare (q2, q));
assert (qset_compare (q, q1));
for (i = 0; i < n_entries; i ++) {
assert (qset_contains (q1, values [i]));
assert (qset_contains (q2, values [i]));
assert (qset_contains (q, values [i]));
}
qset_delete (q);
qset_delete (q1);
qset_delete (q2);
}
# endif /* defned UNSINN */
/* PRIVATE QSET IMPLEMENTATION */
/*
Resize a qset to (at least) the given size.
*/
static void qset_resize (qset_t *qset, const int n_slots)
{
int new_size;
sortable_t *values = NULL;
if (qset->n_slots >= n_slots) {
return;
}
new_size = qset->n_slots;
while (new_size < n_slots) {
new_size *= 2;
}
values = alloc_list (new_size);
memcpy (values, qset->values, qset->n_elems * sizeof (sortable_t));
memset (qset->values, 0x00, qset->n_elems * sizeof (sortable_t)); /* debug only */
free (qset->values);
qset->values = values;
qset->n_slots = new_size;
}
/* PUBLIC INTERFACE */
/*
Print a list of sortables.
*/
void q_print (sortable_t *values, const int n_values, FILE *stream)
{
int i;
fprintf (stream, "{");
for (i = 0; i < n_values; i ++) {
if (0 == values [i]) {
fprintf (stream, "_");
} else {
fprintf (stream, "%d", (int) values [i]);
}
if (i + 1 != n_values) {
fprintf (stream, ", ");
}
}
fprintf (stream, "}\n");
}
/*
Check whether the given list of sortables is sorted.
*/
void q_check (sortable_t *values, const int n_values)
{
int i;
for (i = 1; i < n_values; i ++) {
assert (COMPARE (values [i-1], values [i]) ||
EQUAL (values [i-1], values [i]));
}
for (i = 1; i < n_values; i ++) {
assert (-1 != q_test (values, values [i], n_values));
}
}
/*
Test whether the given val is among values. Return the lowest index of val
in values, or -1.
*/
int q_test (sortable_t *values, const sortable_t val, const int n_elems)
{
int idx = _q_test (values, val, 0, n_elems-1);
while ((0 <= idx-1) && EQUAL (values [idx], val)) {
idx --;
}
return (idx);
}
/*
Sort entries in 'values' from index 'lo' to 'hi' (inclusive)
*/
void q_sort (sortable_t *values, const int n_elems)
{
_q_sort (values, 0, n_elems-1);
}
/*
Merge two sorted lists. Keep duplicates (if present)
*/
sortable_t *q_merge (sortable_t *list1, const int n1_elems,
sortable_t *list2, const int n2_elems)
{
const int n_elems = n1_elems + n2_elems;
sortable_t *res = alloc_list (n_elems);
int i1 = 0;
int i2 = 0;
int i = 0;
while ((i < n_elems) && (i1 < n1_elems) && (i2 < n2_elems)) {
if (COMPARE (list1 [i1], list2 [i2])) {
res [i ++] = list1 [i1 ++];
} else {
res [i ++] = list2 [i2 ++];
}
}
while (i1 < n1_elems) {
res [i ++] = list1 [i1 ++];
}
while (i2 < n2_elems) {
res [i ++] = list2 [i2 ++];
}
return (res);
}
/*
Allocate a new qset with initial space for up to n_elems.
*/
qset_t *qset_new (const int n_elems)
{
qset_t *qset = (qset_t*) malloc (sizeof (qset_t));
qset->values = alloc_list (n_elems);
memset (qset->values, 0x00, n_elems * sizeof (sortable_t));
qset->n_slots = n_elems;
qset->n_elems = 0;
qset->is_sorted = FALSE;
return (qset);
}
/*
Sort the entries of the given qset.
*/
void qset_sort (qset_t *qset)
{
int occ = 0;
int i;
if (qset->is_sorted) {
return;
}
q_sort (qset->values, qset->n_elems);
for (i = 1; i < qset->n_elems; i ++) {
if (! EQUAL (qset->values [i], qset->values [occ])) {
qset->values [++ occ] = qset->values [i];
}
}
occ ++;
/*
if (qset->n_elems != occ) {
fprintf (stdout, "removed %i duplicates\n", qset->n_elems - occ);
}*/
qset->n_elems = occ;
qset->is_sorted = TRUE;
}
/*
Compact a qset to take up no more space than required.
*/
void qset_compact (qset_t *qset)
{
sortable_t *values = (sortable_t*) malloc (qset->n_elems * sizeof (sortable_t));
memcpy (values, qset->values, qset->n_elems * sizeof (sortable_t));
memset (qset->values, 0x00, qset->n_elems * sizeof (sortable_t));
free (qset->values);
qset->values = values;
qset->n_slots = qset->n_elems;
}
/*
Free the memory associated with the given qset
*/
void qset_delete (qset_t *qset)
{
memset (qset->values, 0x00, qset->n_elems * sizeof (sortable_t));
free (qset->values);
memset (qset, 0x00, sizeof (qset_t));
free (qset);
}
/*
Test wether the given qset contains the given value.
*/
int qset_contains (qset_t *qset, sortable_t val)
{
qset_sort (qset);
return (-1 != q_test (qset->values, val, qset->n_elems));
}
/*
Delete the given value from the given qset (if it exists)
*/
void qset_remove (qset_t *qset, sortable_t val)
{
int idx;
int occ = 0;
int i;
qset_sort (qset);
idx = q_test (qset->values, val, qset->n_elems);
if (-1 == idx) {
return;
}
while (EQUAL (qset->values [idx + occ], val)) {
occ ++;
}
for (i = idx; i < qset->n_elems - occ; i ++) {
qset->values [i] = qset->values [i+occ];
}
qset->n_elems -= occ;
}
/*
Insert the given elem into the given qset.
*/
void qset_insert (qset_t *qset, sortable_t val)
{
/* TODO: sort, find */
/* or check for duplicates */
qset_resize (qset, qset->n_elems+1);
qset->values [qset->n_elems++] = val;
qset->is_sorted = FALSE;
}
/*
Insert all elems of qset2 into qset1. qset2 is *not* deleted.
*/
void qset_insert_all (qset_t *qset1, qset_t *qset2)
{
sortable_t *values = qset1->values;
const int n_elems = qset1->n_slots;
qset_sort (qset1);
qset_sort (qset2);
qset1->values = q_merge (qset1->values, qset1->n_elems,
qset2->values, qset2->n_elems);
qset1->n_elems = qset1->n_elems + qset2->n_elems;
qset1->n_slots = qset1->n_elems;
qset_sort (qset1);
memset (values, 0x00, n_elems * sizeof (sortable_t));
free (values);
}
/*
Compare two qsets.
*/
int qset_compare (qset_t *qset1, qset_t *qset2)
{
int i;
const int n_elems = qset1->n_elems;
qset_sort (qset1);
qset_sort (qset2);
if (qset1->n_elems != qset2->n_elems) {
return (FALSE);
}
for (i = 0; i < n_elems; i ++) {
if (qset1->values [i] != qset2->values [i]) {
return (FALSE);
}
}
return (TRUE);
}
/*
Returns the union of two qsets.
*/
qset_t *qset_union (qset_t *qset1, qset_t *qset2)
{
qset_t *qset = (qset_t*) malloc (sizeof (qset_t));
const int n_elems = qset1->n_elems + qset2->n_elems;
qset->values = alloc_list (n_elems);
memcpy (qset->values, qset1->values,
qset1->n_elems * sizeof (sortable_t));
memcpy (qset->values+qset1->n_elems,
qset2->values, qset2->n_elems * sizeof (sortable_t));
qset->n_elems = n_elems;
qset->n_slots = qset->n_elems;
qset_sort (qset);