added qset
authorFlorian Liekweg <liekweg@ipd.info.uni-karlsruhe.de>
Thu, 4 Nov 2004 14:55:13 +0000 (14:55 +0000)
committerFlorian Liekweg <liekweg@ipd.info.uni-karlsruhe.de>
Thu, 4 Nov 2004 14:55:13 +0000 (14:55 +0000)
[r4275]

ir/ana2/Makefile.in
ir/ana2/qset.c [new file with mode: 0644]
ir/ana2/qset.h [new file with mode: 0644]

index deeda8d..beec601 100644 (file)
@@ -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
 
diff --git a/ir/ana2/qset.c b/ir/ana2/qset.c
new file mode 100644 (file)
index 0000000..9d539d1
--- /dev/null
@@ -0,0 +1,686 @@
+/* -*- 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 Universität 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);
+
+  return (qset);
+}
+
+/*
+  Report the size of the given qset.
+*/
+int qset_size (qset_t *qset)
+{
+  return (qset->n_elems);
+}
+
+/*
+  Print the given qset to the given stream.
+*/
+void qset_print (qset_t *qset, FILE *stream)
+{
+  q_print (qset->values, qset->n_elems, stream);
+}
+
+/*
+  Initialise a new iteration over a qset
+*/
+sortable_t *qset_start (qset_t *qset)
+{
+  qset->cursor = 0;
+
+  return (qset_next (qset));    /* works for empty sets, too */
+}
+
+/*
+  Step to the next element
+*/
+sortable_t *qset_next (qset_t *qset)
+{
+  if (qset->n_elems == qset->cursor) {
+    return (NULL);
+  }
+
+  return (qset->values [qset->cursor++]);
+}
+
+
+# ifdef UNSINN
+int qset_test_main (int argc, char **argv)
+{
+  struct timeval tp;
+  unsigned int seed;
+
+  if (-1 == gettimeofday (&tp, NULL)) {
+    perror ("gettimeofday");
+    exit (EXIT_FAILURE);
+  }
+
+  seed = (unsigned int) tp.tv_usec;
+  srand (seed);
+
+  /* test_qsort (20, 1000000, 100000); */
+
+  test_qset (atoi (argv [1]));
+
+  exit (EXIT_SUCCESS);
+}
+# endif /* defined UNSINN */
+
+/*
+  $Log$
+  Revision 1.1  2004/11/04 14:55:13  liekweg
+  added qset
+
+
+ */
diff --git a/ir/ana2/qset.h b/ir/ana2/qset.h
new file mode 100644 (file)
index 0000000..8e9710a
--- /dev/null
@@ -0,0 +1,112 @@
+/* -*- c -*- */
+
+/*
+ * Time-stamp: <31.10.2004 22:36:22h liekweg>
+ * Project:     libFIRM
+ * File name:   ir/ana2/qset.h
+ * Purpose:     yet another set implementation
+ * Author:      Florian
+ * Modified by:
+ * Created:     Mon 18 Oct 2004
+ * CVS-ID:      $Id$
+ * Copyright:   (c) 1999-2004 Universität Karlsruhe
+ * Licence:     This file is protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
+
+#ifndef _QSET_H_
+#define _QSET_H_
+
+# ifndef TRUE
+#  define TRUE 1
+#  define FALSE 0
+# endif /* nof defined TRUE */
+
+/* define this as needed */
+# define COMPARE(A,B)       (A<B)
+# define EQUAL(A,B)       (A==B)
+/* typedef unsigned int sortable_t; */
+typedef void* sortable_t;
+
+typedef struct qset_str
+{
+  sortable_t *values;
+  int n_slots;
+  int n_elems;
+  int is_sorted;
+  int cursor;                   /* for qset_start/qset_next */
+} qset_t;
+
+/* QSET INTERFACE */
+/* Print a list of sortables. */
+void q_print (sortable_t*, const int, FILE*);
+
+/* Check whether the given list of sortables is sorted. */
+void q_check (sortable_t*, const int);
+
+/* Test whether the given val is among values.  Return the index of
+   val in values, or -1. */
+int q_test (sortable_t*, const sortable_t, const int);
+
+/* Sort n_elems entries  in 'values' */
+void q_sort (sortable_t*, const int);
+
+/* Merge two sorted lists */
+sortable_t *q_merge (sortable_t*, const int,
+                     sortable_t*, const int);
+
+
+/* QSET INTERFACE */
+
+/* Allocate a new qset with initial space for up to n_elems. */
+qset_t *qset_new (const int);
+
+/* Sort the entries of the given qset. */
+void qset_sort (qset_t*);
+
+/* Compact a qset to take up no more space than required. */
+void qset_compact (qset_t*);
+
+/* Free the memory associated with the given qset */
+void qset_delete (qset_t*);
+
+/* Test whether the given qset contains the given value. */
+int qset_contains (qset_t*, sortable_t);
+
+/* Delete the given value from the given qset (if it exists) */
+void qset_remove (qset_t*, sortable_t);
+
+/* Insert the given elem into the given qset. */
+void qset_insert (qset_t*, sortable_t);
+
+/* Insert all elems of qset2 into qset1. qset2 is deleted. */
+void qset_insert_all (qset_t*, qset_t*);
+
+/* Compare two qsets. */
+int qset_compare (qset_t*, qset_t*);
+
+/* Returns the union of two qsets. */
+qset_t *qset_union (qset_t *qset1, qset_t *qset2);
+
+/* Report the size of the given qset. */
+int qset_size (qset_t *qset);
+
+/* Print the given qset to the given stream. */
+void qset_print (qset_t*, FILE*);
+
+/*
+   Iterate over a qset
+*/
+/* initialise the iteration, return the first element */
+sortable_t *qset_start (qset_t*);
+/* step to the next element, return NULL iff no more elems are available */
+sortable_t *qset_next (qset_t*);
+
+#endif /* def _QSET_H_ */
+
+/*
+ $Log$
+ Revision 1.1  2004/11/04 14:55:13  liekweg
+ added qset
+
+
+*/